This commit is contained in:
2026-05-14 19:11:10 +02:00
parent 2d4002bd3f
commit 52ad83a96d
15 changed files with 169 additions and 31 deletions

View File

@@ -3,6 +3,7 @@ extends Node
const ROOM_HEIGHT: float = 4.0
const WALL_THICKNESS: float = 0.4
const CORRIDOR_WIDTH: float = 4.0
const DOOR_WIDTH: float = 4.5
var rng: RandomNumberGenerator
var rooms: Array = []
@@ -17,7 +18,7 @@ func generate(parent: Node3D, seed: int, scale_difficulty: float = 1.0) -> Dicti
for i in range(room_count):
var w: float = rng.randf_range(8.0, 14.0)
var d: float = rng.randf_range(8.0, 14.0)
rooms.append({"pos": pos, "size": Vector3(w, ROOM_HEIGHT, d)})
rooms.append({"pos": pos, "size": Vector3(w, ROOM_HEIGHT, d), "openings": []})
if i == room_count - 1:
break
var corridor_len: float = rng.randf_range(4.0, 8.0)
@@ -26,23 +27,61 @@ func generate(parent: Node3D, seed: int, scale_difficulty: float = 1.0) -> Dicti
if rng.randf() < 0.5:
var rotate_left: bool = rng.randf() < 0.5
dir = dir.rotated(Vector3.UP, PI * 0.5 * (1 if rotate_left else -1))
_compute_openings()
_build_geometry(parent)
return {"rooms": rooms, "spawn": rooms[0].pos + Vector3(0, 1, 0), "boss": rooms[-1].pos}
func _compute_openings() -> void:
for i in range(rooms.size() - 1):
var rel: Vector3 = rooms[i + 1].pos - rooms[i].pos
if abs(rel.x) > abs(rel.z):
if rel.x > 0:
rooms[i].openings.append("east")
rooms[i + 1].openings.append("west")
else:
rooms[i].openings.append("west")
rooms[i + 1].openings.append("east")
else:
if rel.z > 0:
rooms[i].openings.append("south")
rooms[i + 1].openings.append("north")
else:
rooms[i].openings.append("north")
rooms[i + 1].openings.append("south")
func _build_geometry(parent: Node3D) -> void:
for r in rooms:
_build_room(parent, r.pos, r.size)
_build_room(parent, r.pos, r.size, r.openings)
for i in range(rooms.size() - 1):
_build_corridor(parent, rooms[i].pos, rooms[i + 1].pos)
func _build_room(parent: Node3D, center: Vector3, size: Vector3) -> void:
func _build_room(parent: Node3D, center: Vector3, size: Vector3, openings: Array) -> void:
_add_floor(parent, center, Vector2(size.x, size.z))
var hw: float = size.x * 0.5
var hd: float = size.z * 0.5
_add_wall(parent, center + Vector3(0, ROOM_HEIGHT * 0.5, -hd), Vector3(size.x, ROOM_HEIGHT, WALL_THICKNESS))
_add_wall(parent, center + Vector3(0, ROOM_HEIGHT * 0.5, hd), Vector3(size.x, ROOM_HEIGHT, WALL_THICKNESS))
_add_wall(parent, center + Vector3(-hw, ROOM_HEIGHT * 0.5, 0), Vector3(WALL_THICKNESS, ROOM_HEIGHT, size.z))
_add_wall(parent, center + Vector3(hw, ROOM_HEIGHT * 0.5, 0), Vector3(WALL_THICKNESS, ROOM_HEIGHT, size.z))
_add_wall_with_opening(parent, center + Vector3(0, ROOM_HEIGHT * 0.5, -hd), Vector3(size.x, ROOM_HEIGHT, WALL_THICKNESS), "north", openings, true)
_add_wall_with_opening(parent, center + Vector3(0, ROOM_HEIGHT * 0.5, hd), Vector3(size.x, ROOM_HEIGHT, WALL_THICKNESS), "south", openings, true)
_add_wall_with_opening(parent, center + Vector3(-hw, ROOM_HEIGHT * 0.5, 0), Vector3(WALL_THICKNESS, ROOM_HEIGHT, size.z), "west", openings, false)
_add_wall_with_opening(parent, center + Vector3(hw, ROOM_HEIGHT * 0.5, 0), Vector3(WALL_THICKNESS, ROOM_HEIGHT, size.z), "east", openings, false)
func _add_wall_with_opening(parent: Node3D, center: Vector3, size: Vector3, side: String, openings: Array, axis_x: bool) -> void:
if not openings.has(side):
_add_wall(parent, center, size)
return
if axis_x:
var seg_len: float = (size.x - DOOR_WIDTH) * 0.5
if seg_len <= 0.1:
return
var seg_offset: float = DOOR_WIDTH * 0.5 + seg_len * 0.5
_add_wall(parent, center + Vector3(-seg_offset, 0, 0), Vector3(seg_len, size.y, size.z))
_add_wall(parent, center + Vector3(seg_offset, 0, 0), Vector3(seg_len, size.y, size.z))
else:
var seg_len: float = (size.z - DOOR_WIDTH) * 0.5
if seg_len <= 0.1:
return
var seg_offset: float = DOOR_WIDTH * 0.5 + seg_len * 0.5
_add_wall(parent, center + Vector3(0, 0, -seg_offset), Vector3(size.x, size.y, seg_len))
_add_wall(parent, center + Vector3(0, 0, seg_offset), Vector3(size.x, size.y, seg_len))
func _build_corridor(parent: Node3D, from: Vector3, to: Vector3) -> void:
var mid: Vector3 = (from + to) * 0.5

