doodle/pkg/collision/actor_offset.go

82 lines
2.2 KiB
Go

package collision
import "git.kirsle.net/go/render"
// ActorOffset helps normalize an actor's Position and Hitbox for collision detection.
//
// It allows for an actor to have a Hitbox which is offset from the 0,0 coordinate
// in the top left corner. During gameplay, the actor's Position (top left corner of
// its *sprite*) is what the game tracks for movement, but if the actor's declared hitbox
// doesn't encompass the point 0,0 it used to lead to collision bugs.
//
// ActorOffset will take your original Actor, compute the offset between its Position
// and its Hitbox, and return a simplified Actor that pretends the hitbox begins at 0,0.
type ActorOffset struct {
d Actor
offset render.Point
}
// NewActorOffset consumes the game's original Actor and returns one that simplifies
// the Hitbox boundary.
func NewActorOffset(d Actor) *ActorOffset {
// Compute the offset from the actor's Position to its Hitbox.
var (
position = d.Position()
hitbox = d.Hitbox()
delta = render.Point{
X: position.X + hitbox.X,
Y: position.Y + hitbox.Y,
}
offset = render.Point{
X: delta.X - position.X,
Y: delta.Y - position.Y,
}
)
return &ActorOffset{
d: d,
offset: offset,
}
}
// Offset returns the offset from the source actor's Position to their new one.
func (ao *ActorOffset) Offset() render.Point {
return ao.offset
}
// Position will be the actor's original world position (of its sprite) plus the
// hitbox offset coordinate.
func (ao *ActorOffset) Position() render.Point {
var P = ao.d.Position()
return render.Point{
X: P.X + ao.offset.X,
Y: P.Y + ao.offset.Y,
}
}
// Size is the same as your original Actor.
func (ao *ActorOffset) Size() render.Rect {
return ao.d.Size()
}
// Hitbox returns the actor's original Hitbox but where the X,Y are locked to 0,0.
// The W,H of the hitbox is the same as original.
func (ao *ActorOffset) Hitbox() render.Rect {
var HB = ao.d.Hitbox()
return render.Rect{
X: 0,
Y: 0,
H: HB.H,
W: HB.W,
}
}
// Grounded returns your original actor's value.
func (ao *ActorOffset) Grounded() bool {
return ao.d.Grounded()
}
// SetGrounded sets the grounded state of your original actor.
func (ao *ActorOffset) SetGrounded(v bool) {
ao.d.SetGrounded(v)
}