1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
|
extends Node
onready var noise = OpenSimplexNoise.new()
onready var rng = RandomNumberGenerator.new()
var _seed
var monuments = []
func _ready():
randomize()
self._seed = randi()
self.noise.seed = self._seed
self.noise.seed = 0
self.noise.period = 16
self.noise.persistence = 0
self.rng.seed = self._seed
func setup_monuments():
monuments.push_back(lighthouseMonument.new(Transform(Basis(),Vector3(300.0,0.0,-300.0))))
monuments.push_back(lighthouseMonument.new(Transform(Basis(),Vector3(0.0,0.0,-1000.0))))
monuments.push_back(lighthouseMonument.new(Transform(Basis(),Vector3(-500.0,0.0,-2500.0))))
monuments.push_back(DockMonument.new(Transform(Basis().rotated(Vector3.UP,PI/2.0),Vector3(-500.0,0.0,0.0))))
func rng_2dv(coords:Vector2):
self.rng.seed = hash(coords)
func gen_chunk(chunk,dummy=false):
if dummy:
return
var monument = get_monument_at_chunk(ChunkLoader.v2_coords(chunk.transform.origin))
if monument != null:
gen_monument(chunk, monument)
else:
gen_distance(chunk,chunk.get_node("gen_tree/lod_distance"))
gen_mid(chunk,chunk.get_node("gen_tree/lod_mid"))
gen_close(chunk,chunk.get_node("gen_tree/lod_close"))
func get_monument_at_chunk(chunk_coords:Vector2):
for monument in monuments:
if monument.is_chunk_in_monument(chunk_coords):
return monument
return null
func gen_monument(chunk, monument):
var inst = monument.scene.instance()
var offset_to_origin = monument.xform.origin - chunk.transform.origin
inst.transform.origin = offset_to_origin
inst.transform.basis = monument.xform.basis
chunk.add_child(inst)
func gen_distance(chunk,tree):
gen_lowres_rocks(chunk,tree)
func gen_mid(chunk,tree):
gen_rocks(chunk,tree)
func gen_close(chunk,tree):
gen_rock_hitboxes(chunk,tree)
func iterate_chunk(chunk,tree,step:Vector2,cb:FuncRef,data):
var chunk_half_size = ChunkLoader.world.chunk_half_size
var chunk_size_rounded = Vector2(chunk_half_size,chunk_half_size).snapped(step)
for x in range(-chunk_size_rounded.x,chunk_size_rounded.x,step.x):
for y in range(-chunk_size_rounded.y,chunk_size_rounded.y,step.y):
cb.call_func(chunk,tree,Vector2(x,y),data)
func make_multimesh(name,cnt,mesh):
var multi_inst = MultiMeshInstance.new()
multi_inst.name = name
var multi = MultiMesh.new()
multi_inst.multimesh = multi
multi.transform_format = MultiMesh.TRANSFORM_3D
multi.mesh = mesh
multi.instance_count = cnt
multi.visible_instance_count = 0
return multi_inst
var rock1_mesh = preload("res://world/obstacles/rock/rock_1.obj")
var rock2_mesh = preload("res://world/obstacles/rock/rock_2.obj")
var rock3_mesh = preload("res://world/obstacles/rock/rock_3.obj")
var rock4_mesh = preload("res://world/obstacles/rock/rock_4.obj")
var rock_mat = preload("res://world/obstacles/rock/rock_material.tres")
func gen_rocks(chunk,tree):
var rocks1 = make_multimesh("rocks1",100,rock1_mesh)
var rocks2 = make_multimesh("rocks2",100,rock2_mesh)
var rocks3 = make_multimesh("rocks3",100,rock3_mesh)
var rocks4 = make_multimesh("rocks4",100,rock4_mesh)
rocks1.material_override = rock_mat
rocks2.material_override = rock_mat
rocks3.material_override = rock_mat
rocks4.material_override = rock_mat
tree.add_child(rocks1)
tree.add_child(rocks2)
tree.add_child(rocks3)
tree.add_child(rocks4)
iterate_chunk(chunk, rocks1.multimesh, Vector2(10.0,10.0), funcref(self,"rock_rng"), [1,funcref(self,"make_rock")])
iterate_chunk(chunk, rocks2.multimesh, Vector2(10.0,10.0), funcref(self,"rock_rng"), [3,funcref(self,"make_rock")])
iterate_chunk(chunk, rocks3.multimesh, Vector2(10.0,10.0), funcref(self,"rock_rng"), [4,funcref(self,"make_rock")])
iterate_chunk(chunk, rocks4.multimesh, Vector2(10.0,10.0), funcref(self,"rock_rng"), [2,funcref(self,"make_rock")])
var rock_lowres_mesh = preload("res://world/obstacles/rock/rock_lowres_mesh.tres")
func gen_lowres_rocks(chunk,tree):
rock_lowres_mesh.material = rock_mat
var multi = make_multimesh("rocks",50,rock_lowres_mesh)
tree.add_child(multi)
iterate_chunk(chunk, multi.multimesh, Vector2(20.0,20.0), funcref(self,"rock_rng"), [0,funcref(self,"make_rock")])
var rock_coll = preload("res://world/obstacles/rock/rock_collision.tres")
func gen_rock_hitboxes(chunk,tree):
iterate_chunk(chunk, tree, Vector2(20.0,20.0), funcref(self,"rock_rng"), [0,funcref(self,"make_rock_hitbox")])
func rock_rng(chunk,rocks,chunk_coords:Vector2,data):
var coords = ChunkLoader.v3_coords(chunk_coords)
var basis = Basis()
var world_coords = chunk_coords + ChunkLoader.v2_coords(chunk.transform.origin)
self.rng_2dv(world_coords)
var noise_val = self.noise.get_noise_2dv(world_coords * 0.125)
#threshold to generate a rock
var noise_min_pointy = 0.4
var noise_max_pointy = 0.5
var noise_max_round = 0.7
if noise_val < noise_min_pointy:
return
var rock = self.rng.randi_range(1,4)
#choose a rock
if data[0] != 0:
if noise_val <= noise_max_pointy:
if rock != data[0]:
return
else:
if ((rock%2)+1) != data[0]:
return
#normalize noise from 0.0 to 1.0
noise_val = min(noise_val,noise_max_round)
noise_val -= noise_min_pointy
noise_val /= noise_max_round - noise_min_pointy
#random rotation
var rng_val = self.rng.randf_range(0.0,TAU)
basis = Basis(Vector3.UP,rng_val) * basis
#scale based on noise
var scale_min = 0.167
var scale_max = 0.667
var scale = lerp(scale_min,scale_max,noise_val)
basis = basis.scaled(Vector3.ONE*scale)
#scale the pointy rocks taller
if rock == 3 || rock == 4:
rng_val = self.rng.randf_range(1.0,1.25)
scale = rng_val * scale
basis = basis.scaled(Vector3(1.0,rng_val,1.0))
#normalize height
match rock:
0:
coords.y += 30.0 * scale
1:
coords.y += 31.5 * scale
2:
coords.y += 27.5 * scale
3:
coords.y += 42.5 * scale
4:
coords.y += 40.0 * scale
#shift them all slightly down
coords.y -= 5.0
data[1].call_func(rocks,Transform(basis,coords))
func make_rock(rocks,xform:Transform):
rocks.visible_instance_count += 1
rocks.set_instance_transform(rocks.visible_instance_count-1, xform)
func make_rock_hitbox(rocks,xform:Transform):
var shape = CollisionShape.new()
shape.shape = rock_coll
shape.transform = xform
rocks.add_child(shape)
|