178 lines
4.2 KiB
Go
178 lines
4.2 KiB
Go
package grid
|
|
|
|
import (
|
|
"openquell/components"
|
|
. "openquell/config"
|
|
|
|
"log/slog"
|
|
)
|
|
|
|
// Check a collision on the grid. We check if the entity in question
|
|
// bumps into the egde of the grid or if it bumps onto a solid wall
|
|
// tile. For both cases the user must provide responder funcs in which
|
|
// it must be implemented how to react on those events.
|
|
func (grid *Grid) CheckGridCollision(
|
|
position *components.Position,
|
|
velocity *components.Velocity,
|
|
respond_edge func(*components.Position, *components.Velocity, *components.Position),
|
|
respond_solid func(*components.Position, *components.Velocity, *components.Position),
|
|
) {
|
|
|
|
if velocity.Moving() {
|
|
ok, newpos := grid.BumpEdge(position, velocity)
|
|
if ok {
|
|
//slog.Debug("falling off the edge", "newpos", newpos)
|
|
respond_edge(position, velocity, newpos)
|
|
} else {
|
|
ok, tilepos := grid.GetSolidNeighborPosition(position, velocity, true)
|
|
if ok {
|
|
slog.Debug("(3) HaveSolidNeighbor", "tilepos",
|
|
tilepos.String(), "playpos", position.String())
|
|
intersects, newpos := tilepos.Intersects(position, velocity)
|
|
if intersects {
|
|
respond_solid(position, velocity, newpos)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func (grid *Grid) GetSolidNeighborPosition(
|
|
position *components.Position,
|
|
velocity *components.Velocity,
|
|
solid bool) (bool, *components.Position) {
|
|
|
|
if !solid {
|
|
return false, nil
|
|
}
|
|
|
|
// set to true if we are already on the last tile in the current
|
|
// direction, i.e. on the edge of the grid
|
|
edge := true
|
|
moving := position.GetMoved(velocity)
|
|
|
|
neighborpos := position.Point()
|
|
if velocity.Direction == East || velocity.Direction == South {
|
|
// FIXES snapin to down+right, but now top+left fail. Only in
|
|
// these cases we need to look at the neighbor in the future
|
|
// position where we will be when we move forward. I don't
|
|
// know why it is like this, in fact it doesn't really make
|
|
// any sense. But it works, so I'll keep it that way for the
|
|
// moment.
|
|
neighborpos = moving.Point()
|
|
}
|
|
|
|
switch velocity.Direction {
|
|
case East:
|
|
if neighborpos.X < grid.TilesX {
|
|
neighborpos.X++
|
|
edge = false
|
|
}
|
|
case West:
|
|
if neighborpos.X > 0 {
|
|
neighborpos.X--
|
|
edge = false
|
|
}
|
|
case South:
|
|
if neighborpos.Y < grid.TilesY {
|
|
neighborpos.Y++
|
|
edge = false
|
|
}
|
|
case North:
|
|
if neighborpos.Y > 0 {
|
|
neighborpos.Y--
|
|
edge = false
|
|
}
|
|
}
|
|
|
|
newpos := components.NewPosition(neighborpos, grid.Tilesize)
|
|
|
|
slog.Debug("SolidNeighbor?", "player", position.Point(),
|
|
"neighbor", neighborpos, "edge", edge, "neighbor-solid",
|
|
grid.Map[neighborpos].Solid, "newpos", newpos.Point())
|
|
if !edge && grid.Map[neighborpos].Solid {
|
|
return true, newpos
|
|
}
|
|
|
|
return false, nil
|
|
}
|
|
|
|
func (grid *Grid) OrigGetSolidNeighborPosition(
|
|
position *components.Position,
|
|
velocity *components.Velocity,
|
|
solid bool) (bool, *components.Position) {
|
|
|
|
if !solid {
|
|
return false, nil
|
|
}
|
|
|
|
// set to true if we are already on the last tile in the current
|
|
// direction, i.e. on the edge of the grid
|
|
edge := true
|
|
neighborpos := position.Point()
|
|
|
|
switch velocity.Direction {
|
|
case East:
|
|
if neighborpos.X < grid.TilesX {
|
|
neighborpos.X++
|
|
edge = false
|
|
}
|
|
case West:
|
|
if neighborpos.X > 0 {
|
|
neighborpos.X--
|
|
edge = false
|
|
}
|
|
case South:
|
|
if neighborpos.Y < grid.TilesY {
|
|
neighborpos.Y++
|
|
edge = false
|
|
}
|
|
case North:
|
|
if neighborpos.Y > 0 {
|
|
neighborpos.Y--
|
|
edge = false
|
|
}
|
|
}
|
|
|
|
newpos := components.NewPosition(neighborpos, grid.Tilesize)
|
|
|
|
slog.Debug("SolidNeighbor?", "player", position.Point(),
|
|
"neighbor", neighborpos, "edge", edge, "neighbor-solid",
|
|
grid.Map[neighborpos].Solid, "newpos", newpos.Point())
|
|
if !edge && grid.Map[neighborpos].Solid {
|
|
return true, newpos
|
|
}
|
|
|
|
return false, nil
|
|
}
|
|
|
|
func (grid *Grid) BumpEdge(
|
|
pos *components.Position,
|
|
velocity *components.Velocity) (bool, *components.Position) {
|
|
|
|
x := pos.X + velocity.Data.X
|
|
y := pos.Y + velocity.Data.Y
|
|
|
|
if x < 0 || x > grid.Width-grid.Tilesize || y < 0 || y > grid.Height-grid.Tilesize {
|
|
newpos := &components.Position{}
|
|
X := pos.X
|
|
Y := pos.Y
|
|
|
|
switch velocity.Direction {
|
|
case East:
|
|
X = 0
|
|
case West:
|
|
X = grid.Width - grid.Tilesize
|
|
case South:
|
|
Y = 0
|
|
case North:
|
|
Y = grid.Height - grid.Tilesize
|
|
}
|
|
|
|
newpos.Update(X, Y, grid.Tilesize)
|
|
return true, newpos
|
|
}
|
|
|
|
return false, nil
|
|
}
|