feat(world): voxel chunks + procedural underwater generation + biomes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
102
scripts/world/BlockDatabase.gd
Normal file
102
scripts/world/BlockDatabase.gd
Normal file
@@ -0,0 +1,102 @@
|
||||
extends Node
|
||||
|
||||
enum BlockType {
|
||||
AIR = 0,
|
||||
WATER = 1,
|
||||
SAND = 2,
|
||||
ROCK = 3,
|
||||
CORAL_RED = 4,
|
||||
CORAL_BLUE = 5,
|
||||
KELP = 6,
|
||||
WRECK_WOOD = 7,
|
||||
ICE = 8,
|
||||
BEDROCK = 9
|
||||
}
|
||||
|
||||
const _BLOCKS: Dictionary = {
|
||||
BlockType.AIR: {
|
||||
"name": "Air",
|
||||
"color": Color(0.0, 0.0, 0.0, 0.0),
|
||||
"hardness": 0.0,
|
||||
"drops": []
|
||||
},
|
||||
BlockType.WATER: {
|
||||
"name": "Eau",
|
||||
"color": Color(0.1, 0.4, 0.8, 0.6),
|
||||
"hardness": 0.0,
|
||||
"drops": []
|
||||
},
|
||||
BlockType.SAND: {
|
||||
"name": "Sable",
|
||||
"color": Color(0.76, 0.70, 0.50, 1.0),
|
||||
"hardness": 0.5,
|
||||
"drops": [BlockType.SAND]
|
||||
},
|
||||
BlockType.ROCK: {
|
||||
"name": "Roche",
|
||||
"color": Color(0.45, 0.45, 0.45, 1.0),
|
||||
"hardness": 2.0,
|
||||
"drops": [BlockType.ROCK]
|
||||
},
|
||||
BlockType.CORAL_RED: {
|
||||
"name": "Corail Rouge",
|
||||
"color": Color(0.90, 0.25, 0.20, 1.0),
|
||||
"hardness": 0.3,
|
||||
"drops": [BlockType.CORAL_RED]
|
||||
},
|
||||
BlockType.CORAL_BLUE: {
|
||||
"name": "Corail Bleu",
|
||||
"color": Color(0.20, 0.50, 0.95, 1.0),
|
||||
"hardness": 0.3,
|
||||
"drops": [BlockType.CORAL_BLUE]
|
||||
},
|
||||
BlockType.KELP: {
|
||||
"name": "Algue",
|
||||
"color": Color(0.15, 0.60, 0.20, 1.0),
|
||||
"hardness": 0.1,
|
||||
"drops": [BlockType.KELP]
|
||||
},
|
||||
BlockType.WRECK_WOOD: {
|
||||
"name": "Bois d'Épave",
|
||||
"color": Color(0.35, 0.22, 0.12, 1.0),
|
||||
"hardness": 1.0,
|
||||
"drops": [BlockType.WRECK_WOOD]
|
||||
},
|
||||
BlockType.ICE: {
|
||||
"name": "Glace",
|
||||
"color": Color(0.75, 0.90, 1.0, 0.85),
|
||||
"hardness": 0.8,
|
||||
"drops": []
|
||||
},
|
||||
BlockType.BEDROCK: {
|
||||
"name": "Bedrock",
|
||||
"color": Color(0.15, 0.15, 0.15, 1.0),
|
||||
"hardness": -1.0,
|
||||
"drops": []
|
||||
}
|
||||
}
|
||||
|
||||
func is_solid(id: int) -> bool:
|
||||
if id == BlockType.AIR or id == BlockType.WATER or id == BlockType.KELP:
|
||||
return false
|
||||
return true
|
||||
|
||||
func get_color(id: int) -> Color:
|
||||
if _BLOCKS.has(id):
|
||||
return _BLOCKS[id]["color"]
|
||||
return Color(1.0, 0.0, 1.0, 1.0)
|
||||
|
||||
func get_block_name(id: int) -> String:
|
||||
if _BLOCKS.has(id):
|
||||
return _BLOCKS[id]["name"]
|
||||
return "Unknown"
|
||||
|
||||
func get_hardness(id: int) -> float:
|
||||
if _BLOCKS.has(id):
|
||||
return _BLOCKS[id]["hardness"]
|
||||
return 1.0
|
||||
|
||||
func get_drops(id: int) -> Array:
|
||||
if _BLOCKS.has(id):
|
||||
return _BLOCKS[id]["drops"]
|
||||
return []
|
||||
175
scripts/world/Chunk.gd
Normal file
175
scripts/world/Chunk.gd
Normal file
@@ -0,0 +1,175 @@
|
||||
extends Node3D
|
||||
class_name Chunk
|
||||
|
||||
const CHUNK_SIZE: int = 16
|
||||
|
||||
var _blocks: PackedInt32Array = PackedInt32Array()
|
||||
var _mesh_instance: MeshInstance3D = null
|
||||
var _static_body: StaticBody3D = null
|
||||
|
||||
func _ready() -> void:
|
||||
if _blocks.size() == 0:
|
||||
_blocks.resize(4096)
|
||||
|
||||
func init_blocks(data: PackedInt32Array) -> void:
|
||||
_blocks = data
|
||||
|
||||
func get_block(x: int, y: int, z: int) -> int:
|
||||
if x < 0 or x >= CHUNK_SIZE or y < 0 or y >= CHUNK_SIZE or z < 0 or z >= CHUNK_SIZE:
|
||||
return BlockDatabase.BlockType.AIR
|
||||
return _blocks[x + y * CHUNK_SIZE + z * 256]
|
||||
|
||||
func set_block(x: int, y: int, z: int, id: int) -> void:
|
||||
if x < 0 or x >= CHUNK_SIZE or y < 0 or y >= CHUNK_SIZE or z < 0 or z >= CHUNK_SIZE:
|
||||
return
|
||||
_blocks[x + y * CHUNK_SIZE + z * 256] = id
|
||||
|
||||
func generate_mesh() -> void:
|
||||
if _mesh_instance != null:
|
||||
_mesh_instance.queue_free()
|
||||
_mesh_instance = null
|
||||
if _static_body != null:
|
||||
_static_body.queue_free()
|
||||
_static_body = null
|
||||
|
||||
var st: SurfaceTool = SurfaceTool.new()
|
||||
st.begin(Mesh.PRIMITIVE_TRIANGLES)
|
||||
|
||||
var has_faces: bool = false
|
||||
|
||||
for x: int in range(CHUNK_SIZE):
|
||||
for y: int in range(CHUNK_SIZE):
|
||||
for z: int in range(CHUNK_SIZE):
|
||||
var block_id: int = get_block(x, y, z)
|
||||
if not BlockDatabase.is_solid(block_id):
|
||||
continue
|
||||
|
||||
var color: Color = BlockDatabase.get_color(block_id)
|
||||
|
||||
if not _is_opaque_at(x, y + 1, z):
|
||||
_add_face_top(st, x, y, z, color)
|
||||
has_faces = true
|
||||
if not _is_opaque_at(x, y - 1, z):
|
||||
_add_face_bottom(st, x, y, z, color)
|
||||
has_faces = true
|
||||
if not _is_opaque_at(x + 1, y, z):
|
||||
_add_face_right(st, x, y, z, color)
|
||||
has_faces = true
|
||||
if not _is_opaque_at(x - 1, y, z):
|
||||
_add_face_left(st, x, y, z, color)
|
||||
has_faces = true
|
||||
if not _is_opaque_at(x, y, z + 1):
|
||||
_add_face_front(st, x, y, z, color)
|
||||
has_faces = true
|
||||
if not _is_opaque_at(x, y, z - 1):
|
||||
_add_face_back(st, x, y, z, color)
|
||||
has_faces = true
|
||||
|
||||
if not has_faces:
|
||||
return
|
||||
|
||||
st.generate_normals()
|
||||
|
||||
var mat: StandardMaterial3D = StandardMaterial3D.new()
|
||||
mat.vertex_color_use_as_albedo = true
|
||||
mat.shading_mode = BaseMaterial3D.SHADING_MODE_PER_VERTEX
|
||||
st.set_material(mat)
|
||||
|
||||
var mesh: ArrayMesh = st.commit()
|
||||
|
||||
_mesh_instance = MeshInstance3D.new()
|
||||
_mesh_instance.mesh = mesh
|
||||
add_child(_mesh_instance)
|
||||
|
||||
var shape: ConcavePolygonShape3D = ConcavePolygonShape3D.new()
|
||||
shape.set_faces(mesh.get_faces())
|
||||
|
||||
var col_shape: CollisionShape3D = CollisionShape3D.new()
|
||||
col_shape.shape = shape
|
||||
|
||||
_static_body = StaticBody3D.new()
|
||||
_static_body.add_child(col_shape)
|
||||
add_child(_static_body)
|
||||
|
||||
func _is_opaque_at(x: int, y: int, z: int) -> bool:
|
||||
if x < 0 or x >= CHUNK_SIZE or y < 0 or y >= CHUNK_SIZE or z < 0 or z >= CHUNK_SIZE:
|
||||
return false
|
||||
return BlockDatabase.is_solid(get_block(x, y, z))
|
||||
|
||||
func _add_face_top(st: SurfaceTool, x: int, y: int, z: int, color: Color) -> void:
|
||||
var fx: float = float(x)
|
||||
var fy: float = float(y)
|
||||
var fz: float = float(z)
|
||||
st.set_color(color)
|
||||
st.add_vertex(Vector3(fx, fy + 1.0, fz))
|
||||
st.add_vertex(Vector3(fx + 1.0, fy + 1.0, fz))
|
||||
st.add_vertex(Vector3(fx + 1.0, fy + 1.0, fz + 1.0))
|
||||
st.set_color(color)
|
||||
st.add_vertex(Vector3(fx, fy + 1.0, fz))
|
||||
st.add_vertex(Vector3(fx + 1.0, fy + 1.0, fz + 1.0))
|
||||
st.add_vertex(Vector3(fx, fy + 1.0, fz + 1.0))
|
||||
|
||||
func _add_face_bottom(st: SurfaceTool, x: int, y: int, z: int, color: Color) -> void:
|
||||
var fx: float = float(x)
|
||||
var fy: float = float(y)
|
||||
var fz: float = float(z)
|
||||
st.set_color(color)
|
||||
st.add_vertex(Vector3(fx, fy, fz + 1.0))
|
||||
st.add_vertex(Vector3(fx + 1.0, fy, fz + 1.0))
|
||||
st.add_vertex(Vector3(fx + 1.0, fy, fz))
|
||||
st.set_color(color)
|
||||
st.add_vertex(Vector3(fx, fy, fz + 1.0))
|
||||
st.add_vertex(Vector3(fx + 1.0, fy, fz))
|
||||
st.add_vertex(Vector3(fx, fy, fz))
|
||||
|
||||
func _add_face_right(st: SurfaceTool, x: int, y: int, z: int, color: Color) -> void:
|
||||
var fx: float = float(x)
|
||||
var fy: float = float(y)
|
||||
var fz: float = float(z)
|
||||
st.set_color(color)
|
||||
st.add_vertex(Vector3(fx + 1.0, fy, fz))
|
||||
st.add_vertex(Vector3(fx + 1.0, fy, fz + 1.0))
|
||||
st.add_vertex(Vector3(fx + 1.0, fy + 1.0, fz + 1.0))
|
||||
st.set_color(color)
|
||||
st.add_vertex(Vector3(fx + 1.0, fy, fz))
|
||||
st.add_vertex(Vector3(fx + 1.0, fy + 1.0, fz + 1.0))
|
||||
st.add_vertex(Vector3(fx + 1.0, fy + 1.0, fz))
|
||||
|
||||
func _add_face_left(st: SurfaceTool, x: int, y: int, z: int, color: Color) -> void:
|
||||
var fx: float = float(x)
|
||||
var fy: float = float(y)
|
||||
var fz: float = float(z)
|
||||
st.set_color(color)
|
||||
st.add_vertex(Vector3(fx, fy, fz + 1.0))
|
||||
st.add_vertex(Vector3(fx, fy, fz))
|
||||
st.add_vertex(Vector3(fx, fy + 1.0, fz))
|
||||
st.set_color(color)
|
||||
st.add_vertex(Vector3(fx, fy, fz + 1.0))
|
||||
st.add_vertex(Vector3(fx, fy + 1.0, fz))
|
||||
st.add_vertex(Vector3(fx, fy + 1.0, fz + 1.0))
|
||||
|
||||
func _add_face_front(st: SurfaceTool, x: int, y: int, z: int, color: Color) -> void:
|
||||
var fx: float = float(x)
|
||||
var fy: float = float(y)
|
||||
var fz: float = float(z)
|
||||
st.set_color(color)
|
||||
st.add_vertex(Vector3(fx + 1.0, fy, fz + 1.0))
|
||||
st.add_vertex(Vector3(fx, fy, fz + 1.0))
|
||||
st.add_vertex(Vector3(fx, fy + 1.0, fz + 1.0))
|
||||
st.set_color(color)
|
||||
st.add_vertex(Vector3(fx + 1.0, fy, fz + 1.0))
|
||||
st.add_vertex(Vector3(fx, fy + 1.0, fz + 1.0))
|
||||
st.add_vertex(Vector3(fx + 1.0, fy + 1.0, fz + 1.0))
|
||||
|
||||
func _add_face_back(st: SurfaceTool, x: int, y: int, z: int, color: Color) -> void:
|
||||
var fx: float = float(x)
|
||||
var fy: float = float(y)
|
||||
var fz: float = float(z)
|
||||
st.set_color(color)
|
||||
st.add_vertex(Vector3(fx, fy, fz))
|
||||
st.add_vertex(Vector3(fx + 1.0, fy, fz))
|
||||
st.add_vertex(Vector3(fx + 1.0, fy + 1.0, fz))
|
||||
st.set_color(color)
|
||||
st.add_vertex(Vector3(fx, fy, fz))
|
||||
st.add_vertex(Vector3(fx + 1.0, fy + 1.0, fz))
|
||||
st.add_vertex(Vector3(fx, fy + 1.0, fz))
|
||||
110
scripts/world/ChunkManager.gd
Normal file
110
scripts/world/ChunkManager.gd
Normal file
@@ -0,0 +1,110 @@
|
||||
extends Node3D
|
||||
class_name ChunkManager
|
||||
|
||||
const CHUNK_SIZE: int = 16
|
||||
|
||||
@export var render_distance: int = 4
|
||||
@export var world_seed: int = 12345
|
||||
|
||||
var chunks: Dictionary = {}
|
||||
|
||||
func _ready() -> void:
|
||||
_load_initial_chunks()
|
||||
|
||||
func _load_initial_chunks() -> void:
|
||||
for cx: int in range(-render_distance, render_distance + 1):
|
||||
for cy: int in range(-render_distance, render_distance + 1):
|
||||
for cz: int in range(-render_distance, render_distance + 1):
|
||||
_load_chunk(Vector3i(cx, cy, cz))
|
||||
|
||||
func update_player_position(pos: Vector3) -> void:
|
||||
var player_chunk: Vector3i = world_to_chunk_coord(pos)
|
||||
|
||||
var to_unload: Array[Vector3i] = []
|
||||
for coord: Vector3i in chunks.keys():
|
||||
var dist: Vector3i = coord - player_chunk
|
||||
if abs(dist.x) > render_distance or abs(dist.y) > render_distance or abs(dist.z) > render_distance:
|
||||
to_unload.append(coord)
|
||||
|
||||
for coord: Vector3i in to_unload:
|
||||
_unload_chunk(coord)
|
||||
|
||||
for cx: int in range(player_chunk.x - render_distance, player_chunk.x + render_distance + 1):
|
||||
for cy: int in range(player_chunk.y - render_distance, player_chunk.y + render_distance + 1):
|
||||
for cz: int in range(player_chunk.z - render_distance, player_chunk.z + render_distance + 1):
|
||||
var coord: Vector3i = Vector3i(cx, cy, cz)
|
||||
if not chunks.has(coord):
|
||||
_load_chunk(coord)
|
||||
|
||||
func break_block(world_pos: Vector3) -> int:
|
||||
var chunk_coord: Vector3i = world_to_chunk_coord(world_pos)
|
||||
if not chunks.has(chunk_coord):
|
||||
return 0
|
||||
var chunk: Chunk = chunks[chunk_coord]
|
||||
var local: Vector3i = world_to_local(world_pos)
|
||||
var old_id: int = chunk.get_block(local.x, local.y, local.z)
|
||||
if old_id == BlockDatabase.BlockType.AIR:
|
||||
return 0
|
||||
chunk.set_block(local.x, local.y, local.z, BlockDatabase.BlockType.AIR)
|
||||
chunk.generate_mesh()
|
||||
return old_id
|
||||
|
||||
func place_block(world_pos: Vector3, block_id: int) -> bool:
|
||||
var chunk_coord: Vector3i = world_to_chunk_coord(world_pos)
|
||||
if not chunks.has(chunk_coord):
|
||||
return false
|
||||
var chunk: Chunk = chunks[chunk_coord]
|
||||
var local: Vector3i = world_to_local(world_pos)
|
||||
var current: int = chunk.get_block(local.x, local.y, local.z)
|
||||
if current != BlockDatabase.BlockType.AIR and current != BlockDatabase.BlockType.WATER:
|
||||
return false
|
||||
chunk.set_block(local.x, local.y, local.z, block_id)
|
||||
chunk.generate_mesh()
|
||||
return true
|
||||
|
||||
func get_block(world_pos: Vector3) -> int:
|
||||
var chunk_coord: Vector3i = world_to_chunk_coord(world_pos)
|
||||
if not chunks.has(chunk_coord):
|
||||
return BlockDatabase.BlockType.AIR
|
||||
var chunk: Chunk = chunks[chunk_coord]
|
||||
var local: Vector3i = world_to_local(world_pos)
|
||||
return chunk.get_block(local.x, local.y, local.z)
|
||||
|
||||
func world_to_chunk_coord(pos: Vector3) -> Vector3i:
|
||||
return Vector3i(
|
||||
int(floor(pos.x / float(CHUNK_SIZE))),
|
||||
int(floor(pos.y / float(CHUNK_SIZE))),
|
||||
int(floor(pos.z / float(CHUNK_SIZE)))
|
||||
)
|
||||
|
||||
func chunk_to_world(coord: Vector3i) -> Vector3:
|
||||
return Vector3(
|
||||
float(coord.x * CHUNK_SIZE),
|
||||
float(coord.y * CHUNK_SIZE),
|
||||
float(coord.z * CHUNK_SIZE)
|
||||
)
|
||||
|
||||
func world_to_local(pos: Vector3) -> Vector3i:
|
||||
var ix: int = int(floor(pos.x))
|
||||
var iy: int = int(floor(pos.y))
|
||||
var iz: int = int(floor(pos.z))
|
||||
return Vector3i(
|
||||
((ix % CHUNK_SIZE) + CHUNK_SIZE) % CHUNK_SIZE,
|
||||
((iy % CHUNK_SIZE) + CHUNK_SIZE) % CHUNK_SIZE,
|
||||
((iz % CHUNK_SIZE) + CHUNK_SIZE) % CHUNK_SIZE
|
||||
)
|
||||
|
||||
func _load_chunk(coord: Vector3i) -> void:
|
||||
var data: PackedInt32Array = WorldGenerator.generate_chunk(coord.x, coord.y, coord.z, world_seed)
|
||||
var chunk: Chunk = Chunk.new()
|
||||
add_child(chunk)
|
||||
chunk.init_blocks(data)
|
||||
chunk.position = chunk_to_world(coord)
|
||||
chunk.generate_mesh()
|
||||
chunks[coord] = chunk
|
||||
|
||||
func _unload_chunk(coord: Vector3i) -> void:
|
||||
if chunks.has(coord):
|
||||
var chunk: Chunk = chunks[coord]
|
||||
chunk.queue_free()
|
||||
chunks.erase(coord)
|
||||
137
scripts/world/WorldGenerator.gd
Normal file
137
scripts/world/WorldGenerator.gd
Normal file
@@ -0,0 +1,137 @@
|
||||
class_name WorldGenerator
|
||||
|
||||
const CHUNK_SIZE: int = 16
|
||||
|
||||
static func generate_chunk(chunk_x: int, chunk_y: int, chunk_z: int, seed: int) -> PackedInt32Array:
|
||||
var data: PackedInt32Array = PackedInt32Array()
|
||||
data.resize(4096)
|
||||
|
||||
var noise_surface: FastNoiseLite = FastNoiseLite.new()
|
||||
noise_surface.seed = seed
|
||||
noise_surface.noise_type = FastNoiseLite.TYPE_SIMPLEX_SMOOTH
|
||||
noise_surface.frequency = 0.015
|
||||
|
||||
var noise_biome: FastNoiseLite = FastNoiseLite.new()
|
||||
noise_biome.seed = seed + 1337
|
||||
noise_biome.noise_type = FastNoiseLite.TYPE_SIMPLEX_SMOOTH
|
||||
noise_biome.frequency = 0.004
|
||||
|
||||
var noise_detail: FastNoiseLite = FastNoiseLite.new()
|
||||
noise_detail.seed = seed + 42
|
||||
noise_detail.noise_type = FastNoiseLite.TYPE_SIMPLEX_SMOOTH
|
||||
noise_detail.frequency = 0.05
|
||||
|
||||
var noise_wreck: FastNoiseLite = FastNoiseLite.new()
|
||||
noise_wreck.seed = seed + 999
|
||||
noise_wreck.noise_type = FastNoiseLite.TYPE_CELLULAR
|
||||
noise_wreck.frequency = 0.03
|
||||
|
||||
for lx: int in range(CHUNK_SIZE):
|
||||
for lz: int in range(CHUNK_SIZE):
|
||||
var wx: int = chunk_x * CHUNK_SIZE + lx
|
||||
var wz: int = chunk_z * CHUNK_SIZE + lz
|
||||
|
||||
var surface_val: float = noise_surface.get_noise_2d(float(wx), float(wz))
|
||||
var ground_height: int = int(-20.0 + surface_val * 20.0)
|
||||
|
||||
var biome_val: float = noise_biome.get_noise_2d(float(wx), float(wz))
|
||||
var biome: int = _get_biome(biome_val, ground_height)
|
||||
|
||||
var wreck_val: float = noise_wreck.get_noise_2d(float(wx), float(wz))
|
||||
var is_wreck_center: bool = wreck_val > 0.75
|
||||
|
||||
for ly: int in range(CHUNK_SIZE):
|
||||
var wy: int = chunk_y * CHUNK_SIZE + ly
|
||||
var idx: int = lx + ly * CHUNK_SIZE + lz * 256
|
||||
|
||||
data[idx] = _get_block_at(wy, ground_height, biome, wx, wz, lx, lz,
|
||||
is_wreck_center, noise_detail, seed)
|
||||
|
||||
return data
|
||||
|
||||
static func _get_biome(biome_val: float, ground_height: int) -> int:
|
||||
if biome_val > 0.5:
|
||||
return 0
|
||||
elif biome_val > 0.0:
|
||||
return 1
|
||||
elif biome_val > -0.5:
|
||||
return 2
|
||||
else:
|
||||
return 3
|
||||
|
||||
static func _get_block_at(wy: int, ground_height: int, biome: int,
|
||||
wx: int, wz: int, lx: int, lz: int,
|
||||
is_wreck_center: bool, noise_detail: FastNoiseLite, seed: int) -> int:
|
||||
|
||||
if wy <= -60:
|
||||
return BlockDatabase.BlockType.BEDROCK
|
||||
|
||||
if wy < ground_height - 5:
|
||||
return BlockDatabase.BlockType.ROCK
|
||||
|
||||
if wy < ground_height:
|
||||
return BlockDatabase.BlockType.SAND
|
||||
|
||||
if wy == ground_height:
|
||||
return _surface_block(biome, wx, wz, noise_detail)
|
||||
|
||||
if wy == ground_height + 1:
|
||||
return _decoration_block(biome, wx, wz, noise_detail, seed)
|
||||
|
||||
if wy > ground_height + 1 and wy <= ground_height + 6:
|
||||
if biome == 1:
|
||||
var kelp_height: int = _kelp_height(wx, wz, seed)
|
||||
if wy <= ground_height + kelp_height:
|
||||
return BlockDatabase.BlockType.KELP
|
||||
|
||||
if wy > 60:
|
||||
return BlockDatabase.BlockType.AIR
|
||||
|
||||
if wy >= 58:
|
||||
var ice_noise: float = noise_detail.get_noise_2d(float(wx) * 0.5, float(wz) * 0.5)
|
||||
if ice_noise > 0.6:
|
||||
return BlockDatabase.BlockType.ICE
|
||||
return BlockDatabase.BlockType.WATER
|
||||
|
||||
if wy > ground_height:
|
||||
if is_wreck_center and biome == 3:
|
||||
var rel_y: int = wy - ground_height - 1
|
||||
if rel_y >= 0 and rel_y < 3:
|
||||
var rel_x: int = (wx % 5 + 5) % 5
|
||||
var rel_z: int = (wz % 3 + 3) % 3
|
||||
if rel_x < 5 and rel_z < 3:
|
||||
if rel_y == 0 or rel_y == 2 or rel_x == 0 or rel_x == 4 or rel_z == 0 or rel_z == 2:
|
||||
return BlockDatabase.BlockType.WRECK_WOOD
|
||||
return BlockDatabase.BlockType.WATER
|
||||
|
||||
return BlockDatabase.BlockType.WATER
|
||||
|
||||
static func _surface_block(biome: int, wx: int, wz: int, noise_detail: FastNoiseLite) -> int:
|
||||
match biome:
|
||||
0:
|
||||
return BlockDatabase.BlockType.SAND
|
||||
1:
|
||||
return BlockDatabase.BlockType.SAND
|
||||
2:
|
||||
return BlockDatabase.BlockType.ROCK
|
||||
3:
|
||||
return BlockDatabase.BlockType.SAND
|
||||
_:
|
||||
return BlockDatabase.BlockType.SAND
|
||||
|
||||
static func _decoration_block(biome: int, wx: int, wz: int, noise_detail: FastNoiseLite, seed: int) -> int:
|
||||
match biome:
|
||||
0:
|
||||
var coral_noise: float = noise_detail.get_noise_2d(float(wx + seed % 100), float(wz + seed % 100))
|
||||
if coral_noise > 0.4:
|
||||
if (wx + wz) % 2 == 0:
|
||||
return BlockDatabase.BlockType.CORAL_RED
|
||||
else:
|
||||
return BlockDatabase.BlockType.CORAL_BLUE
|
||||
_:
|
||||
pass
|
||||
return BlockDatabase.BlockType.WATER
|
||||
|
||||
static func _kelp_height(wx: int, wz: int, seed: int) -> int:
|
||||
var h: int = ((wx * 73856093) ^ (wz * 19349663) ^ seed) % 4
|
||||
return 3 + h
|
||||
Reference in New Issue
Block a user