2024-02-06 15:26:20 +01:00
|
|
|
package game
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"fmt"
|
|
|
|
|
"image"
|
|
|
|
|
"log"
|
|
|
|
|
"openquell/assets"
|
|
|
|
|
"openquell/components"
|
|
|
|
|
. "openquell/config"
|
|
|
|
|
|
2024-02-06 19:02:25 +01:00
|
|
|
"github.com/alecthomas/repr"
|
2024-02-06 15:26:20 +01:00
|
|
|
"github.com/mlange-42/arche/generic"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type Grid struct {
|
|
|
|
|
Width int
|
|
|
|
|
Height int
|
|
|
|
|
Size int
|
|
|
|
|
Tilesize int
|
|
|
|
|
TilesX int
|
|
|
|
|
TilesY int
|
|
|
|
|
Map map[image.Point]*assets.Tile
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// FIXME: put component addition into extra callable function, to be called
|
|
|
|
|
// by game.go in a level-loop. Also remove components of previous level
|
|
|
|
|
func NewGrid(game *Game, tilesize int, mapslice map[image.Point]*assets.Tile) *Grid {
|
|
|
|
|
// we use this to turn our tiles into iterable entities, used for
|
|
|
|
|
// collision detection, transformation and other things
|
|
|
|
|
playermapper := generic.NewMap4[
|
|
|
|
|
components.Position,
|
|
|
|
|
components.Velocity,
|
|
|
|
|
components.Renderable,
|
|
|
|
|
components.Player](game.World)
|
2024-02-07 18:01:58 +01:00
|
|
|
|
2024-02-06 15:26:20 +01:00
|
|
|
solidmapper := generic.NewMap4[
|
|
|
|
|
components.Position,
|
|
|
|
|
components.Renderable,
|
|
|
|
|
components.Tilish,
|
|
|
|
|
components.Solid](game.World)
|
2024-02-07 18:01:58 +01:00
|
|
|
|
2024-02-06 15:26:20 +01:00
|
|
|
emptymapper := generic.NewMap2[components.Position, components.Tilish](game.World)
|
|
|
|
|
|
2024-02-07 18:01:58 +01:00
|
|
|
colmapper := generic.NewMap3[
|
|
|
|
|
components.Position,
|
|
|
|
|
components.Renderable,
|
|
|
|
|
components.Collectible](game.World)
|
|
|
|
|
|
2024-02-08 18:33:59 +01:00
|
|
|
ptmapper := generic.NewMap2[
|
|
|
|
|
components.Position,
|
|
|
|
|
components.Particle,
|
|
|
|
|
](game.World)
|
|
|
|
|
|
2024-02-06 15:26:20 +01:00
|
|
|
var pos *components.Position
|
|
|
|
|
var render *components.Renderable
|
|
|
|
|
|
|
|
|
|
for point, tile := range mapslice {
|
|
|
|
|
switch tile.Renderable {
|
|
|
|
|
case true:
|
|
|
|
|
switch {
|
|
|
|
|
case tile.Solid:
|
|
|
|
|
entity := solidmapper.New()
|
|
|
|
|
pos, render, _, _ = solidmapper.Get(entity)
|
|
|
|
|
case tile.Player:
|
|
|
|
|
entity := playermapper.New()
|
|
|
|
|
pos, _, render, _ = playermapper.Get(entity)
|
|
|
|
|
fmt.Printf("player start pos: %d,%d\n", point.X*tilesize, point.Y*tilesize)
|
2024-02-07 18:01:58 +01:00
|
|
|
case tile.Collectible:
|
|
|
|
|
entity := colmapper.New()
|
|
|
|
|
pos, render, _ = colmapper.Get(entity)
|
2024-02-06 15:26:20 +01:00
|
|
|
default:
|
|
|
|
|
log.Fatalln("unsupported tile type encountered")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
render.Image = tile.Sprite
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
// empty cell, this is where the player[s] move. No
|
|
|
|
|
// sprite required since every level has a background
|
|
|
|
|
// image.
|
|
|
|
|
entity := emptymapper.New()
|
|
|
|
|
pos, _ = emptymapper.Get(entity)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// however, every tile has a position
|
|
|
|
|
pos.Update(point.X*tilesize, point.Y*tilesize, tilesize)
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-08 18:33:59 +01:00
|
|
|
// not part of the grid, but add them as well
|
|
|
|
|
entity := ptmapper.New()
|
|
|
|
|
_, particle := ptmapper.Get(entity)
|
|
|
|
|
particle.Index = assets.Tiles['*'].Particle
|
|
|
|
|
particle.Particles = assets.Tiles['*'].Particles
|
|
|
|
|
|
2024-02-06 15:26:20 +01:00
|
|
|
return &Grid{
|
|
|
|
|
Size: len(mapslice),
|
|
|
|
|
Tilesize: tilesize,
|
|
|
|
|
Width: game.ScreenWidth,
|
|
|
|
|
Height: game.ScreenHeight,
|
|
|
|
|
TilesX: game.ScreenWidth / tilesize,
|
|
|
|
|
TilesY: game.ScreenHeight / tilesize,
|
|
|
|
|
Map: mapslice,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (grid *Grid) 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 < 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)
|
2024-02-06 19:02:25 +01:00
|
|
|
repr.Println(newpos)
|
2024-02-06 15:26:20 +01:00
|
|
|
|
2024-02-06 19:02:25 +01:00
|
|
|
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
|
|
|
|
|
fmt.Println("east X=0")
|
|
|
|
|
case West:
|
|
|
|
|
X = grid.Width - grid.Tilesize
|
|
|
|
|
fmt.Println("west X=max")
|
|
|
|
|
case South:
|
|
|
|
|
Y = 0
|
|
|
|
|
fmt.Println("south y=0")
|
|
|
|
|
case North:
|
|
|
|
|
Y = grid.Height - grid.Tilesize
|
|
|
|
|
fmt.Println("north y=max")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
newpos.Update(X, Y, grid.Tilesize)
|
2024-02-06 15:26:20 +01:00
|
|
|
return true, newpos
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false, nil
|
|
|
|
|
}
|