View File

@@ -2,6 +2,7 @@ extends Node3D
const PLAYER_SCENE: PackedScene = preload("res://scenes/entities/player/player.tscn")
const ENEMY_SCENE: PackedScene = preload("res://scenes/entities/enemy/enemy.tscn")
const PORTAL_SCENE: PackedScene = preload("res://scenes/entities/portal/portal.tscn")
const GENERATOR: GDScript = preload("res://scenes/dungeon/dungeon_generator.gd")
@onready var players_root: Node3D = $EntityRoot/Players
@@ -45,9 +46,9 @@ func _populate_dungeon() -> void:
var room: Dictionary = data.rooms[i]
var n: int = 2 + (1 if GameState.dungeon_red else 0)
for j in range(n):
var off := Vector3(randf_range(-room.size.x * 0.3, room.size.x * 0.3), 0.5, randf_range(-room.size.z * 0.3, room.size.z * 0.3))
var off := Vector3(randf_range(-room.size.x * 0.3, room.size.x * 0.3), 1.0, randf_range(-room.size.z * 0.3, room.size.z * 0.3))
spawn_system.spawn_enemy_at(room.pos + off, GameState.dungeon_red, difficulty * 0.5)
spawn_system.spawn_boss_at(data.boss + Vector3(0, 0.5, 0), difficulty)
spawn_system.spawn_boss_at(data.boss + Vector3(0, 2.0, 0), difficulty)
func _spawn_player(peer_id: int) -> void:
if players_root.get_node_or_null(str(peer_id)) != null:
@@ -70,13 +71,21 @@ func _on_peer_disconnected(id: int) -> void:
if node:
node.queue_free()
func _on_boss_defeated(_b: Node) -> void:
if Net.is_host():
var t := get_tree().create_timer(2.0)
t.timeout.connect(func():
GameState.dungeon_seed = 0
_return.rpc())
func _on_boss_defeated(b: Node) -> void:
if not Net.is_host():
return
var portal: StaticBody3D = PORTAL_SCENE.instantiate()
portal.is_return = true
portal.name = "ReturnPortal"
var portals_root: Node3D = $EntityRoot/Portals
portals_root.add_child(portal, true)
var spawn_pos: Vector3 = (b as Node3D).global_position if b is Node3D else data.boss
portal.global_position = spawn_pos + Vector3(0, 1, 0)
EventBus.portal_spawned.emit(portal)
var t := get_tree().create_timer(3.0)
t.timeout.connect(_auto_return.bind(portal))
@rpc("authority", "reliable", "call_local")
func _return() -> void:
func _auto_return(portal: Node) -> void:
if is_instance_valid(portal):
portal.queue_free()
GameState.change_scene(GameState.SCENE_WORLD)