Now About Social Code
summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorLucas Fryzek <lucas.fryzek@fryzekconcepts.com>2024-09-20 08:38:26 +0100
committerLucas Fryzek <lucas.fryzek@fryzekconcepts.com>2024-09-20 08:38:26 +0100
commited9e5a394fa41758b739e7298852f1c9e2f70a03 (patch)
treef5f14739d873d0222b6bf5f3ea088163a26817ba /scripts
parent91f52909087dca648df82ea7fe77c2348a18c06f (diff)
bsp_level_generator: Switch to grid based approachHEADmain
Generate levels on grid and use grid to place doors. Basic POC of BSP levels is now working.
Diffstat (limited to 'scripts')
-rw-r--r--scripts/bsp_level_generator.gd110
1 files changed, 64 insertions, 46 deletions
diff --git a/scripts/bsp_level_generator.gd b/scripts/bsp_level_generator.gd
index b6cb316..7d9e268 100644
--- a/scripts/bsp_level_generator.gd
+++ b/scripts/bsp_level_generator.gd
@@ -12,6 +12,7 @@ extends Node3D
var min_room_size: int = min_dim * min_dim
enum Direction {LEFT, RIGHT}
+enum Tile {FLOOR, WALL}
class BSPNode:
var axis: int
@@ -57,59 +58,76 @@ func generate_level(axis: int, min_space: Vector2i, max_space: Vector2i, depth:
func is_leaf(node: BSPNode) -> bool:
return node.left == null and node.right == null
-
-func get_children_on_axis(node: BSPNode, axis: int, value: int) -> Array[BSPNode]:
- if is_leaf(node):
- if node.min_dims[axis] == value or node.max_dims[axis] == value:
- return [node]
- else:
- return []
- else:
- return get_children_on_axis(node.left, axis, value) + get_children_on_axis(node.right, axis, value)
-func generate_doors(node: BSPNode):
- var left_children = get_children_on_axis(node.left, node.axis, node.left.max_dims[node.axis])
- var right_children = get_children_on_axis(node.right, node.axis, node.right.min_dims[node.axis])
-
- print(left_children)
- print(right_children)
-
-func generate_geo(map: BSPNode):
- # TODO figure out where to place walls
- if map.left == null and map.right == null:
- var box = CSGBox3D.new()
- var p1 = Vector3(map.min_dims.x + wall_thickness/2, 0, map.min_dims.y + wall_thickness/2)
- var p2 = Vector3(map.max_dims.x - wall_thickness/2, 0.1, map.max_dims.y - wall_thickness/2)
- box.size = p2 - p1
- var pos_p1 = Vector3(map.min_dims.x, 0, map.min_dims.y)
- var pos_p2 = Vector3(map.max_dims.x, 0, map.max_dims.y)
- var offset = (pos_p2 - pos_p1) / 2
- box.position = p1 + offset - Vector3(0, 1, 0)
- add_child(box)
+func generate_grid(map: BSPNode, grid: Array[Tile]):
+ if is_leaf(map):
+ for y in range(map.min_dims.y + 1, map.max_dims.y - 1):
+ for x in range(map.min_dims.x + 1, map.max_dims.x - 1):
+ grid[y * width + x] = Tile.FLOOR
else:
- generate_geo(map.left)
- generate_geo(map.right)
-
- # Generate the wall between the two
- var wall = CSGBox3D.new()
- var axis = 0 if map.axis == 0 else 2
- var other_axis = 2 if axis == 0 else 0
- var max_dim = Vector3(map.max_dims.x, 0, map.max_dims.y)
- var min_dim = Vector3(map.min_dims.x, 0, map.min_dims.y)
- wall.size[map.axis] = wall_thickness
- wall.size[other_axis] = max_dim[other_axis] - min_dim[other_axis]
- wall.size[1] = 2
+ generate_grid(map.left, grid)
+ generate_grid(map.right, grid)
- var pos2d = map.left.max_dims
- var pos3d = Vector3(pos2d.x, 0, pos2d.y)
- wall.position = pos3d - (wall.size/2) + Vector3(1, 1, 1)
- add_child(wall)
+ # Look for space on dividing wall to place door
+ var other_axis = (map.axis + 1) % 2
+ var split_axis = map.left.max_dims[map.axis]
+ var have_door = false
+ var tries = 0
+ while not have_door:
+ var test_door = randi_range(map.min_dims[other_axis], map.max_dims[other_axis] - 1)
+ var door_pos = Vector2i.ZERO
+ door_pos[map.axis] = split_axis
+ door_pos[other_axis] = test_door
+
+ var room_left = door_pos
+ room_left[map.axis] -= 2
+
+ var room_right = door_pos
+ room_right[map.axis] += 1
+
+ # Check if there are two spaces to connect
+ # And ensure no door already exists in the space
+ if grid[room_left.y * width + room_left.x] == Tile.FLOOR \
+ and grid[room_right.y * width + room_right.x] == Tile.FLOOR \
+ and grid[door_pos.y * width + door_pos.x] == Tile.WALL:
+ have_door = true
+ grid[door_pos.y * width + door_pos.x] = Tile.FLOOR
+ door_pos[map.axis] -= 1
+ grid[door_pos.y * width + door_pos.x] = Tile.FLOOR
+
+ tries += 1
+ if tries > 1000:
+ print("Took too many attempts to generate a door")
+ get_tree().quit()
+
+func generate_geo(grid: Array[Tile]):
+ var csg_root = CSGCombiner3D.new()
+ for y in range(height):
+ for x in range(width):
+ var tile = grid[y * width + x]
+
+ if tile == Tile.FLOOR:
+ var box = CSGBox3D.new()
+ box.size = Vector3(1.5, 0.1, 1.5)
+ box.position = 1.5*Vector3(x, 0, y) + 0.5 * box.size
+ csg_root.add_child(box)
+ elif tile == Tile.WALL:
+ var box = CSGBox3D.new()
+ box.size = Vector3(1.5, 2, 1.5)
+ box.position = 1.5*Vector3(x, 0, y) + 0.5 * box.size
+ csg_root.add_child(box)
+
+ csg_root.use_collision = true
+ add_child(csg_root)
func _ready() -> void:
var starting_axis = randi_range(0, 1)
var min_space = Vector2i(0, 0)
var max_space = Vector2i(width, height)
var map = generate_level(starting_axis, min_space, max_space)
- generate_doors(map)
- generate_geo(map)
+ var grid: Array[Tile] = []
+ grid.resize(width * height)
+ grid.fill(Tile.WALL)
+ generate_grid(map, grid)
+ generate_geo(grid)