openquell/components/position.go

117 lines
2.5 KiB
Go

package components
import (
"fmt"
"image"
"log/slog"
. "openquell/config"
)
// physical location on screen
type Position struct {
X int
Y int
Cellsize int
Rect *image.Rectangle
}
func (position *Position) Update(x, y int, size ...int) {
if len(size) == 1 {
position.Cellsize = size[0]
}
position.X = x
position.Y = y
rect := image.Rect(x, y, x+position.Cellsize, y+position.Cellsize)
position.Rect = &rect
}
func NewPosition(point image.Point, cellsize int) *Position {
position := &Position{}
position.Update(point.X*cellsize, point.Y*cellsize, cellsize)
return position
}
func (position *Position) GetMoved(velosity *Velocity) *Position {
pos := &Position{}
pos.Update(position.X+velosity.Data.X, position.Y+velosity.Data.Y, position.Cellsize)
return pos
}
func (position *Position) Point() image.Point {
return image.Point{position.X / position.Cellsize, position.Y / position.Cellsize}
}
func (position *Position) Left() int {
return position.X
}
func (position *Position) Right() int {
return position.X + position.Cellsize
}
func (position *Position) Top() int {
return position.Y
}
func (position *Position) Bottom() int {
return position.Y + position.Cellsize
}
func (position *Position) String() string {
return fmt.Sprintf("[%d,%d](Left:%d,Top:%d) x (Right:%d,Bottom:%d)",
position.X/32,
position.Y/32,
position.X,
position.Y,
position.Right(),
position.Bottom(),
)
}
func (position *Position) Move(velocity *Velocity, speed *Speed) {
if velocity.Direction != 0 {
slog.Debug("moving", "velocity", velocity, "speed", speed)
}
position.Update(
position.X+(velocity.Data.X*speed.Value),
position.Y+(velocity.Data.Y*speed.Value),
)
}
func (position *Position) Set(newpos *Position) {
position.Update(newpos.X, newpos.Y)
}
func (tile *Position) Intersects(moving *Position, velocity *Velocity) (bool, *Position) {
object := moving.GetMoved(velocity)
is := tile.Rect.Bounds().Intersect(object.Rect.Bounds())
if is != image.ZR {
slog.Debug("Intersect",
"velocity", velocity.Data,
"player", moving.Rect,
"moved player", object.Rect,
"collision at", is,
)
// collision, snap into neighbouring tile depending on the direction
switch velocity.Direction {
case West:
object.Update(tile.Rect.Max.X, tile.Y)
case East:
object.Update(tile.Rect.Min.X-tile.Cellsize, tile.Y)
case South:
object.Update(tile.X, tile.Rect.Min.Y-tile.Cellsize)
case North:
object.Update(tile.X, tile.Rect.Max.Y)
}
return true, object
}
return false, nil
}