package game import ( "fmt" "image" "github.com/hajimehoshi/ebiten/v2" "gitea.brasse-pc.eu/brasse/metro-puzzle-jp/internal/level" "gitea.brasse-pc.eu/brasse/metro-puzzle-jp/internal/res" "gitea.brasse-pc.eu/brasse/metro-puzzle-jp/internal/sim" ) // Ordningen på rutorna i resources/sprites/tiles.png (måste matcha tools/genart). var tileOrder = []level.Tile{ level.Wall, level.Floor, level.Spawn, level.Platform, level.Gate, level.TicketMachine, level.Sign, } // Assets är allt som laddats från resources/. type Assets struct { ResDir string LevelsDir string Tiles map[level.Tile]*ebiten.Image Player [4][3]*ebiten.Image // [riktning: ner, upp, vänster, höger][bildruta: stilla, gå1, gå2] Text map[string]string } // LoadAssets läser grafik och texter. func LoadAssets() (*Assets, error) { dir, err := res.Dir() if err != nil { return nil, err } a := &Assets{ResDir: dir, Tiles: map[level.Tile]*ebiten.Image{}} a.LevelsDir, _ = res.Path("data", "levels") tiles, err := loadImage("sprites", "tiles.png") if err != nil { return nil, err } if w := tiles.Bounds().Dx(); w < TileSize*len(tileOrder) { return nil, fmt.Errorf("tiles.png är %d px bred, behöver minst %d", w, TileSize*len(tileOrder)) } for i, t := range tileOrder { a.Tiles[t] = tiles.SubImage(image.Rect(i*TileSize, 0, (i+1)*TileSize, TileSize)).(*ebiten.Image) } a.Tiles[level.WrongPlatform] = a.Tiles[level.Platform] // samma utseende; tåget avgör player, err := loadImage("sprites", "player.png") if err != nil { return nil, err } for row := 0; row < 4; row++ { for col := 0; col < 3; col++ { a.Player[row][col] = player.SubImage(image.Rect(col*TileSize, row*TileSize, (col+1)*TileSize, (row+1)*TileSize)).(*ebiten.Image) } } if err := res.LoadJSON(&a.Text, "text", "sv.json"); err != nil { return nil, err } return a, nil } // T slår upp en UI-text; saknas nyckeln visas nyckeln själv så att det syns. func (a *Assets) T(key string) string { if s, ok := a.Text[key]; ok { return s } return key } // PlayerFrame returnerar rätt bildruta för riktning och gångfas. func (a *Assets) PlayerFrame(facing sim.Dir, moving bool, animT float64) *ebiten.Image { row := 0 switch facing { case sim.Up: row = 1 case sim.Left: row = 2 case sim.Right: row = 3 } col := 0 if moving { col = 1 + int(animT/0.12)%2 } return a.Player[row][col] } func loadImage(parts ...string) (*ebiten.Image, error) { img, err := res.LoadImage(parts...) if err != nil { return nil, err } return ebiten.NewImageFromImage(img), nil }