diff --git a/ui/map/map.gd b/ui/map/map.gd index d08c630..f840151 100644 --- a/ui/map/map.gd +++ b/ui/map/map.gd @@ -2,53 +2,30 @@ extends Node2D var terrain -func create_map(): - - Global.print_debug("Create river") - var river = {"size": 3, "color": "blue"} - print(terrain) - print("a") - terrain.get_edge(16).set_data("river", river) - - var triangle_idx = 5 - var triangle = terrain.get_triangle(triangle_idx) - - print("Triangle index : %d" % (triangle.get_index())) - - var edges = triangle.edges() - - print("Number of edges : %d" % (edges.size())) - print() - - for edge in edges: - print("Edge index : %d" % (edge.get_index())) - var start_point = edge.start() - var end_point = edge.end() - var start = start_point.point2d() - var end = end_point.point2d() - - print("Start point index : %d" % (start_point.get_index())) - print("End point index : %d" % (end_point.get_index())) +func heightmap(): + for triangle in terrain.get_triangles(): + 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, Color("#89cfa5")) # green + colors.add_point(-0.999, Color("#5e4fa2")) # blue + var color = colors.interpolate(min(triangle.get_data("elevation"), 0.999)) + if triangle.get_data("ocean"): + var factor = pow((triangle.get_data("elevation")+1), 10) / 5.0 + color = Color("#5e4fa2") + Color(factor, factor, factor, 0.0) + if triangle.polygon().size() > 2: + draw_polygon(triangle.polygon(), PoolColorArray([color])) - print("Start point : %s" % (start)) - print("End point : %s" % (end)) - - if edge.has_key("river"): - print("Has river") - var a_river = edge.get_data("river") - print("River size : %d" % (a_river["size"])) - print("River color : %s" % (a_river["color"])) - - print() - print(terrain.get_point(5).point3d()) + var coastline = PoolVector2Array() + for edge in terrain.get_edges(): + if edge.get_data("coast"): + coastline.append(edge.line()[0]) + coastline.append(edge.line()[1]) + if edge.get_data("river"): + draw_line(edge.line()[0], edge.line()[1], Color.blue, 5.0) + draw_multiline(coastline, Color.black) - -func draw_triangles(): - for polygon in terrain.get_triangles_as_polygon(): - var color = Color(randf(), randf(), randf(), 1) - if polygon.size() > 2: - draw_polygon(polygon, PoolColorArray([color])) - func draw_triangles_edges(color=Color("#000000")): for line in terrain.get_edges_as_line(): draw_line(line[0], line[1], color) @@ -108,7 +85,7 @@ func draw_voronoi_cells_convex_hull(): func _draw(): print("before drawing") - draw_triangles() + heightmap() # draw_voronoi_cells() # draw_triangles_edges() # draw_voronoi_cells_convex_hull() @@ -116,4 +93,4 @@ func _draw(): func _on_Game_world_loaded(game_terrain): terrain = game_terrain - create_map() + update() diff --git a/utils/terrain/Terrain.gd b/utils/terrain/Terrain.gd index 7d87404..75e4cfb 100644 --- a/utils/terrain/Terrain.gd +++ b/utils/terrain/Terrain.gd @@ -169,7 +169,7 @@ class Point: func points_around(): var list_points = [] var incoming = _terrain._points_to_halfedges.get(_idx) - var incoming_edge = Point.new(incoming, _terrain) + var incoming_edge = Edge.new(incoming, _terrain) var outgoing_edge while true: list_points.append(Point.new(_terrain._triangles[incoming_edge._idx], _terrain)); @@ -248,6 +248,12 @@ class Edge: func opposite(): return Edge.new(_terrain._halfedges[_idx], _terrain) + + func line(): + var line = [] + line.append(start().point2d()) + line.append(end().point2d()) + return line # Terrain instance variables const terrain_file = "user://terrain_%s.save" diff --git a/world/game.gd b/world/game.gd index afabdcc..89fc0c7 100644 --- a/world/game.gd +++ b/world/game.gd @@ -10,8 +10,8 @@ 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(int) var mountain_height = 6 -export(int) var river_proba = 200 +export(float) var mountain_height = 6.0 / 24.0 +export(int) var river_proba = 100 var rng = RandomNumberGenerator.new() var noise = OpenSimplexNoise.new() @@ -23,28 +23,89 @@ func _ready(): noise.seed = rng.randi() noise.octaves = octaves terrain = Terrain.new(width,height,spacing,true) - init_points_data() -<<<<<<< HEAD - # print(terrain.get_point(3)) -======= - print(terrain) ->>>>>>> 7594b7d05c95e46157d72da7c31083c3111996b1 + + init_data() emit_signal("world_loaded", terrain) -func init_points_data(): +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(): - point.set_elevation(find_elevation(point.point2d())) -# points_data.append({ -# "elevation": 0, -# "used": false, -# "water": false, -# "ocean": false, -# "coast": false, -# "mountain": false, -# "river": false -# }) - -func find_elevation(point): + 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 = [] + var end + 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 = [] + end = current_point_id + 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) @@ -64,11 +125,55 @@ func find_elevation(point): elevation = min(elevation, 1) - elevation = elevation * terraces + # elevation = elevation * terraces return elevation -# -# if points_data[point_id].elevation <= 0: -# points_data[point_id].water = true -# -# if points_data[point_id].elevation >= mountain_height: -# points_data[point_id].mountain = true + +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 diff --git a/world/game.tscn b/world/game.tscn index 04f54ff..3c60c82 100644 --- a/world/game.tscn +++ b/world/game.tscn @@ -8,6 +8,9 @@ script = ExtResource( 2 ) [node name="UI" parent="." instance=ExtResource( 1 )] +[node name="Map" parent="UI" index="0"] +scale = Vector2( 0.5, 0.5 ) + [connection signal="world_loaded" from="." to="UI/Map" method="_on_Game_world_loaded"] [editable path="UI"]