From 0abec8156bd944aa883d544850ee1187219ba943 Mon Sep 17 00:00:00 2001 From: Lucas Fryzek Date: Tue, 17 Sep 2024 22:02:33 +0100 Subject: Initial commit --- scripts/level_generator.gd | 118 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 scripts/level_generator.gd (limited to 'scripts/level_generator.gd') diff --git a/scripts/level_generator.gd b/scripts/level_generator.gd new file mode 100644 index 0000000..94a87dd --- /dev/null +++ b/scripts/level_generator.gd @@ -0,0 +1,118 @@ +extends Node3D + +@export var width: int = 10 +@export var height: int = 10 + +var room = preload("res://prefabs/round_room.tscn") +var door = preload("res://prefabs/door.tscn") + +var bounds: Vector3 = Vector3.ZERO +var astar: AStar3D + +signal astar_created + +func get_grid_index(pos: Vector2i) -> int: + return pos.y*height + pos.x + +func set_grid_index(grid: Array[int], pos: Vector2i): + # If the point lies outside the grid we return + if pos.x < 0 or pos.x >= width or pos.y < 0 or pos.y >= height: + return + + var index = get_grid_index(pos) + + # If we already set this point we exit + if grid[index] != 0: + return + + grid[index] = 1 + var new_room: Node3D = room.instantiate() + var mesh = new_room.find_child("MeshInstance3D") + # TODO can we just load and cache the bounds? + bounds = mesh.get_aabb().size + var offset_pos = Vector3(pos.x - width / 2, 0, pos.y - height / 2) + new_room.position = (offset_pos * bounds) + #print("Placing at ", pos) + add_child(new_room) + + var next = [pos + Vector2i.UP, + pos + Vector2i.LEFT, + pos + Vector2i.DOWN, + pos + Vector2i.RIGHT] + + for n in next: + var chance = randi_range(0, 1) + if chance == 0: + set_grid_index(grid, n) + +func place_door(grid: Array[int], pos: Vector2i): + var index = get_grid_index(pos) + if grid[index] == 0: + return + + var next = [pos + Vector2i.UP, + pos + Vector2i.LEFT, + pos + Vector2i.DOWN, + pos + Vector2i.RIGHT] + + var angle = -90 + for n in next: + angle += 90 + var next_index = get_grid_index(n) + if n.x < 0 or n.x >= width or n.y < 0 or n.y >= height or grid[next_index] == 0: + var new_door: Node3D = door.instantiate() + var offset_pos = Vector3(pos.x - width / 2, 0, pos.y - height / 2) + new_door.position = (offset_pos * bounds) + new_door.rotate_y(deg_to_rad(angle)) + add_child(new_door) + +func place_doors(grid: Array[int]): + for y in range(0, height): + for x in range(0, width): + place_door(grid, Vector2i(x, y)) + +func compute_astar(grid: Array[int]): + for y in range(0, height): + for x in range(0, width): + var pos = Vector2i(x, y) + var index = get_grid_index(pos) + if grid[index] == 0: + continue + var offset_pos = Vector3(pos.x - width / 2, 0, pos.y - height / 2) + astar.add_point(index, offset_pos * bounds) + + for y in range(0, height): + for x in range(0, width): + var pos = Vector2i(x, y) + var index = get_grid_index(pos) + if grid[index] == 0: + continue + + var next = [pos + Vector2i.UP, + pos + Vector2i.LEFT, + pos + Vector2i.DOWN, + pos + Vector2i.RIGHT] + for n in next: + var next_index = get_grid_index(n) + if n.x < 0 or n.x >= width or n.y < 0 or n.y >= height or grid[next_index] == 0: + continue + + astar.connect_points(index, next_index) + +# Called when the node enters the scene tree for the first time. +func _ready() -> void: + astar = AStar3D.new() + var grid: Array[int] = [0] + grid.resize(width*height) + grid.fill(0) + + var middle_x: int = width / 2 + var middle_y: int = height / 2 + + var pos = Vector2i(middle_x, middle_y) + set_grid_index(grid, pos) + + place_doors(grid) + compute_astar(grid) + + astar_created.emit(astar) -- cgit