2024-02-06 15:26:20 +01:00
|
|
|
package game
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"image"
|
|
|
|
|
"log"
|
|
|
|
|
"openquell/assets"
|
|
|
|
|
"openquell/components"
|
2024-02-10 19:45:06 +01:00
|
|
|
"openquell/grid"
|
2024-02-11 14:24:30 +01:00
|
|
|
"openquell/observers"
|
2024-02-10 19:45:06 +01:00
|
|
|
"openquell/systems"
|
2024-02-06 15:26:20 +01:00
|
|
|
"strings"
|
|
|
|
|
|
|
|
|
|
"github.com/hajimehoshi/ebiten/v2"
|
|
|
|
|
"github.com/mlange-42/arche/ecs"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type Level struct {
|
|
|
|
|
Cellsize, Width, Height int
|
|
|
|
|
World *ecs.World
|
|
|
|
|
Name string
|
|
|
|
|
Description string
|
|
|
|
|
Mapslice map[image.Point]*assets.Tile
|
2024-02-07 18:01:58 +01:00
|
|
|
|
2024-02-10 19:45:06 +01:00
|
|
|
Player *systems.PlayerSystem
|
|
|
|
|
GridSystem *systems.GridSystem
|
2024-02-07 18:01:58 +01:00
|
|
|
|
2024-02-10 19:45:06 +01:00
|
|
|
Grid *grid.Grid
|
|
|
|
|
}
|
2024-02-07 18:01:58 +01:00
|
|
|
|
2024-02-10 19:45:06 +01:00
|
|
|
func NewLevel(game *Game, cellsize int, plan *assets.RawLevel) *Level {
|
|
|
|
|
gridsystem := systems.NewGridSystem(game.World, game.ScreenWidth,
|
|
|
|
|
game.ScreenHeight, cellsize, plan.Background)
|
2024-02-19 19:05:48 +01:00
|
|
|
|
2024-02-10 19:45:06 +01:00
|
|
|
playersystem := systems.NewPlayerSystem(game.World, gridsystem)
|
2024-02-07 18:01:58 +01:00
|
|
|
|
2024-02-06 15:26:20 +01:00
|
|
|
return &Level{
|
|
|
|
|
Mapslice: LevelToSlice(game, plan, cellsize),
|
|
|
|
|
Cellsize: cellsize,
|
|
|
|
|
World: game.World,
|
|
|
|
|
Width: game.ScreenWidth,
|
|
|
|
|
Height: game.ScreenHeight,
|
|
|
|
|
Description: plan.Description,
|
2024-02-18 18:19:34 +01:00
|
|
|
Name: plan.Name,
|
2024-02-10 19:45:06 +01:00
|
|
|
GridSystem: gridsystem,
|
|
|
|
|
Player: playersystem,
|
2024-02-06 15:26:20 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (level *Level) Update() {
|
2024-02-10 19:45:06 +01:00
|
|
|
level.GridSystem.Update()
|
|
|
|
|
level.Player.Update()
|
|
|
|
|
}
|
2024-02-08 18:33:59 +01:00
|
|
|
|
2024-02-10 19:45:06 +01:00
|
|
|
func (level *Level) Draw(screen *ebiten.Image) {
|
|
|
|
|
level.GridSystem.Draw(screen)
|
|
|
|
|
level.Player.Draw(screen)
|
2024-02-06 15:26:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (level *Level) Position2Point(position *components.Position) image.Point {
|
|
|
|
|
return image.Point{
|
|
|
|
|
int(position.X) / level.Cellsize,
|
|
|
|
|
int(position.Y) / level.Cellsize,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (level *Level) SetupGrid(game *Game) {
|
2024-02-09 20:20:13 +01:00
|
|
|
// generic variant does not work here:
|
|
|
|
|
// selector := generic.NewFilter1[components.Position]()
|
|
|
|
|
// level.World.Batch().RemoveEntities(selector)
|
|
|
|
|
// missing argument in conversion to generic.Filter1[components.Position]
|
|
|
|
|
|
|
|
|
|
// erase all entities of previous level, if any
|
|
|
|
|
posID := ecs.ComponentID[components.Position](level.World)
|
|
|
|
|
selector := ecs.All(posID)
|
|
|
|
|
level.World.Batch().RemoveEntities(selector)
|
|
|
|
|
|
2024-02-11 14:24:30 +01:00
|
|
|
// get rid of any players on PlayerObserver. FIXME: remove them in grid.NewGrid()?
|
|
|
|
|
playerobserver := observers.GetPlayerObserver(level.World)
|
|
|
|
|
playerobserver.RemoveEntities()
|
|
|
|
|
|
2024-02-09 20:20:13 +01:00
|
|
|
// setup world
|
2024-02-10 19:45:06 +01:00
|
|
|
level.GridSystem.SetGrid(grid.NewGrid(game.World, level.Cellsize, level.Width, level.Height, level.Mapslice))
|
2024-02-06 15:26:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func LevelToSlice(game *Game, level *assets.RawLevel, tilesize int) map[image.Point]*assets.Tile {
|
|
|
|
|
size := game.ScreenWidth * game.ScreenHeight
|
|
|
|
|
mapslice := make(map[image.Point]*assets.Tile, size)
|
|
|
|
|
|
|
|
|
|
for y, line := range strings.Split(string(level.Data), "\n") {
|
|
|
|
|
if len(line) != game.ScreenWidth/tilesize && y < game.ScreenHeight/tilesize {
|
|
|
|
|
log.Fatalf("line %d doesn't contain %d tiles, but %d",
|
|
|
|
|
y, game.ScreenWidth/tilesize, len(line))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for x, char := range line {
|
|
|
|
|
mapslice[image.Point{x, y}] = assets.Tiles[byte(char)]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return mapslice
|
|
|
|
|
}
|