#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.
68 lines
2.6 KiB
GDScript
68 lines
2.6 KiB
GDScript
extends Area2D
|
|
|
|
# #86: faster. The bolt used to crawl far enough behind a moving target that
|
|
# leading a shot was guesswork rather than skill.
|
|
# #155: was 850, which took 1.1s to cross the gun's own range - long enough
|
|
# that a shot read as leaving the ship rather than as hitting something. The
|
|
# range below is derived from this (see set_range), so raising it makes shots
|
|
# faster without making them fall short.
|
|
@export var speed: float = 1400.0
|
|
# How long a bolt lives if nothing sets a range. VesselWeaponComponent always
|
|
# does - see set_range() - so this only covers a projectile fired by something
|
|
# that has no range of its own.
|
|
@export var lifetime: float = 1.5
|
|
@export var damage: int = 1
|
|
@export var bolt_length: float = 20.0
|
|
|
|
var velocity: Vector2 = Vector2.ZERO
|
|
var age: float = 0.0
|
|
|
|
|
|
func _ready() -> void:
|
|
add_to_group("player_projectiles")
|
|
area_entered.connect(_on_area_entered)
|
|
# Draw once. The earlier invisible-bolt bug came from _draw() deriving
|
|
# the bolt's look from `age` - drawing only at age==0 froze it at
|
|
# whatever the age==0 case rendered as. _draw() below is now a fixed
|
|
# shape with no age dependency, so one draw is safe and matches the
|
|
# Ship.gd/Asteroid.gd pattern: position/rotation are transform
|
|
# properties Godot applies at render time without re-tessellating.
|
|
queue_redraw()
|
|
|
|
|
|
# The gun's reach, in world units. Converted to a lifetime here rather than
|
|
# stored separately, so the distance a bolt COVERS and the distance the aim
|
|
# guide DRAWS are the same number rather than two that have to be kept in
|
|
# step. They were not: the guide showed fire_range (320) while a bolt actually
|
|
# flew speed * lifetime (750), so shots landed well past the line promising
|
|
# where they would stop.
|
|
func set_range(world_units: float) -> void:
|
|
if world_units > 0.0 and speed > 0.0:
|
|
lifetime = world_units / speed
|
|
|
|
|
|
func launch(direction: Vector2) -> void:
|
|
velocity = direction.normalized() * speed
|
|
rotation = direction.angle() + PI / 2.0
|
|
|
|
|
|
func _physics_process(delta: float) -> void:
|
|
position += velocity * delta
|
|
age += delta
|
|
if age >= lifetime:
|
|
queue_free()
|
|
|
|
|
|
func _on_area_entered(area: Area2D) -> void:
|
|
# Asteroids answer take_damage() exactly as enemies do, so both are hit by
|
|
# the same branch rather than by a second special case.
|
|
if area.is_in_group("enemies") or area.is_in_group("asteroids"):
|
|
area.take_damage(damage)
|
|
queue_free()
|
|
|
|
|
|
func _draw() -> void:
|
|
# Fixed-length, constant-brightness bolt. Drawn once and left alone.
|
|
var tip: Vector2 = Vector2(0, -bolt_length * 0.6)
|
|
var tail: Vector2 = Vector2(0, bolt_length * 0.4)
|
|
NeonDraw.draw_glowing_line(self, tail, tip, Color(1.0, 0.85, 0.3), 1.0, 0.5)
|