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 {
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
}

View File

@ -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

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() {
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()
}

View File

@ -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
}

View File

@ -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())
}

View File

@ -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)
}
}