extends Reference class_name WorldGeneration export(int) var width = 2048 export(int) var height = 2048 export(int) var spacing = 5 export(int, 1, 9) var octaves = 5 export(int, 1, 30) var wavelength = 8 export(int) var border_width = 200 export(int) var terraces = 100 export(int) var terrace_height = 5 export(float) var mountain_height = 0.3 export(int) var river_proba = 200 var rng = RandomNumberGenerator.new() var noise = OpenSimplexNoise.new() func _init(): rng.randomize() noise.seed = rng.randi() noise.octaves = octaves if Global.terrain.exists(Global.terrain_name): var coeffs = [1] Global.loadings["world_creation"].start(coeffs, "Chargement...", 100) Global.terrain.load(Global.terrain_name) else: var coeffs = [0, 1, 2, 2, 2, 2, 2, 8] Global.loadings["world_creation"].start(coeffs, "Start", 100) Global.terrain.create(width,height,spacing,Global.terrain_name) if Global.terrain.is_created(): init_data() Global.terrain.reset_temp_data() Global.terrain.save() var terrain_mesh = TerrainMesh.new() Global.terrain.set_temp_data("mesh", terrain_mesh.create_mesh()) if Global.terrain.is_loaded(): var terrain_mesh = TerrainMesh.new() Global.terrain.set_temp_data("mesh", terrain_mesh.load_mesh()) Global.loadings["world_creation"].stop() func init_data(): Global.loadings["world_creation"].new_phase("Generation des continents...", Global.terrain.get_centers().size()) for center in Global.terrain.get_centers(): center.set_elevation(find_elevation(center.point2d())) center.set_data("temperature", find_temperature(center)) center.set_data("moisture", find_moisture(center.point2d())) if center.get_data("temperature") > 0.5: center.set_data("snow", true) if center.get_elevation() <= 0.0: center.set_data("water", true) if center.get_elevation() >= mountain_height: center.set_data("mountain", true) Global.loadings["world_creation"].increment_step() Global.loadings["world_creation"].new_phase("Remplissage des oceans...", 1) fill_oceans() remove_holes() Global.loadings["world_creation"].new_phase("Generation des biomes...", Global.terrain.get_centers().size()) for center in Global.terrain.get_centers(): center.set_data("coast", is_coast(center.to_point())) # if center.get_data("ocean"): # center.set_elevation(-1.0) center.set_data("material", "grass") if center.get_data("mountain"): center.set_data("material", "stone") if center.get_data("coast"): center.set_data("material", "sand") if ( not center.get_data("coast") and not center.get_data("mountain") and not center.get_data("ocean") and center.get_data("moisture") > 0.3 ): center.set_data("forest", true) Global.loadings["world_creation"].increment_step() # for point in Global.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 Global.terrain.get_points(): # if point.get_data("water") and not point.get_data("ocean"): # point.set_elevation(0.1) # point.set_data("water", false) # point.set_data("coast", point_is_coast(point)) # if point.get_data("river"): # set_river_path(point) # print("a") # for center in Global.terrain.get_centers(): # print("z") # center.set_elevation(find_elevation(center.point2d)) # Global.loading.increment_step() # print(center.get_elevation()) # for triangle in Global.terrain.get_triangles(): # triangle.set_elevation(find_elevation(triangle.center2d())) # # triangle.set_data("elevation", triangle_find_elevation(triangle)) # triangle.set_data("water", triangle_is_water(triangle)) # if not triangle.get_data("water"): # if triangle.get_elevation() < 0: # print(triangle.get_elevation()) # if triangle.is_water(): # triangle.set_elevation(0) # Global.loading.increment_step() # triangle.set_data("ocean", false) # for point in triangle.points(): # if point.get_data("ocean"): # triangle.set_data("ocean", true) # for edge in Global.terrain.get_edges(): # edge.set_data("coast", edge_is_coast(edge)) # edge.set_data("river", edge_is_river(edge)) 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 Global.terrain.get_point(current_point_id).get_elevation() < start_elevation: waypoints.append(current_point_id) start_elevation = Global.terrain.get_point(current_point_id).get_elevation() stack = [] if Global.terrain.get_point(current_point_id).get_data("ocean"): break for neighbour in Global.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: Global.terrain.get_point(index).set_data("river", true) # Global.terrain.get_point(index).set_data("water", true) # Point 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_elevation() <= 0.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 func 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) var nx = 2 * point.x / width - 1 var ny = 2 * point.y / height - 1 var radius = range_lerp(elevation, -1, 1, 0.8, 0.9) var distance = 1 - (1-pow(nx, 2)) * (1-pow(ny,2)) distance = sqrt(pow(nx, 2) + pow(ny, 2)) if distance > radius: elevation = (elevation - range_lerp(distance, radius, 1.0, 0.0, 1.0)) 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) / terraces return elevation func find_moisture(point): var elevation = noise.get_noise_2d((point.x + 100) / wavelength * 2, (point.y + 100) / wavelength * 2) return elevation func find_temperature(center): var poles = 4 var equator = -4 var elevation = center.get_elevation() var latitude = sin(PI * (float(center.point2d().y) / float(Global.terrain.get_parameters()["height"]))) var temperature = 40*elevation*elevation + poles + (equator-poles) * latitude return temperature func fill_oceans(): var stack = [] var first_center = null var i = 0.0 while not first_center: first_center = Global.terrain.find_point(Vector2(i, i)) i += 1.0 stack.append(first_center.get_index()) while stack.size(): var current_point_id = stack.pop_front() Global.terrain.get_point(current_point_id).set_data("ocean", true) for neighbour in Global.terrain.get_point(current_point_id).points_around(): if neighbour.get_data("water") and not neighbour.get_data("ocean"): stack.append(neighbour.get_index()) func remove_holes(): for center in Global.terrain.get_centers(): if center.get_data("water") and not center.get_data("ocean"): center.set_elevation(0.02) center.set_data("water", false) func is_coast(point): if not point.get_data("water"): for neighbour in point.points_around(): if neighbour.get_data("ocean"): return true return false # Enregistrement de la map + intégration dans la génération du monde #32 # func create_map(): # print("oui") # var viewport = Viewport.new() # viewport.size = Vector2(width, height) # var canvas = Node2D.new() # viewport.add_child(canvas) # canvas.draw_line(Vector2(0.0, 0.0), Vector2(1000.0, 1000.0), [Color("#5e4fa2")) # for center in Global.terrain.get_centers(): # var colors = Gradient.new() # colors.add_point(0.999, Color("#9e0142")) # red # colors.add_point(0.5, Color("#dc865d")) # orange # colors.add_point(0.25, Color("#fbf8b0")) # yellow # colors.add_point(0.0, Color("#89cfa5")) # green # colors.add_point(-0.999, Color("#5e4fa2")) # blue # var color = colors.interpolate(min(center.get_elevation() + 0.001, 0.999)) # # color = Color.green # if center.get_data("water"): # # var factor = pow((center.get_elevation()+1.001), 10) / 5.0 # color = Color("#5e4fa2") # if center.polygon().size() > 2: # canvas.draw_polygon(center.polygon(), PoolColorArray([color])) # Global.loading.increment_step() # var img = viewport.get_texture().get_data() # img.flip_y() # var err = img.save_png("user://terrain/heightmap.png") # print(err) # # print("non")