summaryrefslogtreecommitdiff
path: root/scripts/lake_generator.gd
blob: 8d14e26b264da0eebf75f4fd3ff8bf01b6ceb887 (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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
extends Object

class_name LakeGenerator

var map_config : MapGeneratorResource = preload("res://resources/map_generator_resource.tres")
var _tile_map : TileMapLayer
var _lake : Array[Vector2i]
var _lake_queue : Array[Vector2i]
var _path : Array[Vector2i]

enum TileTransform {
	ROTATE_0 = 0,
	ROTATE_90 = TileSetAtlasSource.TRANSFORM_TRANSPOSE | TileSetAtlasSource.TRANSFORM_FLIP_H,
	ROTATE_180 = TileSetAtlasSource.TRANSFORM_FLIP_H | TileSetAtlasSource.TRANSFORM_FLIP_V,
	ROTATE_270 = TileSetAtlasSource.TRANSFORM_TRANSPOSE | TileSetAtlasSource.TRANSFORM_FLIP_V,
}

func _init(tile_map_layer: TileMapLayer, path : Array[Vector2i]):
	_tile_map = tile_map_layer
	_path = path

func generate_lake():
	var tile : Vector2i

	while 1:
		tile.x = randi_range(0, map_config.grid_width - 1)
		tile.y = randi_range(0, map_config.grid_height - 1)

		if _is_expansion_valid(tile):
			break

	_visit_tile(tile)
	while _lake.size() < map_config.max_lake_size:
		tile = _pop_tile()
		# no room to grow
		if tile == Vector2i(-1, -1):
			break

		var adj_tiles : Array[Vector2i] = _get_adjacent_tiles(tile)
		for i in adj_tiles:
			_try_expand(i)

	draw_lake()

func draw_lake():
	for i in _lake:
		var score : int = _get_tile_score(i)

		var atlas_coords : Vector2i = map_config.atlas_coords["WATER_MIDDLE"]
		var rot : TileTransform = TileTransform.ROTATE_0

		match score:
			1, 3, 129, 131:
				atlas_coords = map_config.atlas_coords["WATER_END"]
				rot = TileTransform.ROTATE_180
			4, 6, 12, 14:
				atlas_coords = map_config.atlas_coords["WATER_END"]
				rot = TileTransform.ROTATE_270
			16, 24, 48, 56:
				atlas_coords = map_config.atlas_coords["WATER_END"]
			64, 96, 192, 224:
				atlas_coords = map_config.atlas_coords["WATER_END"]
				rot = TileTransform.ROTATE_90
			7, 135, 15, 143:
				atlas_coords = map_config.atlas_coords["WATER_BEND_OUTER"]
				rot = TileTransform.ROTATE_270
			28, 30, 60, 62:
				atlas_coords = map_config.atlas_coords["WATER_BEND_OUTER"]
			112, 120, 240, 248:
				atlas_coords = map_config.atlas_coords["WATER_BEND_OUTER"]
				rot = TileTransform.ROTATE_90
			193, 195, 225, 227:
				atlas_coords = map_config.atlas_coords["WATER_BEND_OUTER"]
				rot = TileTransform.ROTATE_180
			199, 207, 231, 239:
				atlas_coords = map_config.atlas_coords["WATER_SHORE"]
				rot = TileTransform.ROTATE_270
			31, 63, 159, 191:
				atlas_coords = map_config.atlas_coords["WATER_SHORE"]
			124, 126, 252, 254:
				atlas_coords = map_config.atlas_coords["WATER_SHORE"]
				rot = TileTransform.ROTATE_90
			241, 243, 249, 251:
				atlas_coords = map_config.atlas_coords["WATER_SHORE"]
				rot = TileTransform.ROTATE_180
			68, 100, 196:
				atlas_coords = map_config.atlas_coords["WATER_STRAIGHT"]
				rot = TileTransform.ROTATE_90
			17:
				atlas_coords = map_config.atlas_coords["WATER_STRAIGHT"]

		_display_tile(atlas_coords, rot, i)

func _try_expand(tile : Vector2i):
	if _is_expansion_valid(tile):
		_visit_tile(tile)

func _is_expansion_valid(tile : Vector2i) -> bool:
	return !(_is_tile_oob(tile) || _lake.has(tile) || _path.has(tile))

func _is_tile_oob(tile : Vector2i):
	return tile.y < 0 || tile.y > map_config.grid_height - 1 || tile.x < 0 || tile.x > map_config.grid_width - 1

func _visit_tile(tile: Vector2i):
	_lake_queue.append(tile)
	_lake.append(tile)

func _pop_tile() -> Vector2i:
	if _lake_queue.size() > 0:
		return _lake_queue.pop_front()
	return Vector2i(-1, -1)

func _get_adjacent_tiles(tile: Vector2i) -> Array[Vector2i]:
	var adj: Array[Vector2i] = []
	var dirs: Array = [Vector2i(0, -1), Vector2i(0, 1), Vector2i(-1, 0), Vector2i(1, 0)]

	for dir in dirs:
		var n = tile + dir
		adj.append(n)
	
	return adj

func _display_tile(coords : Vector2i, rot : TileTransform, pos : Vector2i):
	_tile_map.set_cell(pos, 0, coords, rot)

func _get_tile_score(tile : Vector2i) -> int:
	var score : int = 0
	var x : int = tile.x
	var y : int = tile.y
	
	score += 1 if _lake.has(Vector2i(x, y - 1)) else 0
	score += 2 if _lake.has(Vector2i(x + 1, y - 1)) else 0
	score += 4 if _lake.has(Vector2i(x + 1, y)) else 0
	score += 8 if _lake.has(Vector2i(x + 1, y + 1)) else 0
	score += 16 if _lake.has(Vector2i(x, y + 1)) else 0
	score += 32 if _lake.has(Vector2i(x - 1, y + 1)) else 0
	score += 64 if _lake.has(Vector2i(x - 1, y)) else 0
	score += 128 if _lake.has(Vector2i(x - 1, y - 1)) else 0
	
	return score