[gd_scene format=3 uid="uid://c2gdxshrhuv3t"] [ext_resource type="Script" uid="uid://bj1fb7syiqys7" path="res://scripts/player.gd" id="2_player"] [sub_resource type="GDScript" id="GDScript_aw1u5"] script/source = "extends Node3D # First-person demo. Generates a grid of chunks (each a 79×29 dungeon) times # level_count stacked layers. Default is 1×1 chunks × 3 levels. Bump # chunks_x / chunks_y to stress-test the renderer with larger worlds. 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_WATER := 1 const L_LAVA := 2 const L_CHASM := 3 const L_BRIMSTONE := 4 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 const CHUNK_W := 79 const CHUNK_H := 29 @export var base_seed: int = 2028 @export var depth_start: int = 20 @export var level_count: int = 3 @export var level_spacing: float = 6.0 @export var chunks_x: int = 1 @export var chunks_y: int = 1 @export var player_spawn_height: float = 1.1 @onready var levels_root: Node3D = $Levels @onready var player: CharacterBody3D = $Player @onready var fps_overlay: Node = $FPSOverlay if has_node(\"FPSOverlay\") else null var _mesh_library: MeshLibrary func _ready() -> void: var t0 := Time.get_ticks_msec() _mesh_library = MeshLibraryBuilder.build(true) var total_cells := 0 var total_chunks := 0 var spawn_world := Vector3.ZERO var spawn_found := false for level_index in range(level_count): for cy in range(chunks_y): for cx in range(chunks_x): var seed := base_seed \\ + level_index * 1000 \\ + cy * chunks_x + cx var depth := depth_start + level_index var gen := BrogueGen.new() var grid: Dictionary = gen.generate(seed, depth) gen.free() var grid_map := GridMap.new() grid_map.name = \"L%d_C%d_%d\" % [level_index, cx, cy] grid_map.mesh_library = _mesh_library grid_map.cell_size = Vector3(1, 1, 1) grid_map.position = Vector3( cx * CHUNK_W, -level_index * level_spacing, cy * CHUNK_H ) levels_root.add_child(grid_map) var cells := _populate_level(grid_map, grid) total_cells += cells total_chunks += 1 # First up-stair on level 0, chunk (0,0) is the spawn point. if not spawn_found and level_index == 0 and cx == 0 and cy == 0: var up: Vector2i = grid[\"stairs_up\"] as Vector2i if up.x >= 0: spawn_world = Vector3(up.x, player_spawn_height, up.y) spawn_found = true if not spawn_found: spawn_world = Vector3(CHUNK_W * 0.5, player_spawn_height, CHUNK_H * 0.5) player.position = spawn_world var build_ms := Time.get_ticks_msec() - t0 var info := \"%d chunks (%dx%d x %d lvls) %d placed cells build=%d ms\" % [ total_chunks, chunks_x, chunks_y, level_count, total_cells, build_ms, ] print(info) print(\"Player spawned at %s\" % spawn_world) if fps_overlay and fps_overlay.has_method(\"set_subtitle\"): fps_overlay.set_subtitle(info) # Place every non-chasm cell into the GridMap. Returns the number of cells # actually placed (excludes T_NOTHING and chasms). 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 placed := 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] if t == T_LIQUID and liq == L_CHASM: continue var tile_id := _tile_for(t, liq) if tile_id == -1: continue grid_map.set_cell_item(Vector3i(x, 0, y), tile_id) placed += 1 return placed 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 _: return TILE_WATER _: return -1 " [sub_resource type="Environment" id="Env1"] background_mode = 1 background_color = Color(0.02, 0.02, 0.03, 1) ambient_light_source = 2 ambient_light_color = Color(0.6, 0.6, 0.7, 1) ambient_light_energy = 0.35 [sub_resource type="CapsuleShape3D" id="Capsule1"] radius = 0.3 height = 1.7 [sub_resource type="GDScript" id="GDScript_5guhk"] script/source = "extends CanvasLayer # Cheap FPS + stats overlay. Attach as a child of any scene. # The parent scene can call set_subtitle(text) to add a line below the FPS. @onready var label: Label = $Label var _subtitle := \"\" func set_subtitle(text: String) -> void: _subtitle = text func _process(_delta: float) -> void: var fps := Engine.get_frames_per_second() var frame_ms := 0.0 if fps <= 0 else 1000.0 / fps var txt := \"FPS: %d %.2f ms\" % [fps, frame_ms] if _subtitle != \"\": txt += \"\\n\" + _subtitle label.text = txt " [node name="DemoLarge" type="Node3D" unique_id=1477096723] script = SubResource("GDScript_aw1u5") chunks_x = 5 chunks_y = 5 [node name="WorldEnvironment" type="WorldEnvironment" parent="." unique_id=1826007557] environment = SubResource("Env1") [node name="DirectionalLight3D" type="DirectionalLight3D" parent="." unique_id=332057448] transform = Transform3D(0.707107, -0.5, 0.5, 0, 0.707107, 0.707107, -0.707107, -0.5, 0.5, 0, 10, 0) light_color = Color(1, 0.95, 0.85, 1) light_energy = 0.9 shadow_enabled = true [node name="Levels" type="Node3D" parent="." unique_id=933491194] [node name="Player" type="CharacterBody3D" parent="." unique_id=1414808402] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 39, 1.1, 14) script = ExtResource("2_player") [node name="CollisionShape3D" type="CollisionShape3D" parent="Player" unique_id=587919818] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.85, 0) shape = SubResource("Capsule1") [node name="Camera3D" type="Camera3D" parent="Player" unique_id=680522156] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.5, 0) current = true far = 2000.0 [node name="FPSOverlay" type="CanvasLayer" parent="." unique_id=315989227] script = SubResource("GDScript_5guhk") [node name="Label" type="Label" parent="FPSOverlay" unique_id=1568814951] offset_left = 12.0 offset_top = 12.0 offset_right = 1000.0 offset_bottom = 80.0 theme_override_colors/font_color = Color(0.95, 0.95, 0.95, 1) theme_override_colors/font_outline_color = Color(0, 0, 0, 1) theme_override_constants/outline_size = 3 text = "FPS: --"