Implements procedural ground tile generation
Adds procedural ground tile generation with chunking for improved performance. Includes: - Ground tile entity with debug text and cell information - Grass and tree placement based on cell data - Ground shader for visual representation - Chunk loading and unloading system based on player position
This commit is contained in:
parent
95665f54eb
commit
b5bf7619e6
21 changed files with 532 additions and 149 deletions
16
Entities/GroundTile/GroundTile.gdshader
Normal file
16
Entities/GroundTile/GroundTile.gdshader
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
shader_type spatial;
|
||||||
|
|
||||||
|
uniform sampler2D noise_texture : filter_linear_mipmap;
|
||||||
|
uniform sampler2D gradient_texture : filter_linear;
|
||||||
|
uniform float noise_scale : hint_range(0.1, 10.0) = 1.0;
|
||||||
|
uniform float roughness_value : hint_range(0.0, 1.0) = 0.8;
|
||||||
|
|
||||||
|
void fragment() {
|
||||||
|
vec2 noise_uv = UV * noise_scale;
|
||||||
|
float noise_val = texture(noise_texture, noise_uv).r;
|
||||||
|
|
||||||
|
vec4 earth_color = texture(gradient_texture, vec2(noise_val, 0.0));
|
||||||
|
|
||||||
|
ALBEDO = earth_color.rgb;
|
||||||
|
ROUGHNESS = roughness_value;
|
||||||
|
}
|
||||||
1
Entities/GroundTile/GroundTile.gdshader.uid
Normal file
1
Entities/GroundTile/GroundTile.gdshader.uid
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
uid://cuew4u0k6md1v
|
||||||
|
|
@ -1,43 +1,84 @@
|
||||||
[gd_scene load_steps=7 format=3 uid="uid://bwcevwwphdvq"]
|
[gd_scene load_steps=18 format=3 uid="uid://bwcevwwphdvq"]
|
||||||
|
|
||||||
[ext_resource type="Script" uid="uid://bq7hia2dit80y" path="res://Entities/GroundTile/ground_tile.gd" id="1_uwxqs"]
|
[ext_resource type="Script" uid="uid://bq7hia2dit80y" path="res://Entities/GroundTile/ground_tile.gd" id="1_uwxqs"]
|
||||||
[ext_resource type="PackedScene" uid="uid://ckesk3bs6g7tt" path="res://Stages/Test3D/assets/fish.glb" id="2_h4g11"]
|
[ext_resource type="PackedScene" uid="uid://ckesk3bs6g7tt" path="res://Stages/Test3D/assets/fish.glb" id="2_h4g11"]
|
||||||
|
[ext_resource type="ArrayMesh" uid="uid://duj6747nq4qsk" path="res://Stages/Test3D/assets/stylizedGrassMeshes/grass.res" id="3_8mhad"]
|
||||||
|
[ext_resource type="Script" uid="uid://cacp8ncwuofuj" path="res://Entities/GroundTile/scripts/grass.gd" id="3_224hx"]
|
||||||
|
[ext_resource type="Material" uid="uid://b1miqvl8lus75" path="res://Stages/Test3D/GrassMaterialOverride.tres" id="3_f37ob"]
|
||||||
|
[ext_resource type="Script" uid="uid://btju6b83mvgvk" path="res://Entities/GroundTile/scripts/grass_multimesh.gd" id="4_3wpcb"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://dgvycnw8hpebx" path="res://Stages/Test3D/assets/tree-tall.glb" id="6_7lc7k"]
|
||||||
|
[ext_resource type="Script" uid="uid://cqko4m7cbxsfb" path="res://Entities/GroundTile/scripts/trees.gd" id="7_7lc7k"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://cccqxa0y0ksju" path="res://Stages/Test3D/assets/tree-trunk.glb" id="7_jysav"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://cwfp2cf8no8fi" path="res://Stages/Test3D/assets/tree.glb" id="8_q0r4p"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://bwdibgbi3ycqn" path="res://Stages/Test3D/assets/tree-autumn-tall.glb" id="12_4hjaq"]
|
||||||
|
|
||||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_oqd8f"]
|
[sub_resource type="ViewportTexture" id="ViewportTexture_h4g11"]
|
||||||
albedo_color = Color(0.171, 0.57, 0.24415, 1)
|
viewport_path = NodePath("DebugText/DebugTextViewport")
|
||||||
|
|
||||||
|
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_f37ob"]
|
||||||
|
albedo_color = Color(0.706084, 0.408439, 0.274016, 1)
|
||||||
|
metallic = 1.0
|
||||||
|
|
||||||
[sub_resource type="PlaneMesh" id="PlaneMesh_oqd8f"]
|
[sub_resource type="PlaneMesh" id="PlaneMesh_oqd8f"]
|
||||||
|
|
||||||
[sub_resource type="BoxShape3D" id="BoxShape3D_h4g11"]
|
[sub_resource type="BoxShape3D" id="BoxShape3D_h4g11"]
|
||||||
size = Vector3(2, 2, 2)
|
size = Vector3(2, 2, 2)
|
||||||
|
|
||||||
[sub_resource type="ViewportTexture" id="ViewportTexture_h4g11"]
|
[sub_resource type="MultiMesh" id="MultiMesh_3wpcb"]
|
||||||
viewport_path = NodePath("DebugText")
|
transform_format = 1
|
||||||
|
mesh = ExtResource("3_8mhad")
|
||||||
|
|
||||||
|
[sub_resource type="PlaneMesh" id="PlaneMesh_f37ob"]
|
||||||
|
flip_faces = true
|
||||||
|
|
||||||
[node name="GroundTile" type="Node3D"]
|
[node name="GroundTile" type="Node3D"]
|
||||||
script = ExtResource("1_uwxqs")
|
script = ExtResource("1_uwxqs")
|
||||||
|
|
||||||
|
[node name="DebugText" type="Node3D" parent="."]
|
||||||
|
visible = false
|
||||||
|
|
||||||
|
[node name="DebugTextViewport" type="SubViewport" parent="DebugText"]
|
||||||
|
size = Vector2i(50, 50)
|
||||||
|
|
||||||
|
[node name="DebugTextLabel" type="Label" parent="DebugText/DebugTextViewport"]
|
||||||
|
offset_right = 40.0
|
||||||
|
offset_bottom = 23.0
|
||||||
|
text = "Hello world"
|
||||||
|
|
||||||
|
[node name="DebugTextBillboard" type="Sprite3D" parent="DebugText"]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.0461426, 0.199493, 0.0660986)
|
||||||
|
texture = SubResource("ViewportTexture_h4g11")
|
||||||
|
|
||||||
[node name="Ground" type="MeshInstance3D" parent="."]
|
[node name="Ground" type="MeshInstance3D" parent="."]
|
||||||
material_override = SubResource("StandardMaterial3D_oqd8f")
|
material_override = SubResource("StandardMaterial3D_f37ob")
|
||||||
|
cast_shadow = 0
|
||||||
mesh = SubResource("PlaneMesh_oqd8f")
|
mesh = SubResource("PlaneMesh_oqd8f")
|
||||||
|
|
||||||
[node name="GroundCollision" type="StaticBody3D" parent="."]
|
[node name="GroundCollision" type="StaticBody3D" parent="Ground"]
|
||||||
|
|
||||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="GroundCollision"]
|
[node name="CollisionShape3D" type="CollisionShape3D" parent="Ground/GroundCollision"]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1, 0)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1, 0)
|
||||||
shape = SubResource("BoxShape3D_h4g11")
|
shape = SubResource("BoxShape3D_h4g11")
|
||||||
|
|
||||||
[node name="fish2" parent="." instance=ExtResource("2_h4g11")]
|
[node name="fish2" parent="." instance=ExtResource("2_h4g11")]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.00713956, 0, 0.0313604)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.00713956, 0, 0.0313604)
|
||||||
|
|
||||||
[node name="DebugText" type="SubViewport" parent="."]
|
[node name="Grass" type="Node3D" parent="."]
|
||||||
size = Vector2i(50, 50)
|
script = ExtResource("3_224hx")
|
||||||
|
|
||||||
[node name="DebugTextLabel" type="Label" parent="DebugText"]
|
[node name="GrassMultimesh" type="MultiMeshInstance3D" parent="Grass"]
|
||||||
offset_right = 40.0
|
material_override = ExtResource("3_f37ob")
|
||||||
offset_bottom = 23.0
|
cast_shadow = 0
|
||||||
text = "Hello world"
|
multimesh = SubResource("MultiMesh_3wpcb")
|
||||||
|
script = ExtResource("4_3wpcb")
|
||||||
|
|
||||||
[node name="Sprite3D" type="Sprite3D" parent="."]
|
[node name="GrassTarget" type="MeshInstance3D" parent="Grass"]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -0.0939356)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.0111763, 0)
|
||||||
texture = SubResource("ViewportTexture_h4g11")
|
mesh = SubResource("PlaneMesh_f37ob")
|
||||||
|
|
||||||
|
[node name="Trees" type="Node3D" parent="."]
|
||||||
|
script = ExtResource("7_7lc7k")
|
||||||
|
tree_scenes = Array[PackedScene]([ExtResource("8_q0r4p"), ExtResource("6_7lc7k"), ExtResource("12_4hjaq"), ExtResource("8_q0r4p"), ExtResource("8_q0r4p"), ExtResource("8_q0r4p"), ExtResource("8_q0r4p")])
|
||||||
|
|
||||||
|
[node name="tree-trunk2" parent="." instance=ExtResource("7_jysav")]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.554052, 0, 0.470964)
|
||||||
|
|
|
||||||
BIN
Entities/GroundTile/assets/Dirt_05-256x256.png
(Stored with Git LFS)
Normal file
BIN
Entities/GroundTile/assets/Dirt_05-256x256.png
(Stored with Git LFS)
Normal file
Binary file not shown.
35
Entities/GroundTile/assets/Dirt_05-256x256.png.import
Normal file
35
Entities/GroundTile/assets/Dirt_05-256x256.png.import
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://b8pca7c2vlwaa"
|
||||||
|
path.s3tc="res://.godot/imported/Dirt_05-256x256.png-df3829dddfb4eeab82c63b0845e8a300.s3tc.ctex"
|
||||||
|
metadata={
|
||||||
|
"imported_formats": ["s3tc_bptc"],
|
||||||
|
"vram_texture": true
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Entities/GroundTile/assets/Dirt_05-256x256.png"
|
||||||
|
dest_files=["res://.godot/imported/Dirt_05-256x256.png-df3829dddfb4eeab82c63b0845e8a300.s3tc.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=2
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=true
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=0
|
||||||
|
|
@ -1,26 +1,29 @@
|
||||||
|
# GroundTile.gd
|
||||||
|
class_name GroundTile
|
||||||
extends Node3D
|
extends Node3D
|
||||||
|
|
||||||
@onready var debug_text: Label = $DebugText/DebugTextLabel
|
@onready var debug_text: Label = $DebugText/DebugTextViewport/DebugTextLabel
|
||||||
|
|
||||||
var grid_x: int
|
var grid_x: int
|
||||||
var grid_z: int
|
var grid_z: int
|
||||||
var cell_info: CellDataResource
|
var cell_info: CellDataResource = null:
|
||||||
|
set(value):
|
||||||
|
cell_info = value
|
||||||
|
if cell_info != null:
|
||||||
|
cell_info_updated.emit(value)
|
||||||
|
|
||||||
|
var rng: RandomClass = RandomClass.new()
|
||||||
|
|
||||||
|
signal cell_info_updated(value)
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
if cell_info != null:
|
if cell_info != null:
|
||||||
update_text_label()
|
update_text_label()
|
||||||
|
rng.set_seed(cell_info.cell_seed)
|
||||||
|
|
||||||
func set_grid_location(x, z) -> void:
|
func set_grid_location(x, z) -> void:
|
||||||
grid_x = x
|
grid_x = x
|
||||||
grid_z = z
|
grid_z = z
|
||||||
cell_info = MapData.get_map_data(grid_x, grid_z)
|
cell_info = MapData.get_map_data(grid_x, grid_z)
|
||||||
|
|
||||||
var debug_dict = {}
|
|
||||||
if cell_info.get_script():
|
|
||||||
var script_properties = cell_info.get_script().get_script_property_list()
|
|
||||||
for prop in script_properties:
|
|
||||||
debug_dict[prop.name] = cell_info.get(prop.name)
|
|
||||||
Log.pr(debug_dict)
|
|
||||||
|
|
||||||
func update_text_label() -> void:
|
func update_text_label() -> void:
|
||||||
debug_text.text = str(grid_x) + ', ' + str(grid_z) + ', ' + str(cell_info.cell_seed)
|
debug_text.text = str(grid_x) + ', ' + str(grid_z) + ', ' + str(cell_info.cell_seed)
|
||||||
|
|
|
||||||
50
Entities/GroundTile/scripts/grass.gd
Normal file
50
Entities/GroundTile/scripts/grass.gd
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
# GrassController.gd
|
||||||
|
extends Node3D
|
||||||
|
class_name GrassController
|
||||||
|
|
||||||
|
# 229379
|
||||||
|
|
||||||
|
var parent_node: GroundTile = null
|
||||||
|
var grass_density: float = 0.5
|
||||||
|
var grass_instance_range: int = 10
|
||||||
|
|
||||||
|
signal grass_data_ready()
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
# Use call_deferred to ensure parent is fully ready
|
||||||
|
call_deferred("_setup_connections")
|
||||||
|
|
||||||
|
func _setup_connections() -> void:
|
||||||
|
parent_node = get_parent() as GroundTile
|
||||||
|
if parent_node == null:
|
||||||
|
Log.pr("Error: Parent node is not a GroundTile!")
|
||||||
|
return
|
||||||
|
|
||||||
|
parent_node.cell_info_updated.connect(_on_parent_data_changed)
|
||||||
|
|
||||||
|
# Check if cell_info already exists and process it
|
||||||
|
if parent_node.cell_info != null:
|
||||||
|
_on_parent_data_changed(parent_node.cell_info)
|
||||||
|
|
||||||
|
func _on_parent_data_changed(value):
|
||||||
|
if value == null:
|
||||||
|
return
|
||||||
|
|
||||||
|
grass_density = value.vegetation_density
|
||||||
|
|
||||||
|
update_grass_density()
|
||||||
|
|
||||||
|
grass_data_ready.emit()
|
||||||
|
|
||||||
|
func update_grass_density() -> void:
|
||||||
|
if parent_node == null or parent_node.rng == null:
|
||||||
|
return
|
||||||
|
|
||||||
|
if grass_density > 0.8:
|
||||||
|
grass_instance_range = parent_node.rng.randi_range(100, 500)
|
||||||
|
elif grass_density > 0.6:
|
||||||
|
grass_instance_range = parent_node.rng.randi_range(30, 50)
|
||||||
|
elif grass_density > 0.3:
|
||||||
|
grass_instance_range = parent_node.rng.randi_range(5, 20)
|
||||||
|
else:
|
||||||
|
grass_instance_range = parent_node.rng.randi_range(0, 1)
|
||||||
1
Entities/GroundTile/scripts/grass.gd.uid
Normal file
1
Entities/GroundTile/scripts/grass.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
uid://cacp8ncwuofuj
|
||||||
66
Entities/GroundTile/scripts/grass_multimesh.gd
Normal file
66
Entities/GroundTile/scripts/grass_multimesh.gd
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
# GrassMultiMesh.gd (assuming this is your MultiMeshInstance3D script)
|
||||||
|
extends MultiMeshInstance3D
|
||||||
|
|
||||||
|
var mm: MultiMesh
|
||||||
|
@onready var parent_node: GrassController
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
# Use call_deferred to ensure proper initialization order
|
||||||
|
call_deferred("_setup_connections")
|
||||||
|
|
||||||
|
func _setup_connections() -> void:
|
||||||
|
parent_node = get_parent() as GrassController
|
||||||
|
if parent_node == null:
|
||||||
|
Log.pr("Error: Parent node is not a GrassController!")
|
||||||
|
return
|
||||||
|
|
||||||
|
parent_node.grass_data_ready.connect(_on_grass_data_ready)
|
||||||
|
Log.pr("Connected to grass_data_ready signal")
|
||||||
|
|
||||||
|
func _on_grass_data_ready():
|
||||||
|
Log.pr("Received grass_data_ready signal, setting up multimesh")
|
||||||
|
setup_multimesh()
|
||||||
|
|
||||||
|
func setup_multimesh() -> void:
|
||||||
|
if parent_node == null:
|
||||||
|
Log.pr("Error: Parent node not available in setup_multimesh")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Load the mesh resource directly
|
||||||
|
var mesh = load("res://Stages/Test3D/assets/stylizedGrassMeshes/grass2_mesh.res")
|
||||||
|
if mesh == null:
|
||||||
|
Log.pr("Error: Could not load grass mesh")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Create new MultiMesh instance
|
||||||
|
mm = MultiMesh.new()
|
||||||
|
|
||||||
|
# Configure the MultiMesh
|
||||||
|
mm.transform_format = MultiMesh.TRANSFORM_3D
|
||||||
|
mm.instance_count = parent_node.grass_instance_range
|
||||||
|
mm.mesh = mesh
|
||||||
|
|
||||||
|
Log.pr("Setting up MultiMesh with " + str(mm.instance_count) + " instances")
|
||||||
|
|
||||||
|
# Generate random positions for grass
|
||||||
|
for i in range(mm.instance_count):
|
||||||
|
var random_pos = Vector3(
|
||||||
|
randf_range(-1.0, 1.0),
|
||||||
|
0.0,
|
||||||
|
randf_range(-1.0, 1.0)
|
||||||
|
)
|
||||||
|
|
||||||
|
var random_rotation = randf_range(0.0, TAU)
|
||||||
|
var basis = Basis(Vector3.UP, random_rotation)
|
||||||
|
|
||||||
|
var random_scale = randf_range(0.05, 0.3)
|
||||||
|
basis = basis.scaled(Vector3(random_scale, random_scale, random_scale))
|
||||||
|
|
||||||
|
var tx = Transform3D(basis, random_pos)
|
||||||
|
mm.set_instance_transform(i, tx)
|
||||||
|
|
||||||
|
# Assign the MultiMesh to this node
|
||||||
|
multimesh = mm
|
||||||
|
cast_shadow = GeometryInstance3D.SHADOW_CASTING_SETTING_OFF
|
||||||
|
|
||||||
|
Log.pr("MultiMesh setup complete with " + str(multimesh.instance_count) + " instances")
|
||||||
1
Entities/GroundTile/scripts/grass_multimesh.gd.uid
Normal file
1
Entities/GroundTile/scripts/grass_multimesh.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
uid://btju6b83mvgvk
|
||||||
105
Entities/GroundTile/scripts/trees.gd
Normal file
105
Entities/GroundTile/scripts/trees.gd
Normal file
|
|
@ -0,0 +1,105 @@
|
||||||
|
extends Node3D
|
||||||
|
|
||||||
|
# Array of tree scenes to randomly choose from
|
||||||
|
@export var tree_scenes: Array[PackedScene] = []
|
||||||
|
@export var spawn_area_size: Vector2 = Vector2(2.0, 2.0) # 2x2 area
|
||||||
|
@export var max_trees: int = 3 # Maximum possible trees
|
||||||
|
@export var min_distance: float = 0.5 # Minimum distance between trees
|
||||||
|
|
||||||
|
var spawned_positions: Array[Vector3] = []
|
||||||
|
var parent_ground_tile: GroundTile
|
||||||
|
var rng: RandomClass
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
# Get reference to parent GroundTile
|
||||||
|
parent_ground_tile = get_parent() as GroundTile
|
||||||
|
if parent_ground_tile:
|
||||||
|
# Connect to the signal
|
||||||
|
parent_ground_tile.cell_info_updated.connect(_on_cell_info_updated)
|
||||||
|
|
||||||
|
# If cell_info already exists, spawn trees immediately
|
||||||
|
if parent_ground_tile.cell_info != null:
|
||||||
|
_on_cell_info_updated(parent_ground_tile.cell_info)
|
||||||
|
|
||||||
|
func _on_cell_info_updated(cell_info: CellDataResource):
|
||||||
|
# Initialize RNG with the cell's seed for consistent results
|
||||||
|
rng = RandomClass.new()
|
||||||
|
rng.set_seed(cell_info.cell_seed)
|
||||||
|
|
||||||
|
# Calculate number of trees based on vegetation_density
|
||||||
|
var tree_count = calculate_tree_count(cell_info.vegetation_density)
|
||||||
|
|
||||||
|
# Spawn the trees
|
||||||
|
spawn_trees(tree_count)
|
||||||
|
|
||||||
|
func calculate_tree_count(vegetation_density: float) -> int:
|
||||||
|
if vegetation_density < 0.7:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
# vegetation_density should be between 0.0 and 1.0
|
||||||
|
# Scale it to our max_trees range
|
||||||
|
var scaled_count = vegetation_density * max_trees
|
||||||
|
|
||||||
|
# Round to nearest integer, but ensure at least 0
|
||||||
|
return max(0, int(round(scaled_count)))
|
||||||
|
|
||||||
|
func spawn_trees(tree_count: int):
|
||||||
|
if tree_scenes.is_empty():
|
||||||
|
print("No tree scenes assigned!")
|
||||||
|
return
|
||||||
|
|
||||||
|
if tree_count == 0:
|
||||||
|
print("No trees to spawn (vegetation_density too low)")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Clear any existing trees
|
||||||
|
clear_trees()
|
||||||
|
|
||||||
|
# Try to place trees
|
||||||
|
var attempts = 0
|
||||||
|
var max_attempts = tree_count * 10 # Prevent infinite loops
|
||||||
|
|
||||||
|
while spawned_positions.size() < tree_count and attempts < max_attempts:
|
||||||
|
var pos = get_random_position()
|
||||||
|
|
||||||
|
if is_position_valid(pos):
|
||||||
|
spawn_tree_at_position(pos)
|
||||||
|
spawned_positions.append(pos)
|
||||||
|
|
||||||
|
attempts += 1
|
||||||
|
|
||||||
|
print("Spawned ", spawned_positions.size(), " trees")
|
||||||
|
|
||||||
|
func get_random_position() -> Vector3:
|
||||||
|
var x = rng.randf_range(-spawn_area_size.x / 2, spawn_area_size.x / 2)
|
||||||
|
var z = rng.randf_range(-spawn_area_size.y / 2, spawn_area_size.y / 2)
|
||||||
|
return Vector3(x, 0, z)
|
||||||
|
|
||||||
|
func is_position_valid(pos: Vector3) -> bool:
|
||||||
|
# Check if position is too close to existing trees
|
||||||
|
for existing_pos in spawned_positions:
|
||||||
|
if pos.distance_to(existing_pos) < min_distance:
|
||||||
|
return false
|
||||||
|
return true
|
||||||
|
|
||||||
|
func spawn_tree_at_position(pos: Vector3):
|
||||||
|
# Pick a random tree scene using the seeded RNG
|
||||||
|
var random_index = rng.randi() % tree_scenes.size()
|
||||||
|
var random_tree_scene = tree_scenes[random_index]
|
||||||
|
var tree_instance = random_tree_scene.instantiate()
|
||||||
|
add_child(tree_instance)
|
||||||
|
tree_instance.position = pos
|
||||||
|
|
||||||
|
# Optional: Add some random rotation using seeded RNG
|
||||||
|
tree_instance.rotation.y = rng.randf() * TAU
|
||||||
|
|
||||||
|
func clear_trees():
|
||||||
|
# Remove all existing tree children
|
||||||
|
for child in get_children():
|
||||||
|
child.queue_free()
|
||||||
|
spawned_positions.clear()
|
||||||
|
|
||||||
|
# Call this if you want to respawn trees manually
|
||||||
|
func respawn_trees():
|
||||||
|
if parent_ground_tile and parent_ground_tile.cell_info:
|
||||||
|
_on_cell_info_updated(parent_ground_tile.cell_info)
|
||||||
1
Entities/GroundTile/scripts/trees.gd.uid
Normal file
1
Entities/GroundTile/scripts/trees.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
uid://cqko4m7cbxsfb
|
||||||
|
|
@ -9,7 +9,8 @@ func _ready() -> void:
|
||||||
position = Vector3.ZERO
|
position = Vector3.ZERO
|
||||||
|
|
||||||
func _physics_process(delta):
|
func _physics_process(delta):
|
||||||
%MultiMesh3D.set("instance_shader_parameters/player_position", position)
|
RenderingServer.global_shader_parameter_set("player_position", position)
|
||||||
|
|
||||||
%TileGround.update_chunks(position)
|
%TileGround.update_chunks(position)
|
||||||
|
|
||||||
# We create a local variable to store the input direction.
|
# We create a local variable to store the input direction.
|
||||||
|
|
|
||||||
56
Utilities/Random/RandomClass.gd
Normal file
56
Utilities/Random/RandomClass.gd
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
extends Node
|
||||||
|
|
||||||
|
class_name RandomClass
|
||||||
|
|
||||||
|
var _rng: RandomNumberGenerator = RandomNumberGenerator.new()
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
randomize()
|
||||||
|
print("Global RNG initialized with seed: ", _rng.seed)
|
||||||
|
|
||||||
|
# Set a specific seed for reproducible results
|
||||||
|
func set_seed(seed_value: int) -> void:
|
||||||
|
_rng.seed = seed_value
|
||||||
|
print("RNG seed set to: ", seed_value)
|
||||||
|
|
||||||
|
# Randomize the seed (for non-reproducible results)
|
||||||
|
func randomize() -> void:
|
||||||
|
_rng.randomize()
|
||||||
|
print("RNG seed randomized to: ", _rng.seed)
|
||||||
|
|
||||||
|
# Get the current seed value
|
||||||
|
func get_seed() -> int:
|
||||||
|
return _rng.seed
|
||||||
|
|
||||||
|
# Get a random integer between min and max (inclusive)
|
||||||
|
func randi_range(min_value: int, max_value: int) -> int:
|
||||||
|
return _rng.randi_range(min_value, max_value)
|
||||||
|
|
||||||
|
# Get a random float between 0.0 and 1.0
|
||||||
|
func randf() -> float:
|
||||||
|
return _rng.randf()
|
||||||
|
|
||||||
|
func randi() -> int:
|
||||||
|
return _rng.randi()
|
||||||
|
|
||||||
|
# Get a random float between min and max
|
||||||
|
func randf_range(min_value: float, max_value: float) -> float:
|
||||||
|
return _rng.randf_range(min_value, max_value)
|
||||||
|
|
||||||
|
# Get a random normalized vector
|
||||||
|
func random_unit_vector() -> Vector2:
|
||||||
|
return Vector2(randf_range(-1.0, 1.0), randf_range(-1.0, 1.0)).normalized()
|
||||||
|
|
||||||
|
# Get a random point inside a circle with radius 1
|
||||||
|
func random_point_in_circle() -> Vector2:
|
||||||
|
var r = sqrt(randf())
|
||||||
|
var theta = randf() * 2.0 * PI
|
||||||
|
return Vector2(r * cos(theta), r * sin(theta))
|
||||||
|
|
||||||
|
# Get a random point inside a circle with specified radius
|
||||||
|
func random_point_in_circle_with_radius(radius: float) -> Vector2:
|
||||||
|
return random_point_in_circle() * radius
|
||||||
|
|
||||||
|
# Get a random boolean value with specified probability
|
||||||
|
func random_bool(probability: float = 0.5) -> bool:
|
||||||
|
return randf() < probability
|
||||||
1
Utilities/Random/RandomClass.gd.uid
Normal file
1
Utilities/Random/RandomClass.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
uid://bbyxn7t840t6w
|
||||||
|
|
@ -16,7 +16,7 @@ global uniform float wind_noise_size; // high values dont work well
|
||||||
global uniform float wind_noise_speed;
|
global uniform float wind_noise_speed;
|
||||||
|
|
||||||
// Instance the Player Position through a GDScript in the _physics_process
|
// Instance the Player Position through a GDScript in the _physics_process
|
||||||
instance uniform vec3 player_position;
|
global uniform vec3 player_position;
|
||||||
|
|
||||||
void vertex() {
|
void vertex() {
|
||||||
vec3 world_position = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz;
|
vec3 world_position = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz;
|
||||||
|
|
|
||||||
|
|
@ -61,17 +61,21 @@ jump={
|
||||||
|
|
||||||
wind_direction={
|
wind_direction={
|
||||||
"type": "vec3",
|
"type": "vec3",
|
||||||
"value": Vector3(5, 1, 5)
|
"value": Vector3(0.45, 0, -0.83)
|
||||||
}
|
}
|
||||||
wind_noise_size={
|
wind_noise_size={
|
||||||
"type": "float",
|
"type": "float",
|
||||||
"value": 0.1
|
"value": 2.0
|
||||||
}
|
}
|
||||||
wind_noise_speed={
|
wind_noise_speed={
|
||||||
"type": "float",
|
"type": "float",
|
||||||
"value": 0.2
|
"value": 0.1
|
||||||
}
|
}
|
||||||
wind_strength={
|
wind_strength={
|
||||||
"type": "float",
|
"type": "float",
|
||||||
"value": 7.0
|
"value": 0.5
|
||||||
|
}
|
||||||
|
player_position={
|
||||||
|
"type": "vec3",
|
||||||
|
"value": Vector3(0, 0, 0)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
16
stages/Test3D/GrassMaterialOverride.tres
Normal file
16
stages/Test3D/GrassMaterialOverride.tres
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
[gd_resource type="ShaderMaterial" load_steps=3 format=3 uid="uid://b1miqvl8lus75"]
|
||||||
|
|
||||||
|
[ext_resource type="Shader" uid="uid://dbduq0qcaxmyi" path="res://grass.gdshader" id="1_vnnwo"]
|
||||||
|
|
||||||
|
[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_vnnwo"]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
render_priority = 0
|
||||||
|
shader = ExtResource("1_vnnwo")
|
||||||
|
shader_parameter/top_color = Color(0.102963, 0.465909, 0.382031, 1)
|
||||||
|
shader_parameter/bottom_color = Color(0.121494, 0.374954, 0.315972, 1)
|
||||||
|
shader_parameter/ambient_occlusion_factor = 0.0
|
||||||
|
shader_parameter/specular_strength = 0.0
|
||||||
|
shader_parameter/player_displacement_strength = 1.0
|
||||||
|
shader_parameter/player_displacement_size = 1.0
|
||||||
|
shader_parameter/wind_noise = SubResource("NoiseTexture2D_vnnwo")
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
[gd_scene load_steps=65 format=4 uid="uid://bwsugg4p50fjr"]
|
[gd_scene load_steps=62 format=4 uid="uid://bwsugg4p50fjr"]
|
||||||
|
|
||||||
[ext_resource type="Environment" uid="uid://cm77bbr0io118" path="res://Stages/Test3D/new_environment.tres" id="1_8ph61"]
|
[ext_resource type="Environment" uid="uid://cm77bbr0io118" path="res://Stages/Test3D/new_environment.tres" id="1_8ph61"]
|
||||||
[ext_resource type="Script" uid="uid://bwed2dwogfmxv" path="res://Entities/Player/scripts/player.gd" id="1_d602n"]
|
[ext_resource type="Script" uid="uid://bwed2dwogfmxv" path="res://Entities/Player/scripts/player.gd" id="1_d602n"]
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
[ext_resource type="Shader" uid="uid://bsemnmdracd4m" path="res://Common/shaders/outline.gdshader" id="4_feu7y"]
|
[ext_resource type="Shader" uid="uid://bsemnmdracd4m" path="res://Common/shaders/outline.gdshader" id="4_feu7y"]
|
||||||
[ext_resource type="PackedScene" uid="uid://c66kiiacr2bym" path="res://Stages/Test3D/assets/grass.glb" id="6_8ph61"]
|
[ext_resource type="PackedScene" uid="uid://c66kiiacr2bym" path="res://Stages/Test3D/assets/grass.glb" id="6_8ph61"]
|
||||||
[ext_resource type="PackedScene" uid="uid://dg6v7qap28a5o" path="res://Stages/Test3D/assets/rock-a.glb" id="7_8537y"]
|
[ext_resource type="PackedScene" uid="uid://dg6v7qap28a5o" path="res://Stages/Test3D/assets/rock-a.glb" id="7_8537y"]
|
||||||
[ext_resource type="Shader" uid="uid://dbduq0qcaxmyi" path="res://grass.gdshader" id="7_hvb1l"]
|
[ext_resource type="Material" uid="uid://b1miqvl8lus75" path="res://Stages/Test3D/GrassMaterialOverride.tres" id="7_caaui"]
|
||||||
[ext_resource type="PackedScene" uid="uid://ctw4ktjdpiva7" path="res://Stages/Test3D/assets/rock-b.glb" id="8_h8fbl"]
|
[ext_resource type="PackedScene" uid="uid://ctw4ktjdpiva7" path="res://Stages/Test3D/assets/rock-b.glb" id="8_h8fbl"]
|
||||||
[ext_resource type="ArrayMesh" uid="uid://r2imjo7o2734" path="res://Stages/Test3D/assets/stylizedGrassMeshes/grass2.res" id="8_xvexm"]
|
[ext_resource type="ArrayMesh" uid="uid://r2imjo7o2734" path="res://Stages/Test3D/assets/stylizedGrassMeshes/grass2.res" id="8_xvexm"]
|
||||||
[ext_resource type="PackedScene" uid="uid://nsnthin0ekva" path="res://Stages/Test3D/assets/rock-c.glb" id="9_rt72s"]
|
[ext_resource type="PackedScene" uid="uid://nsnthin0ekva" path="res://Stages/Test3D/assets/rock-c.glb" id="9_rt72s"]
|
||||||
|
|
@ -40,7 +40,8 @@ script/source = "@tool
|
||||||
extends DirectionalLight3D
|
extends DirectionalLight3D
|
||||||
|
|
||||||
func _process(_delta):
|
func _process(_delta):
|
||||||
(%PostProcessing as MeshInstance3D).mesh.surface_get_material(0).set_shader_parameter('light_direction', -global_basis.z)
|
pass
|
||||||
|
#(%PostProcessing as MeshInstance3D).mesh.surface_get_material(0).set_shader_parameter('light_direction', -global_basis.z)
|
||||||
"
|
"
|
||||||
|
|
||||||
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_tfa5t"]
|
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_tfa5t"]
|
||||||
|
|
@ -374,26 +375,6 @@ material = SubResource("ShaderMaterial_tfa5t")
|
||||||
flip_faces = true
|
flip_faces = true
|
||||||
size = Vector2(2, 2)
|
size = Vector2(2, 2)
|
||||||
|
|
||||||
[sub_resource type="FastNoiseLite" id="FastNoiseLite_hvb1l"]
|
|
||||||
|
|
||||||
[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_xvexm"]
|
|
||||||
noise = SubResource("FastNoiseLite_hvb1l")
|
|
||||||
|
|
||||||
[sub_resource type="ShaderMaterial" id="ShaderMaterial_ukp6m"]
|
|
||||||
render_priority = 0
|
|
||||||
shader = ExtResource("7_hvb1l")
|
|
||||||
shader_parameter/top_color = Color(0.415686, 0.694118, 0.266667, 1)
|
|
||||||
shader_parameter/bottom_color = Color(0.176471, 0.333333, 0.0941176, 1)
|
|
||||||
shader_parameter/ambient_occlusion_factor = 0.5
|
|
||||||
shader_parameter/specular_strength = 0.4
|
|
||||||
shader_parameter/player_displacement_strength = 1.0
|
|
||||||
shader_parameter/player_displacement_size = 0.53
|
|
||||||
shader_parameter/wind_direction = Vector3(0.4, -0.3, 0.81)
|
|
||||||
shader_parameter/wind_strength = 0.3
|
|
||||||
shader_parameter/wind_noise = SubResource("NoiseTexture2D_xvexm")
|
|
||||||
shader_parameter/wind_noise_size = 0.05
|
|
||||||
shader_parameter/wind_noise_speed = 0.1
|
|
||||||
|
|
||||||
[sub_resource type="MultiMesh" id="MultiMesh_hvb1l"]
|
[sub_resource type="MultiMesh" id="MultiMesh_hvb1l"]
|
||||||
transform_format = 1
|
transform_format = 1
|
||||||
instance_count = 10000
|
instance_count = 10000
|
||||||
|
|
@ -785,7 +766,8 @@ script = ExtResource("2_sdmks")
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, -1.49012e-07, 0, 1.19209e-07, 1, 0.0410548, 0.237644, 3.45114)
|
transform = Transform3D(1, 0, 0, 0, 1, -1.49012e-07, 0, 1.19209e-07, 1, 0.0410548, 0.237644, 3.45114)
|
||||||
projection = 1
|
projection = 1
|
||||||
current = true
|
current = true
|
||||||
size = 3.0
|
size = 4.0
|
||||||
|
near = 0.01
|
||||||
far = 100.0
|
far = 100.0
|
||||||
|
|
||||||
[node name="PostProcessing" type="MeshInstance3D" parent="SubViewportContainer/SubViewport/Player/CameraPivot/Camera3D"]
|
[node name="PostProcessing" type="MeshInstance3D" parent="SubViewportContainer/SubViewport/Player/CameraPivot/Camera3D"]
|
||||||
|
|
@ -803,7 +785,7 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.247314, 0, 0.404175)
|
||||||
|
|
||||||
[node name="MultiMesh3D" type="MultiMeshInstance3D" parent="SubViewportContainer/SubViewport/Environment"]
|
[node name="MultiMesh3D" type="MultiMeshInstance3D" parent="SubViewportContainer/SubViewport/Environment"]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
material_override = SubResource("ShaderMaterial_ukp6m")
|
material_override = ExtResource("7_caaui")
|
||||||
cast_shadow = 0
|
cast_shadow = 0
|
||||||
multimesh = SubResource("MultiMesh_hvb1l")
|
multimesh = SubResource("MultiMesh_hvb1l")
|
||||||
|
|
||||||
|
|
@ -850,7 +832,7 @@ draw_pass_1 = SubResource("QuadMesh_hvb1l")
|
||||||
[node name="OmniLight3D" type="OmniLight3D" parent="SubViewportContainer/SubViewport/VFX/Fire"]
|
[node name="OmniLight3D" type="OmniLight3D" parent="SubViewportContainer/SubViewport/VFX/Fire"]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.000509977, 0.121094, -0.00151992)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.000509977, 0.121094, -0.00151992)
|
||||||
light_color = Color(0.89, 0.461613, 0.2136, 1)
|
light_color = Color(0.89, 0.461613, 0.2136, 1)
|
||||||
light_energy = 0.779335
|
light_energy = 0.763335
|
||||||
light_indirect_energy = 1.084
|
light_indirect_energy = 1.084
|
||||||
light_volumetric_fog_energy = 3.764
|
light_volumetric_fog_energy = 3.764
|
||||||
light_size = 0.105
|
light_size = 0.105
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -3,108 +3,108 @@ extends Node3D
|
||||||
@export var map_width: int = 500
|
@export var map_width: int = 500
|
||||||
@export var map_height: int = 500
|
@export var map_height: int = 500
|
||||||
@export var tile_size: float = 2.0
|
@export var tile_size: float = 2.0
|
||||||
@export var chunk_size: int = 2
|
@export var chunk_size: int = 5
|
||||||
@export var view_distance: int = 2
|
@export var view_distance: int = 2
|
||||||
@export var tiles_per_frame: int = 1 # How many tiles to create per frame
|
@export var tiles_per_frame: int = 5 # How many tiles to create per frame
|
||||||
var loaded_chunks: Dictionary = {}
|
var loaded_chunks: Dictionary = {}
|
||||||
var player_position: Vector3
|
var player_position: Vector3
|
||||||
var last_chunk_pos: Vector2i = Vector2i(-999, -999)
|
var last_chunk_pos: Vector2i = Vector2i(-999, -999)
|
||||||
var loading_chunks: Dictionary = {} # Track chunks currently being loaded
|
var loading_chunks: Dictionary = {} # Track chunks currently being loaded
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
Log.pr('Testing optimized tile map generation')
|
Log.pr('Testing optimized tile map generation')
|
||||||
create_tiles_chunked()
|
create_tiles_chunked()
|
||||||
|
|
||||||
func create_tiles_chunked() -> void:
|
func create_tiles_chunked() -> void:
|
||||||
Log.pr('Setting up chunked tile system...')
|
Log.pr('Setting up chunked tile system...')
|
||||||
|
|
||||||
var player = %Player
|
var player = %Player
|
||||||
if player:
|
if player:
|
||||||
player_position = player.global_position
|
player_position = player.global_position
|
||||||
update_chunks(player_position)
|
update_chunks(player_position)
|
||||||
else:
|
else:
|
||||||
Log.pr("Player not found, loading chunks around origin")
|
Log.pr("Player not found, loading chunks around origin")
|
||||||
update_chunks(Vector3.ZERO)
|
update_chunks(Vector3.ZERO)
|
||||||
|
|
||||||
func update_chunks(player_pos: Vector3) -> void:
|
func update_chunks(player_pos: Vector3) -> void:
|
||||||
player_position = player_pos
|
player_position = player_pos
|
||||||
|
|
||||||
var current_chunk = Vector2i(
|
var current_chunk = Vector2i(
|
||||||
int(player_pos.x / (chunk_size * tile_size)),
|
int(player_pos.x / (chunk_size * tile_size)),
|
||||||
int(player_pos.z / (chunk_size * tile_size))
|
int(player_pos.z / (chunk_size * tile_size))
|
||||||
)
|
)
|
||||||
|
|
||||||
if current_chunk == last_chunk_pos:
|
if current_chunk == last_chunk_pos:
|
||||||
return
|
return
|
||||||
|
|
||||||
last_chunk_pos = current_chunk
|
last_chunk_pos = current_chunk
|
||||||
Log.pr("CHUNK CHANGE - New chunk: ", current_chunk)
|
Log.pr("CHUNK CHANGE - New chunk: ", current_chunk)
|
||||||
|
|
||||||
# Determine which chunks should be loaded
|
# Determine which chunks should be loaded
|
||||||
var chunks_to_load: Array[Vector2i] = []
|
var chunks_to_load: Array[Vector2i] = []
|
||||||
for x in range(-view_distance, view_distance + 1):
|
for x in range(-view_distance, view_distance + 1):
|
||||||
for z in range(-view_distance, view_distance + 1):
|
for z in range(-view_distance, view_distance + 1):
|
||||||
chunks_to_load.append(current_chunk + Vector2i(x, z))
|
chunks_to_load.append(current_chunk + Vector2i(x, z))
|
||||||
|
|
||||||
# LOADING new chunks
|
# LOADING new chunks
|
||||||
Log.pr("Chunks to load: ", chunks_to_load.size())
|
Log.pr("Chunks to load: ", chunks_to_load.size())
|
||||||
for chunk_pos in chunks_to_load:
|
for chunk_pos in chunks_to_load:
|
||||||
if chunk_pos not in loaded_chunks and chunk_pos not in loading_chunks:
|
if chunk_pos not in loaded_chunks and chunk_pos not in loading_chunks:
|
||||||
Log.pr("Loading new: ", chunk_pos)
|
Log.pr("Loading new: ", chunk_pos)
|
||||||
loading_chunks[chunk_pos] = true
|
loading_chunks[chunk_pos] = true
|
||||||
load_chunk_async(chunk_pos)
|
load_chunk_async(chunk_pos)
|
||||||
|
|
||||||
# UNLOADING far chunks
|
# UNLOADING far chunks
|
||||||
var chunks_to_unload: Array[Vector2i] = []
|
var chunks_to_unload: Array[Vector2i] = []
|
||||||
for chunk_pos in loaded_chunks.keys():
|
for chunk_pos in loaded_chunks.keys():
|
||||||
if chunk_pos not in chunks_to_load:
|
if chunk_pos not in chunks_to_load:
|
||||||
chunks_to_unload.append(chunk_pos)
|
chunks_to_unload.append(chunk_pos)
|
||||||
|
|
||||||
Log.pr("Chunks to unload: ", chunks_to_unload.size())
|
Log.pr("Chunks to unload: ", chunks_to_unload.size())
|
||||||
for chunk_pos in chunks_to_unload:
|
for chunk_pos in chunks_to_unload:
|
||||||
Log.pr("Unloading: ", chunk_pos)
|
Log.pr("Unloading: ", chunk_pos)
|
||||||
unload_chunk(chunk_pos)
|
unload_chunk(chunk_pos)
|
||||||
|
|
||||||
func load_chunk_async(chunk_pos: Vector2i) -> void:
|
func load_chunk_async(chunk_pos: Vector2i) -> void:
|
||||||
if not ground_tile:
|
if not ground_tile:
|
||||||
Log.pr("ground_tile is null!")
|
Log.pr("ground_tile is null!")
|
||||||
loading_chunks.erase(chunk_pos)
|
loading_chunks.erase(chunk_pos)
|
||||||
return
|
return
|
||||||
|
|
||||||
var chunk_node = Node3D.new()
|
var chunk_node = Node3D.new()
|
||||||
chunk_node.name = "Chunk_%d_%d" % [chunk_pos.x, chunk_pos.y]
|
chunk_node.name = "Chunk_%d_%d" % [chunk_pos.x, chunk_pos.y]
|
||||||
add_child(chunk_node)
|
add_child(chunk_node)
|
||||||
|
|
||||||
var start_x = chunk_pos.x * chunk_size * tile_size - (chunk_size * tile_size) / 2.0
|
var start_x = chunk_pos.x * chunk_size * tile_size - (chunk_size * tile_size) / 2.0
|
||||||
var start_z = chunk_pos.y * chunk_size * tile_size - (chunk_size * tile_size) / 2.0
|
var start_z = chunk_pos.y * chunk_size * tile_size - (chunk_size * tile_size) / 2.0
|
||||||
|
|
||||||
var tiles_created = 0
|
var tiles_created = 0
|
||||||
var tiles_this_frame = 0
|
var tiles_this_frame = 0
|
||||||
|
|
||||||
for x in range(chunk_size):
|
for x in range(chunk_size):
|
||||||
for z in range(chunk_size):
|
for z in range(chunk_size):
|
||||||
var tile_instance = ground_tile.instantiate()
|
var tile_instance = ground_tile.instantiate()
|
||||||
tile_instance.set_grid_location((chunk_pos.x * chunk_size) + x, (chunk_pos.y * chunk_size) + z)
|
tile_instance.set_grid_location((chunk_pos.x * chunk_size) + x, (chunk_pos.y * chunk_size) + z)
|
||||||
tile_instance.position = Vector3(
|
tile_instance.position = Vector3(
|
||||||
start_x + (x * tile_size),
|
start_x + (x * tile_size),
|
||||||
0,
|
0,
|
||||||
start_z + (z * tile_size)
|
start_z + (z * tile_size)
|
||||||
)
|
)
|
||||||
chunk_node.add_child(tile_instance)
|
chunk_node.add_child(tile_instance)
|
||||||
tiles_created += 1
|
tiles_created += 1
|
||||||
tiles_this_frame += 1
|
tiles_this_frame += 1
|
||||||
|
|
||||||
# Yield after creating a certain number of tiles
|
# Yield after creating a certain number of tiles
|
||||||
if tiles_this_frame >= tiles_per_frame:
|
if tiles_this_frame >= tiles_per_frame:
|
||||||
tiles_this_frame = 0
|
tiles_this_frame = 0
|
||||||
await get_tree().process_frame
|
await get_tree().process_frame
|
||||||
|
|
||||||
Log.pr("Created ", tiles_created, " tiles in chunk ", chunk_pos)
|
Log.pr("Created ", tiles_created, " tiles in chunk ", chunk_pos)
|
||||||
loaded_chunks[chunk_pos] = chunk_node
|
loaded_chunks[chunk_pos] = chunk_node
|
||||||
loading_chunks.erase(chunk_pos)
|
loading_chunks.erase(chunk_pos)
|
||||||
|
|
||||||
func unload_chunk(chunk_pos: Vector2i) -> void:
|
func unload_chunk(chunk_pos: Vector2i) -> void:
|
||||||
if chunk_pos in loaded_chunks:
|
if chunk_pos in loaded_chunks:
|
||||||
Log.pr("Unloading chunk: ", chunk_pos)
|
Log.pr("Unloading chunk: ", chunk_pos)
|
||||||
loaded_chunks[chunk_pos].queue_free()
|
loaded_chunks[chunk_pos].queue_free()
|
||||||
loaded_chunks.erase(chunk_pos)
|
loaded_chunks.erase(chunk_pos)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue