#155 - the projectile flew at 850, which took 1.1 seconds to cross the gun's own range: long enough that a shot read as leaving the ship rather than as hitting something. 1400 now, and the interceptor's range goes 950 to 1200, so it crosses in 0.86s and comfortably outranges the 620 the standoff enemies hold at. A projectile's lifetime is derived from its range and speed, so faster does not mean falling short - the test pins that arithmetic rather than trusting it. #152 asked for VFX on three events, and the finding is worth recording: all three already existed and were already wired. What had happened is that #130 gave a lost VESSEL thirty particles and a shockwave, which left everything else in the game visibly smaller than it - an enemy kill, the thing the player is being rewarded for, and a broken rock, the thing they do more than anything else, were both still on or near the base class's twelve-particle default with no shockwave at all. So this is about PROPORTION rather than about adding anything, and proportion is what the test checks: a lost vessel outweighs a kill, a kill outweighs a rock, and nothing sits on the base defaults. Numbers get rebalanced; an ordering that says a rock outweighs a battleship is a bug. Particles now run 38 > 32 > 24 against a default of 12.
51 lines
1.8 KiB
GDScript
51 lines
1.8 KiB
GDScript
class_name AsteroidExplosionVFX
|
|
extends ExplosionVFXBase
|
|
|
|
# Tumbling rock-chunk debris, distinct from the energy-ship light-burst
|
|
# style - asteroids are matter, not light.
|
|
|
|
const COLOR: Color = Color(0.65, 0.5, 0.35)
|
|
|
|
|
|
func _init() -> void:
|
|
# #152: this took the base class's defaults - 12 chunks over half a
|
|
# second, no shockwave - which is why breaking a rock, the thing the
|
|
# player does more than anything else in the game, barely registered.
|
|
# Matter rather than light, so it throws more and slower than an energy
|
|
# burst does, and its shockwave is dust rather than a flash.
|
|
particle_count = 24
|
|
lifetime = 0.7
|
|
min_speed = 70.0
|
|
max_speed = 330.0
|
|
shockwave_radius = 72.0
|
|
shockwave_color = Color(0.72, 0.6, 0.44)
|
|
|
|
|
|
static func spawn(parent: Node, world_position: Vector2) -> void:
|
|
var vfx: AsteroidExplosionVFX = AsteroidExplosionVFX.new()
|
|
vfx.position = world_position
|
|
parent.add_child(vfx)
|
|
|
|
|
|
func _random_particle_size() -> float:
|
|
return randf_range(4.0, 11.0)
|
|
|
|
|
|
# Debris tumbles independently of its flight path, unlike the light-burst
|
|
# streaks - each chunk needs its own evolving rotation, so the base class
|
|
# must keep writing visual.rotation every frame instead of leaving it fixed.
|
|
func _particle_spins() -> bool:
|
|
return true
|
|
|
|
|
|
func _configure_particle(visual: ExplosionParticle, p: Dictionary) -> void:
|
|
var s: float = p["size"]
|
|
# Unrotated local points - the child node's own `rotation` (driven by
|
|
# the base class from p["rot"]) supplies the tumble that used to be
|
|
# baked into a fresh pt.rotated(p["rot"]) call every frame.
|
|
var local_pts: PackedVector2Array = PackedVector2Array([
|
|
Vector2(-s, -s * 0.6), Vector2(s * 0.7, -s * 0.5),
|
|
Vector2(s, s * 0.5), Vector2(-s * 0.6, s),
|
|
])
|
|
visual.draw_callable = func(item: CanvasItem) -> void:
|
|
item.draw_colored_polygon(local_pts, COLOR)
|