You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
194 lines
5.4 KiB
194 lines
5.4 KiB
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,false)
|
|
|
|
var terrain_name="bonjour"
|
|
terrain = Terrain.new()
|
|
|
|
print(terrain.list())
|
|
|
|
if terrain.exists(terrain_name):
|
|
terrain.load(terrain_name)
|
|
else:
|
|
terrain.create(width,height,spacing,"bonjour")
|
|
|
|
if terrain.is_created() or terrain.is_loaded():
|
|
init_data()
|
|
emit_signal("world_loaded", terrain)
|
|
else:
|
|
Global.print_debug("Pas de terrain, pas de construction ...")
|
|
Global.print_debug("Pas de construction ..., pas de palais ...")
|
|
Global.print_debug("Pas de palais ..., pas de palais.")
|
|
|
|
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 = []
|
|
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)
|
|
|
|
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
|
|
|