package game import ( "fmt" "image" "log" "openquell/assets" "openquell/components" . "openquell/config" "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) solidmapper := generic.NewMap4[ components.Position, components.Renderable, components.Tilish, components.Solid](game.World) emptymapper := generic.NewMap2[components.Position, components.Tilish](game.World) 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) 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) } 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 } fmt.Println(position) // 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) fmt.Println(newpos, edge) if !edge && grid.Map[*neighborpos].Solid { return true, newpos } return false, nil }