164 lines
3.5 KiB
Go
164 lines
3.5 KiB
Go
package systems
|
|
|
|
import (
|
|
"fmt"
|
|
"image"
|
|
"image/draw"
|
|
"openquell/components"
|
|
. "openquell/components"
|
|
. "openquell/config"
|
|
"openquell/grid"
|
|
|
|
"github.com/alecthomas/repr"
|
|
"github.com/hajimehoshi/ebiten/v2"
|
|
"github.com/mlange-42/arche/ecs"
|
|
"github.com/mlange-42/arche/generic"
|
|
)
|
|
|
|
type GridSystem struct {
|
|
World *ecs.World
|
|
Selector *generic.Filter3[Renderable, Position, Solid]
|
|
UseCache bool
|
|
Cache *ebiten.Image
|
|
Background *ebiten.Image
|
|
Width, Height, TilesX, TilesY, Tilesize int
|
|
Grid *grid.Grid
|
|
}
|
|
|
|
func NewGridSystem(world *ecs.World, width, height,
|
|
tilesize int, background *ebiten.Image) *GridSystem {
|
|
|
|
cache := ebiten.NewImage(width, height)
|
|
|
|
system := &GridSystem{
|
|
Selector: generic.NewFilter3[Renderable, Position, Solid](),
|
|
UseCache: false,
|
|
Cache: cache,
|
|
Width: width,
|
|
Height: height,
|
|
TilesX: width / tilesize,
|
|
TilesY: height / tilesize,
|
|
Tilesize: tilesize,
|
|
Background: background,
|
|
World: world,
|
|
}
|
|
|
|
return system
|
|
}
|
|
|
|
func (system *GridSystem) SetGrid(grid *grid.Grid) {
|
|
system.Grid = grid
|
|
}
|
|
|
|
func (system *GridSystem) Update() {}
|
|
|
|
func (system *GridSystem) Draw(screen *ebiten.Image) {
|
|
op := &ebiten.DrawImageOptions{}
|
|
|
|
if !system.UseCache {
|
|
// map not cached or cacheable, write it to the cache
|
|
draw.Draw(system.Cache, system.Background.Bounds(), system.Background, image.ZP, draw.Src)
|
|
|
|
query := system.Selector.Query(system.World)
|
|
|
|
for query.Next() {
|
|
sprite, pos, _ := query.Get()
|
|
|
|
draw.Draw(
|
|
system.Cache,
|
|
image.Rect(pos.X, pos.Y, pos.X+pos.Cellsize, pos.Y+pos.Cellsize),
|
|
sprite.Image, image.ZP, draw.Over)
|
|
}
|
|
|
|
op.GeoM.Reset()
|
|
screen.DrawImage(system.Cache, op)
|
|
|
|
system.UseCache = true
|
|
} else {
|
|
// use the cached map
|
|
op.GeoM.Reset()
|
|
screen.DrawImage(system.Cache, op)
|
|
}
|
|
}
|
|
|
|
func (system *GridSystem) GetSolidNeighborPosition(
|
|
position *components.Position,
|
|
velocity *components.Velocity,
|
|
solid bool) (bool, *components.Position) {
|
|
|
|
if !solid {
|
|
return false, nil
|
|
}
|
|
|
|
// set to true, ifwe 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 < system.TilesX {
|
|
neighborpos.X++
|
|
edge = false
|
|
}
|
|
case West:
|
|
if neighborpos.X > 0 {
|
|
neighborpos.X--
|
|
edge = false
|
|
}
|
|
case South:
|
|
if neighborpos.Y < system.TilesY {
|
|
neighborpos.Y++
|
|
edge = false
|
|
}
|
|
case North:
|
|
if neighborpos.Y > 0 {
|
|
neighborpos.Y--
|
|
edge = false
|
|
}
|
|
}
|
|
|
|
newpos := components.NewPosition(neighborpos, system.Tilesize)
|
|
repr.Println(newpos)
|
|
|
|
if !edge && system.Grid.Map[neighborpos].Solid {
|
|
return true, newpos
|
|
}
|
|
|
|
return false, nil
|
|
}
|
|
|
|
func (system *GridSystem) 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 > system.Width-system.Tilesize || y < 0 || y > system.Height-system.Tilesize {
|
|
newpos := &components.Position{}
|
|
X := pos.X
|
|
Y := pos.Y
|
|
|
|
switch velocity.Direction {
|
|
case East:
|
|
X = 0
|
|
fmt.Println("east X=0")
|
|
case West:
|
|
X = system.Width - system.Tilesize
|
|
fmt.Println("west X=max")
|
|
case South:
|
|
Y = 0
|
|
fmt.Println("south y=0")
|
|
case North:
|
|
Y = system.Height - system.Tilesize
|
|
fmt.Println("north y=max")
|
|
}
|
|
|
|
newpos.Update(X, Y, system.Tilesize)
|
|
return true, newpos
|
|
}
|
|
|
|
return false, nil
|
|
}
|