2024-06-06 23:17:22 +03:00
|
|
|
package model
|
|
|
|
|
|
|
|
import (
|
|
|
|
"mvvasilev/last_light/engine"
|
|
|
|
|
|
|
|
"github.com/gdamore/tcell/v2"
|
|
|
|
)
|
|
|
|
|
2024-06-06 23:28:06 +03:00
|
|
|
type Map interface {
|
2024-06-06 23:17:22 +03:00
|
|
|
Size() engine.Size
|
2024-06-06 23:28:06 +03:00
|
|
|
Tiles() [][]Tile
|
|
|
|
ExploredTiles() map[engine.Position]Tile
|
2024-06-06 23:17:22 +03:00
|
|
|
ExploredTileStyle() tcell.Style
|
2024-06-06 23:28:06 +03:00
|
|
|
DefaultTile() Tile
|
2024-06-06 23:17:22 +03:00
|
|
|
|
|
|
|
PlayerSpawnPoint() *Map_PlayerSpawnPointComponent
|
|
|
|
Rooms() *Map_RoomsComponent
|
|
|
|
NextLevelStaircase() *Map_NextLevelStaircaseComponent
|
|
|
|
PreviousLevelStaircase() *Map_PreviousLevelStaircaseComponent
|
|
|
|
}
|
|
|
|
|
|
|
|
type Map_PlayerSpawnPointComponent struct {
|
|
|
|
Position engine.Position
|
|
|
|
}
|
|
|
|
|
|
|
|
type Map_RoomsComponent struct {
|
|
|
|
Rooms []engine.BoundingBox
|
|
|
|
}
|
|
|
|
|
|
|
|
type Map_NextLevelStaircaseComponent struct {
|
|
|
|
Position engine.Position
|
|
|
|
}
|
|
|
|
|
|
|
|
type Map_PreviousLevelStaircaseComponent struct {
|
|
|
|
Position engine.Position
|
|
|
|
}
|
|
|
|
|
|
|
|
type BaseMap struct {
|
|
|
|
size engine.Size
|
2024-06-06 23:28:06 +03:00
|
|
|
tiles [][]Tile
|
|
|
|
exploredTiles map[engine.Position]Tile
|
2024-06-06 23:17:22 +03:00
|
|
|
exploredStyle tcell.Style
|
2024-06-06 23:28:06 +03:00
|
|
|
defaultTile Tile
|
2024-06-06 23:17:22 +03:00
|
|
|
|
|
|
|
playerSpawnPos *Map_PlayerSpawnPointComponent
|
|
|
|
rooms *Map_RoomsComponent
|
|
|
|
nextLevel *Map_NextLevelStaircaseComponent
|
|
|
|
prevLevel *Map_PreviousLevelStaircaseComponent
|
|
|
|
}
|
|
|
|
|
2024-06-06 23:28:06 +03:00
|
|
|
func CreateMap(size engine.Size, tiles [][]Tile, exploredStyle tcell.Style, defaultTile Tile, components ...func(*BaseMap)) Map {
|
2024-06-06 23:17:22 +03:00
|
|
|
m := &BaseMap{
|
|
|
|
size: size,
|
|
|
|
tiles: tiles,
|
2024-06-06 23:28:06 +03:00
|
|
|
exploredTiles: make(map[engine.Position]Tile, 0),
|
2024-06-06 23:17:22 +03:00
|
|
|
exploredStyle: exploredStyle,
|
|
|
|
defaultTile: defaultTile,
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, c := range components {
|
|
|
|
c(m)
|
|
|
|
}
|
|
|
|
|
|
|
|
return m
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *BaseMap) Size() engine.Size {
|
|
|
|
return m.size
|
|
|
|
}
|
|
|
|
|
2024-06-06 23:28:06 +03:00
|
|
|
func (m *BaseMap) Tiles() [][]Tile {
|
2024-06-06 23:17:22 +03:00
|
|
|
return m.tiles
|
|
|
|
}
|
|
|
|
|
2024-06-06 23:28:06 +03:00
|
|
|
func (m *BaseMap) ExploredTiles() map[engine.Position]Tile {
|
2024-06-06 23:17:22 +03:00
|
|
|
return m.exploredTiles
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *BaseMap) ExploredTileStyle() tcell.Style {
|
|
|
|
return m.exploredStyle
|
|
|
|
}
|
|
|
|
|
2024-06-06 23:28:06 +03:00
|
|
|
func (m *BaseMap) DefaultTile() Tile {
|
2024-06-06 23:17:22 +03:00
|
|
|
return m.defaultTile
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *BaseMap) PlayerSpawnPoint() *Map_PlayerSpawnPointComponent {
|
|
|
|
return m.playerSpawnPos
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *BaseMap) Rooms() *Map_RoomsComponent {
|
|
|
|
return m.rooms
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *BaseMap) NextLevelStaircase() *Map_NextLevelStaircaseComponent {
|
|
|
|
return m.nextLevel
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *BaseMap) PreviousLevelStaircase() *Map_PreviousLevelStaircaseComponent {
|
|
|
|
return m.prevLevel
|
|
|
|
}
|
|
|
|
|
|
|
|
func Map_WithRooms(rooms []engine.BoundingBox) func(*BaseMap) {
|
|
|
|
return func(bm *BaseMap) {
|
|
|
|
bm.rooms = &Map_RoomsComponent{
|
|
|
|
Rooms: rooms,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func Map_WithPlayerSpawnPoint(pos engine.Position) func(*BaseMap) {
|
|
|
|
return func(bm *BaseMap) {
|
|
|
|
bm.playerSpawnPos = &Map_PlayerSpawnPointComponent{
|
|
|
|
Position: pos,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func Map_WithNextLevelStaircase(pos engine.Position) func(*BaseMap) {
|
|
|
|
return func(bm *BaseMap) {
|
|
|
|
bm.nextLevel = &Map_NextLevelStaircaseComponent{
|
|
|
|
Position: pos,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func Map_WithPreviousLevelStaircase(pos engine.Position) func(*BaseMap) {
|
|
|
|
return func(bm *BaseMap) {
|
|
|
|
bm.prevLevel = &Map_PreviousLevelStaircaseComponent{
|
|
|
|
Position: pos,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-06-06 23:28:06 +03:00
|
|
|
func Map_SetTileAt(bm Map, x int, y int, t Tile) Tile {
|
2024-06-06 23:17:22 +03:00
|
|
|
if !Map_IsInBounds(bm, x, y) {
|
|
|
|
return bm.DefaultTile()
|
|
|
|
}
|
|
|
|
|
|
|
|
bm.Tiles()[y][x] = t
|
|
|
|
|
|
|
|
return bm.Tiles()[y][x]
|
|
|
|
}
|
|
|
|
|
2024-06-06 23:28:06 +03:00
|
|
|
func Map_TileAt(bm Map, x int, y int) Tile {
|
2024-06-06 23:17:22 +03:00
|
|
|
if !Map_IsInBounds(bm, x, y) {
|
|
|
|
return bm.DefaultTile()
|
|
|
|
}
|
|
|
|
|
|
|
|
tile := bm.Tiles()[y][x]
|
|
|
|
|
|
|
|
if tile == nil {
|
|
|
|
return bm.DefaultTile()
|
|
|
|
}
|
|
|
|
|
|
|
|
return tile
|
|
|
|
}
|
|
|
|
|
2024-06-06 23:28:06 +03:00
|
|
|
func Map_IsInBounds(bm Map, x, y int) bool {
|
2024-06-06 23:17:22 +03:00
|
|
|
if x < 0 || y < 0 {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
if x >= bm.Size().Width() || y >= bm.Size().Height() {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2024-06-06 23:28:06 +03:00
|
|
|
func Map_ExploredTileAt(bm Map, x, y int) Tile {
|
2024-06-06 23:17:22 +03:00
|
|
|
return bm.ExploredTiles()[engine.PositionAt(x, y)]
|
|
|
|
}
|
|
|
|
|
2024-06-06 23:28:06 +03:00
|
|
|
func Map_MarkExplored(bm Map, x, y int) {
|
2024-06-06 23:17:22 +03:00
|
|
|
if !Map_IsInBounds(bm, x, y) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
tile := Map_TileAt(bm, x, y)
|
|
|
|
|
|
|
|
symbol, _ := tile.DefaultPresentation()
|
|
|
|
|
|
|
|
bm.ExploredTiles()[engine.PositionAt(x, y)] = &BaseTile{
|
|
|
|
defaultSymbol: symbol,
|
|
|
|
defaultStyle: bm.ExploredTileStyle(),
|
|
|
|
}
|
|
|
|
}
|