Now About Social Code
summaryrefslogtreecommitdiff
path: root/scripts/bsp_level_generator.gd
blob: af34e0bd516da1e8ebacc1979a213fae9c1a85ed (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
extends Node2D

@export var width: int = 40
@export var height: int = 40
@export var min_dim: int = 5

var min_room_size: int = min_dim * min_dim

var rects: Array[Vector4i] = []

class BSPNode:
	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):
		min_dims = p_min_dims
		max_dims = p_max_dims
		left = p_left
		right = p_right

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)
		
	# 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)
	
	var left_min_space = min_space
	var left_max_space = max_space
	left_max_space[axis] = split
	var left = generate_level(new_axis, left_min_space, left_max_space, depth + 1)
	
	var right_min_space = min_space
	right_min_space[axis] = split
	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))
	
	if left == null and right == null:
		rects.append(Vector4i(min_space.x, min_space.y, max_space.x, max_space.y))
	
	return BSPNode.new(min_space, max_space, left, right)

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