nature-sim/Entities/GroundTile/scripts/trees.gd
2025-06-27 11:58:59 +01:00

114 lines
3.2 KiB
GDScript

extends Node3D
@export var spawn_area_size: Vector2 = Vector2(2.0, 2.0)
@export var min_distance: float = 0.5
var spawned_positions: Array[Vector3] = []
var parent_ground_tile: GroundTile
func _ready():
parent_ground_tile = get_parent() as GroundTile
func spawn_trees_for_cell(cell_info: CellDataResource):
if not cell_info:
return
if not parent_ground_tile:
return
# Clear existing trees WITHOUT queue_free()
for child in get_children():
child.free() # Immediate cleanup instead of queue_free()
spawned_positions.clear()
# Spawn each tree in the array
var spawned_count = 0
var attempts = 0
var max_attempts = cell_info.trees.size() * 10
for tree_resource in cell_info.trees:
if attempts >= max_attempts:
Log.pr("Reached max attempts, could only spawn %d of %d trees" % [spawned_count, cell_info.trees.size()])
break
var pos = get_random_position()
if is_position_valid(pos):
spawn_tree_at_position(pos, tree_resource as TreeDataResource)
spawned_positions.append(pos)
spawned_count += 1
attempts += 1
Log.pr("Spawned %d of %d trees in cell" % [spawned_count, cell_info.trees.size()])
func get_random_position() -> Vector3:
var rng = parent_ground_tile.get_rng()
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 spawn_tree_at_position(pos: Vector3, tree_resource: TreeDataResource):
if not tree_resource:
Log.pr("No tree resource provided")
return
var tree_scene = preload("res://Entities/Tree/Tree.tscn")
var tree_instance = tree_scene.instantiate()
add_child(tree_instance)
tree_instance.position = pos
var rng = parent_ground_tile.get_rng()
tree_instance.rotation.y = rng.randf() * TAU
# Pass the TreeDataResource to the Tree instance
if tree_instance.has_method("set_tree_data"):
tree_instance.set_tree_data(tree_resource)
elif tree_instance.has_method("setup_tree"):
tree_instance.setup_tree(tree_resource)
else:
Log.pr("Tree instance doesn't have set_tree_data() or setup_tree() method")
func is_position_valid(pos: Vector3) -> bool:
for existing_pos in spawned_positions:
if pos.distance_to(existing_pos) < min_distance:
return false
return true
# Alternative method that shuffles trees for more random placement
func spawn_trees_shuffled(cell_info: CellDataResource):
if not cell_info:
return
if not parent_ground_tile:
return
# Clear existing trees
for child in get_children():
child.free()
spawned_positions.clear()
# Create a copy and shuffle for random placement order
var trees_to_spawn = cell_info.trees.duplicate()
trees_to_spawn.shuffle()
var spawned_count = 0
var attempts = 0
var max_attempts = trees_to_spawn.size() * 10
for tree_resource in trees_to_spawn:
if attempts >= max_attempts:
Log.pr("Reached max attempts, could only spawn %d of %d trees" % [spawned_count, trees_to_spawn.size()])
break
var pos = get_random_position()
if is_position_valid(pos):
spawn_tree_at_position(pos, tree_resource as TreeDataResource)
spawned_positions.append(pos)
spawned_count += 1
attempts += 1
Log.pr("Spawned %d of %d trees in cell (shuffled)" % [spawned_count, trees_to_spawn.size()])