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.
 
Gridmap/scripts/WorldGeneration.gd

222 lines
5.7 KiB

extends Control
@export var world_width = 1024
@export var world_height = 512
@export var min_continent = 5
@export var max_continent = 5
@export var min_area = 0.5
@export var max_area = 2.0
@export var min_ratio = -1.0
@export var max_ratio = 1.0
@export var ocean_ratio = 0
@export var nbr_rect_position = 10000
@export var max_intersection_area = 1000.0
@export var mountain_frequency = 1.5 # higher number means less mountains
@export var world_elevation = 10
@export var max_moisture = 2
@export var details = 2
@export var coasts_thickness = 0.055
var heightmap: Array
var moisturemap: Array
var oceanmap: Array
var coastmap: Array
var rivers: Array
var continents: Array
var nbr_continent
var list_continents = []
var list_rect_continents = []
var blocs: Array
var noise = FastNoiseLite.new()
func _ready():
Global.world.width = world_width
Global.world.height = world_height
noise.seed = randi()
noise.fractal_lacunarity = details
noise.frequency = 0.005
init_maps()
init_blocs()
create_continents()
for continent in continents:
fill_continent(continent)
set_oceans()
set_coasts()
fix_heightmap()
set_moisture()
set_blocs()
Global.world.heightMap = heightmap
Global.world.moistureMap = moisturemap
Global.world.blocs = blocs
set_entities()
get_tree().change_scene_to_file("scenes/Game.tscn")
func init_maps():
for x in world_width:
heightmap.append([])
oceanmap.append([])
coastmap.append([])
moisturemap.append([])
for y in world_height:
heightmap[x].append([])
heightmap[x][y] = 0
oceanmap[x].append([])
oceanmap[x][y] = 0
coastmap[x].append([])
coastmap[x][y] = 0
moisturemap[x].append([])
moisturemap[x][y] = 0
func create_continents():
var america = Rect2i(Vector2i(0, 0), Vector2i(world_width / 4, world_height))
continents.append(america)
var antarctica = Rect2i(Vector2i(world_width / 4, world_height / 2), Vector2i(3 * world_width / 4, world_height / 2))
continents.append(antarctica)
var africa = Rect2i(Vector2i(world_width / 4, 3 * world_height / 8), Vector2i(3 * world_width / 8, 3 * world_height / 8))
continents.append(africa)
var europa = Rect2i(Vector2i(3 * world_width / 8, 10), Vector2i(world_width / 4, world_height / 2))
continents.append(europa)
var asia = Rect2i(Vector2i(4 * world_width / 9, world_height / 8), Vector2i(world_width / 2, 3 * world_height / 8))
continents.append(asia)
func fill_continent(continent: Rect2i):
for x in continent.size.x:
for y in continent.size.y:
# set rectange radius
var center = Vector2(float(continent.size.x) / 2.0, float(continent.size.y) / 2.0)
var distance_x = abs(float(x) - center.x) / center.x
var distance_y = abs(float(y) - center.y) / center.y
var distance = sqrt(pow(distance_x, 2) + pow(distance_y, 2))
distance = remap(distance, 0, sqrt(2), 0, 1) * 1.2
# set height
var height = noise.get_noise_2d(x, y)
height = remap(height, -1, 1, 0, 1)
height -= distance
if height > 0:
var current_height = heightmap[continent.position.x + x][continent.position.y + y]
height = pow(height * 1.2, mountain_frequency)
height = remap(height, 0, 1, 1, world_elevation)
heightmap[continent.position.x + x][continent.position.y + y] = max(current_height, height)
if height > heightmap[continent.position.x + x][continent.position.y + y]:
heightmap[continent.position.x + x][continent.position.y + y] = height
elif height > 0 - coasts_thickness:
coastmap[x + continent.position.x][y + continent.position.y] = 1
func set_oceans():
var stack = []
var first_coord = Vector2i(0, 0)
stack.append(first_coord)
while stack.size():
var coord = stack.pop_back()
oceanmap[coord.x][coord.y] = 1
for neighbour in neighbours(coord).values():
if heightmap[neighbour.x][neighbour.y] == 0 and oceanmap[neighbour.x][neighbour.y] == 0:
stack.append(neighbour)
for x in world_width:
for y in world_height:
if heightmap[x][y] == 0 and not oceanmap[x][y]:
heightmap[x][y] = 2
func set_coasts():
for x in world_width:
for y in world_height:
if coastmap[x][y] and heightmap[x][y] == 0:
heightmap[x][y] = 1
pass
func set_moisture():
for x in world_width:
for y in world_height:
moisturemap[x][y] = remap(noise.get_noise_2d(x + 6789, y + 5927), -1, 1, 0, max_moisture)
func neighbours(coord: Vector2i):
var neighbours: Dictionary
if coord.x + 1 < world_width:
neighbours.right = Vector2i(coord.x + 1, coord.y)
if coord.y + 1 < world_height :
neighbours.bottom = Vector2i(coord.x, coord.y + 1)
if coord.x - 1 >= 0:
neighbours.left = Vector2i(coord.x - 1, coord.y)
if coord.y - 1 >= 0:
neighbours.top = Vector2i(coord.x, coord.y - 1)
return neighbours
func fix_heightmap():
for x in world_width:
for y in world_height:
heightmap[x][y] = ceil(heightmap[x][y])
# if heightmap[x][y] > 4:
# mountain_blocs.append(Vector2i(x, y))
func init_blocs():
for x in world_width:
blocs.append([])
for y in world_height:
var bloc = {
"type": 0,
"entity": -1
}
blocs[x].append(bloc)
func set_blocs():
for x in world_width:
for y in world_height:
if not blocs[x][y].type:
if heightmap[x][y] > 0:
blocs[x][y].type = Global.blocs.SAND
if heightmap[x][y] > 1:
blocs[x][y].type = Global.blocs.GRASS
if heightmap[x][y] > 4:
blocs[x][y].type = Global.blocs.STONE
if heightmap[x][y] > 6:
blocs[x][y].type = Global.blocs.SNOW
return blocs
func set_entities():
for x in Global.world.width:
for z in Global.world.height:
var moisture = Global.world.get_moisture(Vector2i(x, z))
var height = Global.world.get_height(Vector2i(x, z))
if height > 1:
if moisture > 1.5 and randi_range(1, 10) == 1:
Global.world.add_entity("OakTree", Vector2i(x, z))