From 5414fbfac80611c285c9b949d71f7eb282d81bdd Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Thu, 18 Jul 2024 17:46:36 +0800 Subject: [PATCH] :sparkles: Interactable object! --- pkg/internal/land/object.go | 6 +++ pkg/internal/land/object_collision.go | 10 +++++ pkg/internal/land/object_interactable.go | 7 +++ pkg/internal/land/root.go | 56 ++++++++++++++++++++---- pkg/internal/land/vector2d.go | 6 +++ pkg/internal/tiles/tile.go | 5 +++ pkg/main.go | 4 +- 7 files changed, 84 insertions(+), 10 deletions(-) create mode 100644 pkg/internal/land/object_interactable.go diff --git a/pkg/internal/land/object.go b/pkg/internal/land/object.go index 9f79f3d..0b543d8 100644 --- a/pkg/internal/land/object.go +++ b/pkg/internal/land/object.go @@ -5,6 +5,8 @@ import "github.com/veandco/go-sdl2/sdl" type Object interface { Create() Update() + AddChild(child Object) + GetChildren() []Object } type DrawableObject interface { @@ -27,3 +29,7 @@ func (p *BaseObject) Update() { func (p *BaseObject) AddChild(child Object) { p.Children = append(p.Children, child) } + +func (p *BaseObject) GetChildren() []Object { + return p.Children +} diff --git a/pkg/internal/land/object_collision.go b/pkg/internal/land/object_collision.go index 71d49ee..af3dc86 100644 --- a/pkg/internal/land/object_collision.go +++ b/pkg/internal/land/object_collision.go @@ -1,5 +1,15 @@ package land +type PositionedObject interface { + GetPosition() Vector2D + GetSize() Vector2D +} + +func IsOverlapWithPoint(obj PositionedObject, point Vector2D) bool { + return point.X >= obj.GetPosition().X && point.X <= obj.GetPosition().X+obj.GetSize().X && + point.Y >= obj.GetPosition().Y && point.Y <= obj.GetPosition().Y+obj.GetSize().Y +} + type CollidableObject interface { GetPosition() Vector2D GetSize() Vector2D diff --git a/pkg/internal/land/object_interactable.go b/pkg/internal/land/object_interactable.go new file mode 100644 index 0000000..c1f60ba --- /dev/null +++ b/pkg/internal/land/object_interactable.go @@ -0,0 +1,7 @@ +package land + +type InteractableObject interface { + GetPosition() Vector2D + GetSize() Vector2D + OnClick(mousePos Vector2D) +} diff --git a/pkg/internal/land/root.go b/pkg/internal/land/root.go index d21196a..364950b 100644 --- a/pkg/internal/land/root.go +++ b/pkg/internal/land/root.go @@ -35,26 +35,60 @@ func (p *RootObject) RunEventLoop(tickDuration time.Duration) { } } +func (p *RootObject) ForEachChildren(cb func(child Object)) { + var caller func(current Object) + + caller = func(current Object) { + cb(current) + for _, child := range current.GetChildren() { + caller(child) + } + } + + caller(p) +} + +func (p *RootObject) HandleUserEvent(event sdl.Event) { + switch event := event.(type) { + case *sdl.MouseButtonEvent: + if event.Type == sdl.MOUSEBUTTONDOWN { + x, y := float64(event.X), float64(event.Y) + vec := Vector2D{x, y} + p.ForEachChildren(func(child Object) { + if interChild, ok := child.(InteractableObject); ok { + isOverlap := IsOverlapWithPoint(child.(PositionedObject), vec) + if isOverlap { + interChild.OnClick(vec) + } + } + }) + } + } +} + func (p *RootObject) Update() { p.BaseObject.Update() // Check collision - for _, child := range p.Children { - for _, other := range p.Children { + p.ForEachChildren(func(child Object) { + p.ForEachChildren(func(other Object) { + if child == other { + return + } collidableChild, ok := child.(CollidableObject) if !ok { - continue + return } collidableOther, ok := other.(CollidableObject) if !ok { - continue + return } - if child != other && checkCollisionBetweenObject(collidableChild, collidableOther) { + if checkCollisionBetweenObject(collidableChild, collidableOther) { collidableChild.OnCollide(collidableOther) collidableOther.OnCollide(collidableChild) } - } - } + }) + }) p.Analyzer.Tick() } @@ -65,11 +99,15 @@ func (p *RootObject) Draw(pen *sdl.Renderer) { pen.Clear() // Render each child - for _, child := range p.Children { + p.ForEachChildren(func(child Object) { + if child == p { + // Skip the current to prevent infinite drawing + return + } if drawableChild, ok := child.(DrawableObject); ok { drawableChild.Draw(pen) } - } + }) p.Analyzer.Draw() } diff --git a/pkg/internal/land/vector2d.go b/pkg/internal/land/vector2d.go index 459f826..f414ddd 100644 --- a/pkg/internal/land/vector2d.go +++ b/pkg/internal/land/vector2d.go @@ -1,9 +1,15 @@ package land +import "fmt" + type Vector2D struct { X, Y float64 } +func (p Vector2D) String() string { + return fmt.Sprintf("(%.2f, %.2f)", p.X, p.Y) +} + func (p Vector2D) IsZero() bool { return p.X == 0 && p.Y == 0 } diff --git a/pkg/internal/tiles/tile.go b/pkg/internal/tiles/tile.go index a18e316..7a743c6 100644 --- a/pkg/internal/tiles/tile.go +++ b/pkg/internal/tiles/tile.go @@ -3,6 +3,7 @@ package tiles import ( "git.solsynth.dev/highland/codingland/pkg/internal/land" "github.com/veandco/go-sdl2/sdl" + "log" ) type Tile struct { @@ -38,3 +39,7 @@ func (p *Tile) GetSize() land.Vector2D { func (p *Tile) OnCollide(other land.CollidableObject) { } + +func (p *Tile) OnClick(mousePos land.Vector2D) { + log.Printf("user clicked tile: %s", mousePos.String()) +} diff --git a/pkg/main.go b/pkg/main.go index 2a6a1b6..9634110 100644 --- a/pkg/main.go +++ b/pkg/main.go @@ -44,7 +44,7 @@ func main() { Size: land.Vector2D{X: 50, Y: 50}, }) root.AddChild(&tiles.Tile{ - Position: land.Vector2D{X: 25, Y: 25}, + Position: land.Vector2D{X: 50, Y: 50}, Size: land.Vector2D{X: 50, Y: 50}, }) @@ -57,6 +57,8 @@ func main() { switch event.(type) { case *sdl.QuitEvent: running = false + case *sdl.MouseButtonEvent: + root.HandleUserEvent(event) } }