Interactable object!

This commit is contained in:
LittleSheep 2024-07-18 17:46:36 +08:00
parent 9025859fac
commit 5414fbfac8
7 changed files with 84 additions and 10 deletions

View File

@ -5,6 +5,8 @@ import "github.com/veandco/go-sdl2/sdl"
type Object interface { type Object interface {
Create() Create()
Update() Update()
AddChild(child Object)
GetChildren() []Object
} }
type DrawableObject interface { type DrawableObject interface {
@ -27,3 +29,7 @@ func (p *BaseObject) Update() {
func (p *BaseObject) AddChild(child Object) { func (p *BaseObject) AddChild(child Object) {
p.Children = append(p.Children, child) p.Children = append(p.Children, child)
} }
func (p *BaseObject) GetChildren() []Object {
return p.Children
}

View File

@ -1,5 +1,15 @@
package land 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 { type CollidableObject interface {
GetPosition() Vector2D GetPosition() Vector2D
GetSize() Vector2D GetSize() Vector2D

View File

@ -0,0 +1,7 @@
package land
type InteractableObject interface {
GetPosition() Vector2D
GetSize() Vector2D
OnClick(mousePos Vector2D)
}

View File

@ -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() { func (p *RootObject) Update() {
p.BaseObject.Update() p.BaseObject.Update()
// Check collision // Check collision
for _, child := range p.Children { p.ForEachChildren(func(child Object) {
for _, other := range p.Children { p.ForEachChildren(func(other Object) {
if child == other {
return
}
collidableChild, ok := child.(CollidableObject) collidableChild, ok := child.(CollidableObject)
if !ok { if !ok {
continue return
} }
collidableOther, ok := other.(CollidableObject) collidableOther, ok := other.(CollidableObject)
if !ok { if !ok {
continue return
} }
if child != other && checkCollisionBetweenObject(collidableChild, collidableOther) { if checkCollisionBetweenObject(collidableChild, collidableOther) {
collidableChild.OnCollide(collidableOther) collidableChild.OnCollide(collidableOther)
collidableOther.OnCollide(collidableChild) collidableOther.OnCollide(collidableChild)
} }
} })
} })
p.Analyzer.Tick() p.Analyzer.Tick()
} }
@ -65,11 +99,15 @@ func (p *RootObject) Draw(pen *sdl.Renderer) {
pen.Clear() pen.Clear()
// Render each child // 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 { if drawableChild, ok := child.(DrawableObject); ok {
drawableChild.Draw(pen) drawableChild.Draw(pen)
} }
} })
p.Analyzer.Draw() p.Analyzer.Draw()
} }

View File

@ -1,9 +1,15 @@
package land package land
import "fmt"
type Vector2D struct { type Vector2D struct {
X, Y float64 X, Y float64
} }
func (p Vector2D) String() string {
return fmt.Sprintf("(%.2f, %.2f)", p.X, p.Y)
}
func (p Vector2D) IsZero() bool { func (p Vector2D) IsZero() bool {
return p.X == 0 && p.Y == 0 return p.X == 0 && p.Y == 0
} }

View File

@ -3,6 +3,7 @@ package tiles
import ( import (
"git.solsynth.dev/highland/codingland/pkg/internal/land" "git.solsynth.dev/highland/codingland/pkg/internal/land"
"github.com/veandco/go-sdl2/sdl" "github.com/veandco/go-sdl2/sdl"
"log"
) )
type Tile struct { type Tile struct {
@ -38,3 +39,7 @@ func (p *Tile) GetSize() land.Vector2D {
func (p *Tile) OnCollide(other land.CollidableObject) { func (p *Tile) OnCollide(other land.CollidableObject) {
} }
func (p *Tile) OnClick(mousePos land.Vector2D) {
log.Printf("user clicked tile: %s", mousePos.String())
}

View File

@ -44,7 +44,7 @@ func main() {
Size: land.Vector2D{X: 50, Y: 50}, Size: land.Vector2D{X: 50, Y: 50},
}) })
root.AddChild(&tiles.Tile{ 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}, Size: land.Vector2D{X: 50, Y: 50},
}) })
@ -57,6 +57,8 @@ func main() {
switch event.(type) { switch event.(type) {
case *sdl.QuitEvent: case *sdl.QuitEvent:
running = false running = false
case *sdl.MouseButtonEvent:
root.HandleUserEvent(event)
} }
} }