Gen world #3

Merged
eriwyn merged 12 commits from gen_world into main 3 years ago
  1. 57
      ui/map/map.gd
  2. 10
      utils/terrain/Terrain.gd
  3. 155
      world/game.gd
  4. 3
      world/game.tscn

@ -2,49 +2,40 @@ extends Node2D
var terrain var terrain
func create_map(): func heightmap():
var river = {"size": 3, "color": "blue"} 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]))
terrain.get_edge(16).set_data("river", river) 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)
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()))
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())
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")): func draw_triangles_edges(color=Color("#000000")):
for line in terrain.get_edges_as_line(): for line in terrain.get_edges_as_line():
@ -105,7 +96,7 @@ func draw_voronoi_cells_convex_hull():
func _draw(): func _draw():
print("before drawing") print("before drawing")
draw_triangles() heightmap()
# draw_voronoi_cells() # draw_voronoi_cells()
# draw_triangles_edges() # draw_triangles_edges()
# draw_voronoi_cells_convex_hull() # draw_voronoi_cells_convex_hull()
@ -113,4 +104,4 @@ func _draw():
func _on_Game_world_loaded(game_terrain): func _on_Game_world_loaded(game_terrain):
terrain = game_terrain terrain = game_terrain
create_map() update()

@ -1,7 +1,9 @@
extends Reference extends Reference
# Build terrain from delaunay graph
class_name Terrain class_name Terrain
# Triangles iterator
class Triangles: class Triangles:
var _terrain var _terrain
var _curr var _curr
@ -164,7 +166,7 @@ class Point:
func points_around(): func points_around():
var list_points = [] var list_points = []
var incoming = _terrain._points_to_halfedges.get(_idx) 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 var outgoing_edge
while true: while true:
list_points.append(Point.new(_terrain._triangles[incoming_edge._idx], _terrain)); list_points.append(Point.new(_terrain._triangles[incoming_edge._idx], _terrain));
@ -242,6 +244,12 @@ class Edge:
func opposite(): func opposite():
return Edge.new(_terrain._halfedges[_idx], _terrain) return Edge.new(_terrain._halfedges[_idx], _terrain)
func line():
var line = []
line.append(start().point2d())
line.append(end().point2d())
return line
const terrain_file = "user://terrain.save" const terrain_file = "user://terrain.save"
var width: int var width: int

@ -10,8 +10,8 @@ export(int, 1, 30) var wavelength = 8
export(int) var border_width = 200 export(int) var border_width = 200
export(int) var terraces = 24 export(int) var terraces = 24
export(int) var terrace_height = 5 export(int) var terrace_height = 5
export(int) var mountain_height = 6 export(float) var mountain_height = 6.0 / 24.0
export(int) var river_proba = 200 export(int) var river_proba = 100
var rng = RandomNumberGenerator.new() var rng = RandomNumberGenerator.new()
var noise = OpenSimplexNoise.new() var noise = OpenSimplexNoise.new()
@ -23,24 +23,85 @@ func _ready():
noise.seed = rng.randi() noise.seed = rng.randi()
noise.octaves = octaves noise.octaves = octaves
terrain = Terrain.new(width,height,spacing,true) terrain = Terrain.new(width,height,spacing,true)
init_points_data() init_data()
print(terrain.get_point(3))
emit_signal("world_loaded", terrain) emit_signal("world_loaded", terrain)
func init_points_data(): func init_data():
for index in terrain.get_points().size(): for point in terrain.get_points():
terrain.get_point(index).set_elevation(find_elevation(terrain.get_point(index).point2d())) point.set_elevation(point_find_elevation(point.point2d()))
# points_data.append({ point.set_data("water", point_is_water(point))
# "elevation": 0, point.set_data("mountain", point_is_mountain(point))
# "used": false, point.set_data("river", point_is_river(point))
# "water": false,
# "ocean": false, fill_oceans()
# "coast": false,
# "mountain": false, for point in terrain.get_points():
# "river": false point.set_data("coast", point_is_coast(point))
# }) if point.get_data("river"):
set_river_path(point)
func find_elevation(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 = []
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 border = border_width + rng.randf_range(-20.0, 20.0)
var elevation = noise.get_noise_2d(point.x / wavelength, point.y / wavelength) var elevation = noise.get_noise_2d(point.x / wavelength, point.y / wavelength)
@ -60,11 +121,55 @@ func find_elevation(point):
elevation = min(elevation, 1) elevation = min(elevation, 1)
elevation = elevation * terraces # 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 return elevation
#
# if points_data[point_id].elevation <= 0: func triangle_is_water(triangle):
# points_data[point_id].water = true if triangle.get_data("elevation") <= 0:
# return true
# if points_data[point_id].elevation >= mountain_height: return false
# points_data[point_id].mountain = true
# 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

@ -8,6 +8,9 @@ script = ExtResource( 2 )
[node name="UI" parent="." instance=ExtResource( 1 )] [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"] [connection signal="world_loaded" from="." to="UI/Map" method="_on_Game_world_loaded"]
[editable path="UI"] [editable path="UI"]

Loading…
Cancel
Save