✨ Interactable object!
This commit is contained in:
		| @@ -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 | ||||
| } | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
							
								
								
									
										7
									
								
								pkg/internal/land/object_interactable.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								pkg/internal/land/object_interactable.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| package land | ||||
|  | ||||
| type InteractableObject interface { | ||||
| 	GetPosition() Vector2D | ||||
| 	GetSize() Vector2D | ||||
| 	OnClick(mousePos Vector2D) | ||||
| } | ||||
| @@ -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() | ||||
| } | ||||
|   | ||||
| @@ -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 | ||||
| } | ||||
|   | ||||
| @@ -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()) | ||||
| } | ||||
|   | ||||
| @@ -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) | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user