123 lines
3.8 KiB
GDScript3
123 lines
3.8 KiB
GDScript3
|
|
extends Node3D
|
||
|
|
|
||
|
|
# Demo_3D: renders multiple stacked levels of Brogue dungeons using GridMap.
|
||
|
|
# Chasm cells are rendered as empty (no tile), so looking down through one
|
||
|
|
# reveals the floor of the level below.
|
||
|
|
|
||
|
|
# Must match src/gen/grid.h
|
||
|
|
const T_NOTHING := 0
|
||
|
|
const T_FLOOR := 1
|
||
|
|
const T_WALL := 2
|
||
|
|
const T_DOOR := 3
|
||
|
|
const T_CORRIDOR := 4
|
||
|
|
const T_LIQUID := 5
|
||
|
|
const T_BRIDGE := 6
|
||
|
|
const T_STAIRS_UP := 7
|
||
|
|
const T_STAIRS_DOWN := 8
|
||
|
|
|
||
|
|
const L_NONE := 0
|
||
|
|
const L_WATER := 1
|
||
|
|
const L_LAVA := 2
|
||
|
|
const L_CHASM := 3
|
||
|
|
const L_BRIMSTONE := 4
|
||
|
|
|
||
|
|
# Match the tile IDs exposed by MeshLibraryBuilder.
|
||
|
|
const TILE_FLOOR := 0
|
||
|
|
const TILE_WALL := 1
|
||
|
|
const TILE_DOOR := 2
|
||
|
|
const TILE_CORRIDOR := 3
|
||
|
|
const TILE_WATER := 4
|
||
|
|
const TILE_LAVA := 5
|
||
|
|
const TILE_BRIMSTONE := 6
|
||
|
|
const TILE_BRIDGE := 7
|
||
|
|
const TILE_STAIRS_UP := 8
|
||
|
|
const TILE_STAIRS_DOWN := 9
|
||
|
|
|
||
|
|
@export var base_seed: int = 2321
|
||
|
|
@export var depth_start: int = 20
|
||
|
|
@export var level_count: int = 10
|
||
|
|
@export var level_spacing: float = 6.0
|
||
|
|
|
||
|
|
@onready var levels_root: Node3D = $Levels
|
||
|
|
@onready var camera: Camera3D = $FlyCamera
|
||
|
|
|
||
|
|
var _mesh_library: MeshLibrary
|
||
|
|
|
||
|
|
func _ready() -> void:
|
||
|
|
_mesh_library = MeshLibraryBuilder.build()
|
||
|
|
|
||
|
|
var total_chasm_cells := 0
|
||
|
|
for level_index in range(level_count):
|
||
|
|
var level_seed := base_seed + level_index
|
||
|
|
var depth := depth_start + level_index
|
||
|
|
var gen := BrogueGen.new()
|
||
|
|
var grid: Dictionary = gen.generate(level_seed, depth)
|
||
|
|
gen.free()
|
||
|
|
|
||
|
|
var grid_map := GridMap.new()
|
||
|
|
grid_map.name = "Level%d" % level_index
|
||
|
|
grid_map.mesh_library = _mesh_library
|
||
|
|
grid_map.cell_size = Vector3(1, 1, 1)
|
||
|
|
grid_map.position.y = -level_index * level_spacing
|
||
|
|
levels_root.add_child(grid_map)
|
||
|
|
|
||
|
|
var chasm_cells := _populate_level(grid_map, grid)
|
||
|
|
total_chasm_cells += chasm_cells
|
||
|
|
|
||
|
|
print("Level %d: seed=%d depth=%d rooms=%d machines=%d chasms=%d"
|
||
|
|
% [level_index, level_seed, depth,
|
||
|
|
(grid["rooms"] as Array).size(),
|
||
|
|
(grid["machines"] as Array).size(),
|
||
|
|
chasm_cells])
|
||
|
|
|
||
|
|
# Position the camera above level 0's grid center, tilted down.
|
||
|
|
var grid_w := 79
|
||
|
|
var grid_h := 29
|
||
|
|
camera.position = Vector3(grid_w * 0.5, 14, grid_h * 0.5 + 18)
|
||
|
|
camera.rotation_degrees = Vector3(-35, 0, 0)
|
||
|
|
|
||
|
|
print("Demo3D ready. %d levels, %d chasm cells total." % [level_count, total_chasm_cells])
|
||
|
|
|
||
|
|
# Populate one level's GridMap from the grid dict. Returns the count of
|
||
|
|
# chasm cells that were deliberately skipped (for reporting).
|
||
|
|
func _populate_level(grid_map: GridMap, grid: Dictionary) -> int:
|
||
|
|
var w: int = grid["width"]
|
||
|
|
var h: int = grid["height"]
|
||
|
|
var terrain: PackedByteArray = grid["terrain"]
|
||
|
|
var liquid: PackedByteArray = grid["liquid"]
|
||
|
|
|
||
|
|
var chasm_cells := 0
|
||
|
|
for y in range(h):
|
||
|
|
for x in range(w):
|
||
|
|
var idx := y * w + x
|
||
|
|
var t: int = terrain[idx]
|
||
|
|
var liq: int = liquid[idx]
|
||
|
|
# Chasm liquid renders as an actual see-through pit.
|
||
|
|
if t == T_LIQUID and liq == L_CHASM:
|
||
|
|
chasm_cells += 1
|
||
|
|
continue
|
||
|
|
var tile_id := _tile_for(t, liq)
|
||
|
|
if tile_id == -1:
|
||
|
|
continue # T_NOTHING or other empty — leave unrendered
|
||
|
|
# GridMap coords: (X, Y, Z). We want dungeon x → X, dungeon y → Z.
|
||
|
|
grid_map.set_cell_item(Vector3i(x, 0, y), tile_id)
|
||
|
|
return chasm_cells
|
||
|
|
|
||
|
|
func _tile_for(terrain: int, liquid: int) -> int:
|
||
|
|
match terrain:
|
||
|
|
T_FLOOR: return TILE_FLOOR
|
||
|
|
T_CORRIDOR: return TILE_CORRIDOR
|
||
|
|
T_DOOR: return TILE_DOOR
|
||
|
|
T_WALL: return TILE_WALL
|
||
|
|
T_BRIDGE: return TILE_BRIDGE
|
||
|
|
T_STAIRS_UP: return TILE_STAIRS_UP
|
||
|
|
T_STAIRS_DOWN: return TILE_STAIRS_DOWN
|
||
|
|
T_LIQUID:
|
||
|
|
match liquid:
|
||
|
|
L_WATER: return TILE_WATER
|
||
|
|
L_LAVA: return TILE_LAVA
|
||
|
|
L_BRIMSTONE: return TILE_BRIMSTONE
|
||
|
|
L_CHASM: return -1 # empty cell — see through to level below
|
||
|
|
_: return TILE_WATER
|
||
|
|
_: return -1 # T_NOTHING or unknown
|