82 lines
2.4 KiB
GDScript
82 lines
2.4 KiB
GDScript
class_name MapLayout extends Resource
|
|
|
|
@export var size: Vector2i = Vector2i.ZERO
|
|
@export var rooms: Array[Room]
|
|
## Openings are stored as a flat array of pairs: [from1, to1, from2, to2, ...].
|
|
## Each consecutive pair of Vector2i values represents a bidirectional doorway
|
|
## between two adjacent tiles in different rooms.
|
|
@export var openings: Array[Vector2i]
|
|
|
|
var _tile_room_map: Dictionary = {}
|
|
var _opening_set: Dictionary = {}
|
|
|
|
|
|
func initialize() -> void:
|
|
assert(openings.size() % 2 == 0, "Openings must be provided as pairs of Vector2i")
|
|
_tile_room_map.clear()
|
|
_opening_set.clear()
|
|
for room in rooms:
|
|
for tile in room.tiles:
|
|
_tile_room_map[tile] = room
|
|
for i in range(0, openings.size(), 2):
|
|
var a := openings[i]
|
|
var b := openings[i + 1]
|
|
_opening_set[_edge_key(a, b)] = true
|
|
|
|
|
|
static func _edge_key(a: Vector2i, b: Vector2i) -> String:
|
|
if a < b:
|
|
return "%d,%d-%d,%d" % [a.x, a.y, b.x, b.y]
|
|
return "%d,%d-%d,%d" % [b.x, b.y, a.x, a.y]
|
|
|
|
|
|
func is_tile_valid(tile: Vector2i) -> bool:
|
|
return _tile_room_map.has(tile)
|
|
|
|
|
|
func get_room_at(tile: Vector2i) -> Room:
|
|
return _tile_room_map.get(tile, null)
|
|
|
|
|
|
func is_passable(from: Vector2i, to: Vector2i) -> bool:
|
|
if not is_tile_valid(from) or not is_tile_valid(to):
|
|
return false
|
|
var room_from: Room = _tile_room_map[from]
|
|
var room_to: Room = _tile_room_map[to]
|
|
if room_from == room_to:
|
|
return true
|
|
return _opening_set.has(_edge_key(from, to))
|
|
|
|
|
|
func get_openings() -> Array:
|
|
## Returns an array of [Vector2i, Vector2i] pairs representing opening edges.
|
|
var result: Array = []
|
|
for i in range(0, openings.size(), 2):
|
|
result.append([openings[i], openings[i + 1]])
|
|
return result
|
|
|
|
|
|
func get_walls() -> Array:
|
|
## Returns an array of [Vector2i, Vector2i] pairs representing wall edges.
|
|
## A wall exists where a room tile borders void or a different room (without an opening).
|
|
var walls: Array = []
|
|
var directions := [Vector2i.RIGHT, Vector2i.DOWN, Vector2i.LEFT, Vector2i.UP]
|
|
var visited_edges: Dictionary = {}
|
|
|
|
for room in rooms:
|
|
for tile in room.tiles:
|
|
for dir in directions:
|
|
var neighbor: Vector2i = tile + dir
|
|
var key := _edge_key(tile, neighbor)
|
|
if visited_edges.has(key):
|
|
continue
|
|
visited_edges[key] = true
|
|
|
|
var neighbor_room: Room = _tile_room_map.get(neighbor, null)
|
|
if neighbor_room == room:
|
|
continue
|
|
# Neighbor is void or different room — wall unless opening
|
|
if not _opening_set.has(key):
|
|
walls.append([tile, neighbor])
|
|
return walls
|