Now About Social Code
summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorLucas Fryzek <lucas.fryzek@fryzekconcepts.com>2024-09-19 21:41:34 +0100
committerLucas Fryzek <lucas.fryzek@fryzekconcepts.com>2024-09-19 21:41:34 +0100
commit91f52909087dca648df82ea7fe77c2348a18c06f (patch)
tree95a2b1aa37b0a6c063ca2628dd9850529988ab98 /scripts
parent0abec8156bd944aa883d544850ee1187219ba943 (diff)
bsp_level_generator: Add 3D floor and wall generation
Still need to figure out how to place and generator doors between rooms
Diffstat (limited to 'scripts')
-rw-r--r--scripts/bsp_level_generator.gd91
1 files changed, 64 insertions, 27 deletions
diff --git a/scripts/bsp_level_generator.gd b/scripts/bsp_level_generator.gd
index af34e0b..b6cb316 100644
--- a/scripts/bsp_level_generator.gd
+++ b/scripts/bsp_level_generator.gd
@@ -1,20 +1,27 @@
-extends Node2D
+extends Node3D
+@export_category("Level Generator")
@export var width: int = 40
@export var height: int = 40
@export var min_dim: int = 5
+@export_category("Geometry Generator")
+## Geometry generation config
+@export var wall_thickness: float = 1
+
var min_room_size: int = min_dim * min_dim
-var rects: Array[Vector4i] = []
+enum Direction {LEFT, RIGHT}
class BSPNode:
+ var axis: int
var min_dims: Vector2i
var max_dims: Vector2i
var left: BSPNode
var right: BSPNode
- func _init(p_min_dims: Vector2i, p_max_dims: Vector2i, p_left: BSPNode, p_right: BSPNode):
+ func _init(p_axis: int, p_min_dims: Vector2i, p_max_dims: Vector2i, p_left: BSPNode, p_right: BSPNode):
+ axis = p_axis
min_dims = p_min_dims
max_dims = p_max_dims
left = p_left
@@ -22,24 +29,19 @@ class BSPNode:
func generate_level(axis: int, min_space: Vector2i, max_space: Vector2i, depth: int = 0) -> BSPNode:
var dims = max_space - min_space
- if dims[axis] / 2 < min_dim:
- #rects.append(Vector4i(min_space.x, min_space.y, max_space.x, max_space.y))
- return null
-
var new_axis = (axis + 1) % 2
# 10% we stop here and just create a big room
if (depth > 2 and randi_range(0, 9) == 0) \
or dims.x * dims.y <= min_dim * min_dim \
or dims[new_axis] / 2 < min_dim:
- rects.append(Vector4i(min_space.x, min_space.y, max_space.x, max_space.y))
- return BSPNode.new(min_space, max_space, null, null)
+ return BSPNode.new(new_axis, min_space, max_space, null, null)
# Calculate min and max ranges so that a split
# doesn't create a room that violates min dimensions
var min_value = min_space[axis] + min_dim
var max_value = max_space[axis] - min_dim
var split = randi_range(min_value, max_value)
- print("Spliting axis ", axis, " at ", split)
+ #print("Spliting axis ", axis, " at ", split)
var left_min_space = min_space
var left_max_space = max_space
@@ -51,28 +53,63 @@ func generate_level(axis: int, min_space: Vector2i, max_space: Vector2i, depth:
var right_max_space = max_space
var right = generate_level(new_axis, right_min_space, right_max_space, depth + 1)
- assert((left == null and right == null) or (left != null and right != null))
+ return BSPNode.new(axis, min_space, max_space, left, right)
- if left == null and right == null:
- rects.append(Vector4i(min_space.x, min_space.y, max_space.x, max_space.y))
+func is_leaf(node: BSPNode) -> bool:
+ return node.left == null and node.right == null
- return BSPNode.new(min_space, max_space, left, right)
+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)
+ 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
+
+ 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)
+
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)
-
-func _draw():
- var mult = 1
- for rect in rects:
- var pos1 = 5*Vector2i(rect.x, rect.y)
- var pos2 = 5*Vector2i(rect.z, rect.w)
- var dims = pos2 - pos1
- draw_rect(Rect2(pos1, dims), mult*Color(0.01, 0.01, 0.01))
- draw_line(pos1, Vector2i(pos1.x, pos2.y), Color(0, 1, 0))
- draw_line(Vector2i(pos1.x, pos2.y), pos2, Color(0, 1, 0))
- draw_line(pos2, Vector2i(pos2.x, pos1.y), Color(0, 1, 0))
- draw_line(Vector2i(pos2.x, pos1.y), pos1, Color(0, 1, 0))
- mult += 2
+ generate_doors(map)
+ generate_geo(map)