79 lines
2.6 KiB
GDScript
79 lines
2.6 KiB
GDScript
extends RefCounted
|
|
## Logical map: artwork is never used as collision geometry.
|
|
const ROWS := [
|
|
"############################",
|
|
"#............##............#",
|
|
"#.####.#####.##.#####.####.#",
|
|
"#o####.#####.##.#####.####o#",
|
|
"#.####.#####.##.#####.####.#",
|
|
"#..........................#",
|
|
"#.####.##.########.##.####.#",
|
|
"#.####.##.########.##.####.#",
|
|
"#......##....##....##......#",
|
|
"######.##### ## #####.######",
|
|
" #.##### ## #####.# ",
|
|
" #.## ##.# ",
|
|
" #.## ###--### ##.# ",
|
|
"######.## # # ##.######",
|
|
" . # # . ",
|
|
"######.## # # ##.######",
|
|
" #.## ######## ##.# ",
|
|
" #.## ##.# ",
|
|
" #.## ######## ##.# ",
|
|
"######.## ######## ##.######",
|
|
"#............##............#",
|
|
"#.####.#####.##.#####.####.#",
|
|
"#.####.#####.##.#####.####.#",
|
|
"#o..##....... .......##..o#",
|
|
"###.##.##.########.##.##.###",
|
|
"###.##.##.########.##.##.###",
|
|
"#......##....##....##......#",
|
|
"#.##########.##.##########.#",
|
|
"#.##########.##.##########.#",
|
|
"#..........................#",
|
|
"############################",
|
|
]
|
|
const DIRS := [Vector2i.UP, Vector2i.LEFT, Vector2i.DOWN, Vector2i.RIGHT]
|
|
const PLAYER_START := Vector2i(13, 23)
|
|
const DOOR := Vector2i(13, 11)
|
|
|
|
static func neighbor(tile: Vector2i, direction: Vector2i) -> Vector2i:
|
|
var result := tile + direction
|
|
if result.y == 14:
|
|
result.x = posmod(result.x, 28)
|
|
return result
|
|
|
|
static func walkable(tile: Vector2i, eyes := false) -> bool:
|
|
if tile.x < 0 or tile.x >= 28 or tile.y < 0 or tile.y >= 31:
|
|
return false
|
|
# Blank regions outside the maze are not corridors.
|
|
if tile.y != 14 and tile.y >= 9 and tile.y <= 19 and (tile.x < 5 or tile.x > 22):
|
|
return false
|
|
var cell: String = ROWS[tile.y][tile.x]
|
|
return cell != "#" and (cell != "-" or eyes)
|
|
|
|
static func pellets() -> Dictionary:
|
|
var result := {}
|
|
for y in range(31):
|
|
for x in range(28):
|
|
if ROWS[y][x] in [".", "o"]:
|
|
result[Vector2i(x, y)] = ROWS[y][x] == "o"
|
|
return result
|
|
|
|
static func actor(tile: Vector2i, direction: Vector2i) -> Dictionary:
|
|
return {
|
|
"tile": tile,
|
|
"next": tile,
|
|
"progress": 0.0,
|
|
"dir": direction,
|
|
"spawn_offset": Vector2.ZERO,
|
|
}
|
|
|
|
static func position(actor_data: Dictionary) -> Vector2:
|
|
var offset := Vector2(actor_data.next - actor_data.tile)
|
|
if abs(offset.x) > 1.0:
|
|
offset.x = float(actor_data.dir.x)
|
|
# Actor centers use the logical maze lane. Rendering and collision share
|
|
# this exact position so a sprite cannot be shifted into a neighboring wall.
|
|
return Vector2(actor_data.tile) + actor_data.get("spawn_offset", Vector2.ZERO) + offset * actor_data.progress
|