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) print(map_config.max_lake_size) 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