extends Spatial signal world_loaded export(int) var width = 2000 export(int) var height = 2000 export(int) var spacing = 20 export(int, 1, 9) var octaves = 5 export(int, 1, 30) var wavelength = 8 export(int) var border_width = 200 export(int) var terraces = 24 export(int) var terrace_height = 5 export(float) var mountain_height = 6.0 / 24.0 export(int) var river_proba = 100 var rng = RandomNumberGenerator.new() var noise = OpenSimplexNoise.new() var terrain func _ready(): rng.randomize() noise.seed = rng.randi() noise.octaves = octaves terrain = Terrain.new(width,height,spacing,true) init_data() emit_signal("world_loaded", terrain) func init_data(): for point in terrain.get_points(): point.set_elevation(point_find_elevation(point.point2d())) point.set_data("water", point_is_water(point)) point.set_data("mountain", point_is_mountain(point)) point.set_data("river", point_is_river(point)) fill_oceans() for point in terrain.get_points(): if point.get_data("water") and not point.get_data("ocean"): point.set_elevation(0.1) point.set_data("coast", point_is_coast(point)) if point.get_data("river"): set_river_path(point) for triangle in terrain.get_triangles(): triangle.set_data("elevation", triangle_find_elevation(triangle)) triangle.set_data("water", triangle_is_water(triangle)) triangle.set_data("ocean", false) # TODO #1 : Get triangles around point for point in triangle.points(): if point.get_data("ocean"): triangle.set_data("ocean", true) for edge in terrain.get_edges(): edge.set_data("coast", edge_is_coast(edge)) edge.set_data("river", edge_is_river(edge)) func fill_oceans(): var stack = [] for point in terrain.get_points(): if point.point2d().x < 10 and point.get_data("water") and not point.get_data("ocean"): stack.append(point.get_index()) while stack.size(): var current_point_id = stack.pop_back() terrain.get_point(current_point_id).set_data("ocean", true) for neighbour in terrain.get_point(current_point_id).points_around(): if neighbour.get_data("water") and not neighbour.get_data("ocean"): stack.append(neighbour.get_index()) break func set_river_path(point): #TODO #2 fix rivers var start_elevation = point.get_elevation() var waypoints = [] var stack = [] stack.append(point.get_index()) var came_from = {} while stack.size(): var current_point_id = stack.pop_front() if terrain.get_point(current_point_id).get_elevation() < start_elevation: waypoints.append(current_point_id) start_elevation = terrain.get_point(current_point_id).get_elevation() stack = [] if terrain.get_point(current_point_id).get_data("ocean"): break for neighbour in terrain.get_point(current_point_id).points_around(): if not came_from.has(neighbour.get_index()): stack.append(neighbour.get_index()) came_from[neighbour.get_index()] = current_point_id var path = [] for waypoint in waypoints: var current = waypoint while current != point.get_index(): if not path.has(current): path.append(current) current = came_from[current] path.append(point.get_index()) for index in path: terrain.get_point(index).set_data("river", true) # Point func point_find_elevation(point): var border = border_width + rng.randf_range(-20.0, 20.0) var elevation = noise.get_noise_2d(point.x / wavelength, point.y / wavelength) if point.x < border: elevation -= ((border - point.x) / border) / 2.0 if point.y < border: elevation -= (border - point.y) / border if point.x > width - border: elevation -= (border - (width - point.x)) / border if point.y > height - border: elevation -= (border - (height - point.y)) / border elevation = max(elevation, -1) if elevation > 0.1: elevation = max(pow((elevation) * 1.2, 1.5), 0.1) elevation = min(elevation, 1) # elevation = elevation * terraces return elevation func point_is_water(point): if (point.get_elevation() <= 0): return true return false func point_is_mountain(point): if (point.get_elevation() >= mountain_height): return true return false func point_is_coast(point): if not point.get_data("water"): for neighbour in point.points_around(): if neighbour.get_data("ocean"): return true return false func point_is_river(point): if point.get_data("mountain") and not point.get_data("river"): var random = rng.randi_range(1, river_proba) if random == 1: return true return false # Triangle func triangle_find_elevation(triangle): var elevation = 0 for point in triangle.points(): elevation += point.get_elevation() elevation /= 3.0 return elevation func triangle_is_water(triangle): if triangle.get_data("elevation") <= 0: return true return false # Edge func edge_is_coast(edge): if edge.start().get_data("coast") and edge.end().get_data("coast") and edge.triangle().get_data("ocean"): return true return false func edge_is_river(edge): if edge.start().get_data("river") and edge.end().get_data("river"): return true return false