72 lines
2.3 KiB
GDScript
72 lines
2.3 KiB
GDScript
extends Node2D
|
|
|
|
# Scatters gatherable rocks across a planet's surface around the fleet, and
|
|
# tops them back up as they are collected, so there is always something to
|
|
# mine wherever the player flies.
|
|
#
|
|
# Unlike AsteroidField/PlanetField this is deliberately NOT deterministic
|
|
# per chunk: rocks are consumable, and a chunk-seeded layout would respawn
|
|
# the very same rock in the very same spot the moment the player flew back,
|
|
# making them infinite and free. Tracking every collected rock forever would
|
|
# grow without bound, so they are simply scattered at random within a ring
|
|
# around the fleet and despawned once left far behind.
|
|
|
|
@export var target_count: int = 14
|
|
@export var spawn_radius: float = 1400.0
|
|
@export var min_spawn_distance: float = 320.0
|
|
@export var despawn_radius: float = 2600.0
|
|
@export var check_interval: float = 0.5
|
|
|
|
@export var fleet_path: NodePath = NodePath("../Fleet")
|
|
@onready var fleet: Node2D = get_node(fleet_path)
|
|
|
|
var rock_scene: PackedScene = preload("res://Rock.tscn")
|
|
var rocks: Array = []
|
|
var timer: float = 0.0
|
|
var rng: RandomNumberGenerator = RandomNumberGenerator.new()
|
|
|
|
|
|
func _ready() -> void:
|
|
rng.randomize()
|
|
# Populate immediately rather than waiting out the first interval, so
|
|
# the surface isn't visibly empty for half a second on arrival.
|
|
update_rocks()
|
|
|
|
|
|
func _process(delta: float) -> void:
|
|
timer += delta
|
|
if timer < check_interval:
|
|
return
|
|
timer = 0.0
|
|
update_rocks()
|
|
|
|
|
|
func update_rocks() -> void:
|
|
var centre: Vector2 = fleet.get_centroid()
|
|
|
|
var surviving: Array = []
|
|
for rock in rocks:
|
|
if not is_instance_valid(rock):
|
|
continue
|
|
if rock.position.distance_to(centre) > despawn_radius:
|
|
rock.queue_free()
|
|
continue
|
|
surviving.append(rock)
|
|
rocks = surviving
|
|
|
|
while rocks.size() < target_count:
|
|
_spawn_rock(centre)
|
|
|
|
|
|
func _spawn_rock(centre: Vector2) -> void:
|
|
# Ring, not disc: spawning right on top of the fleet would hand the
|
|
# player free rocks without flying anywhere.
|
|
var angle: float = rng.randf() * TAU
|
|
var distance: float = rng.randf_range(min_spawn_distance, spawn_radius)
|
|
var rock: Area2D = rock_scene.instantiate()
|
|
rock.position = centre + Vector2(cos(angle), sin(angle)) * distance
|
|
rock.build_shape(rng.randi())
|
|
# Keep pickups under this field so its visibility and lifecycle really
|
|
# own them. Deferred is still required because this can run from _ready().
|
|
add_child.call_deferred(rock)
|
|
rocks.append(rock)
|