Asteroids Destroyer Dev Log – 24 April 2026

Asteroids Destroyer — Development Journal

Dev Log — 24 April 2026

📅 Session 6
🎮 Godot 4.6
✨ Level Complete Polish
⚠️ Wave Warning
🔧 Debug Tools
📋
Session Overview
Level Complete editor visibility, wave warning redesign, debug level-complete shortcut

I addressed three items this session:

  1. Level Complete screen: ShipDisplay had no texture in the editor, making the ship invisible and preventing thruster alignment
  2. Wave warning redesigned with new text “Warning Asteroids Incoming!” and full-width red lines above and below
  3. Debug shortcut added: F5 instantly triggers the Level Complete screen during debug builds for rapid testing of the level-up flow
🚀
Level Complete: ShipDisplay Default Texture
scenes/menus/LevelComplete.tscn

Root cause The ShipDisplay node in LevelComplete.tscn had no texture assigned. The ship texture is set at runtime by _populate() based on GameManager.selected_ship, so in-game it works correctly. However, in the Godot editor the node appeared completely empty. This made it impossible to see the ship in the scene view and therefore impossible to align the ThrusterDisplay below it.

Fix

I added CX16-X1.png (the default ship, ship index 0) as a new ext_resource in the scene file and assigned it as the default texture on ShipDisplay:

[ext_resource type=”Texture2D” uid=”uid://u6v5u57mxc34″ path=”res://Game Assests/UI/Level Complate/Ships/CX16-X1.png” id=”7_ship_default”] [node name=”ShipDisplay” …] texture = ExtResource(“7_ship_default”) <– added

The LevelComplete.gd script overwrites this texture at runtime with the player’s actual selected ship, so the default only acts as an editor placeholder. The ship is now visible in the Godot editor scene view, and the ThrusterDisplay can be repositioned visually to align with the ship’s engine nozzle.

Visual polish of the ThrusterDisplay position is still pending; open the scene in the editor and adjust ThrusterDisplay offsets to align with the ship engine.
⚠️
Wave Warning: New Text and Red Lines
scripts/game/GameScene.gd · _show_wave_warning()

Changed The wave warning was previously a single flashing red label reading “WAVE X”. I updated it to read “Warning Asteroids Incoming!” with a full-width red line above and below the text for a more dramatic, broadcast-style look.

Layout

Element Y range Size
Red line (top) 446–450 4px tall, full 1920px wide
Warning label 456–578 72px Neuropol, red
Red line (bottom) 582–586 4px tall, full 1920px wide

Architecture

A root Control node (full-rect) is added to the temporary CanvasLayer. All three elements (top line, label, bottom line) are children of that root. The flash tween targets the root’s modulate:a. Children inherit it automatically, so all three elements flash in sync with a single tween:

var root := Control.new() root.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) cl.add_child(root) # … add line_top, lbl, line_bot to root … var tw := create_tween() for _i in 4: tw.tween_property(root, “modulate:a”, 0.08, 0.20).set_ease(Tween.EASE_IN) tw.tween_property(root, “modulate:a”, 1.00, 0.22).set_ease(Tween.EASE_OUT) tw.tween_callback(cl.queue_free) tw.tween_callback(_start_wave)

I reduced the font size from 96px to 72px to fit the longer string on one line at 1920px width. Total flash duration is unchanged (~1.8 s).

🛠️
Debug Shortcut for Force Level Complete (F5)
scripts/game/GameScene.gd · _unhandled_input()

New Added a debug-only keyboard shortcut to instantly trigger the Level Complete flow without playing through all three waves. This is essential for testing rank progression, star awarding, the Continue/Retry buttons, and next-level unlock logic.

How to use

  • Launch the game in the Godot editor (debug build)
  • Start any level and press F5
  • The Level Complete screen appears immediately using the current session score and health
  • Stars awarded reflect actual player health at the moment F5 is pressed (3hp = 3 stars, etc.)

Implementation

# DEBUG ONLY — F5 instantly triggers Level Complete for testing if OS.is_debug_build() and event is InputEventKey and event.pressed and not event.echo: if event.keycode == KEY_F5 and not is_game_over: get_viewport().set_input_as_handled() _level_complete()

Guarded by OS.is_debug_build(), so the shortcut is completely absent from exported release builds. Also checks not event.echo to avoid repeat-triggers from holding the key, and not is_game_over to prevent conflict with the game-over state.

What this tests

  • Level Complete screen loads without errors
  • Correct ship image displayed for the selected ship
  • Score and Best values populated correctly
  • Star animation plays (1, 2, or 3 stars based on health)
  • Rank name shown in promotion message
  • Continue button advances to next level (or Level Select if last level)
  • Retry button returns to the same level
  • Level stars saved correctly (check Level Select after continuing)
Star Parallax Background Layer
scripts/effects/StarParallax.gd · GameScene · MainMenu · LevelSelect · LevelComplete · Splash

New Added an animated star layer (background_01_Starrs_parallax_02.png, 1920×1270, transparent PNG) to all major scenes. The layer sits between the static space background and the game/UI content, drifting gently left-right in a sine wave to give the impression of depth.

Layering

Scene type Method Result
GameScene (Node2D) Sprite2D, z_index = -5, between Background (z=-10) and game nodes (z=0) Stars behind player & asteroids, in front of static BG
MainMenu / LevelSelect (Node2D) Sprite2D inserted after Background in tree, before planets/UI CanvasLayer Stars above BG, behind planets and all CanvasLayer UI
LevelComplete (CanvasLayer root) Sprite2D injected programmatically at tree index 1 inside Root Control, after Background Stars above BG, behind Dimmer and all menu elements

Animation: StarParallax.gd

A shared script (scripts/effects/StarParallax.gd) is applied to the Sprite2D in every Node2D scene, and loaded dynamically for LevelComplete. It moves the sprite with two overlapping sine waves: a larger horizontal drift and a subtle vertical one with a different frequency so the motion never feels repetitive:

const SPEED_X : float = 0.30 # one H-cycle every ~21 s const AMP_X : float = 50.0 # ±50px horizontal travel const SPEED_Y : float = 0.19 # different freq — avoids locked feel const AMP_Y : float = 18.0 # ±18px vertical drift func _process(delta: float) -> void: _t += delta position.x = 960.0 + sin(_t * SPEED_X) * AMP_X position.y = 540.0 + sin(_t * SPEED_Y) * AMP_Y

Because the star image has a transparent background (only the star dots are opaque), the edges drifting slightly off-screen simply reveals the background, with no visible seam or gap. Adjust AMP_X / AMP_Y or SPEED_X / SPEED_Y in the script to fine-tune the feel.

💥
Nuke Powerup: Full Implementation
PowerUp.gd · NukeMissile.gd/tscn · NukeExplosion.gd/tscn · GameScene.gd

Edge-Spawned Powerups (Health, Shield, Nuke)

All three powerup types now also drift in from outside the screen, in addition to health/shield dropping from destroyed asteroids. Edge-spawned powerups travel faster than dropped ones to keep them visible and reachable:

Source Types Speed Direction
Asteroid drop Health, Shield 35 px/s Random angle
Edge spawn Health (40%), Shield (30%), Nuke (30%) 120 px/s Toward screen centre

Edge spawns happen every 18 seconds (first spawn at 12 s). Spawn point is one of the existing 8 fixed edge positions used by asteroids. The velocity is set on the PowerUp node before add_child() via the new edge_velocity property, so _ready() sees it and skips the random-drift logic.

Nuke Pickup: Instant Fire

When the player collects a Nuke powerup it immediately fires a NukeMissile in the player’s current facing direction. No button press or inventory step; the pickup is the trigger. The missile is instantiated and added to the current scene from within PowerUp._fire_nuke().

NukeMissile

New scene: scenes/entities/NukeMissile.tscn / scripts/entities/NukeMissile.gd

  • Area2D, collision_layer=4, collision_mask=2 (detects asteroids, invisible to player)
  • Sprite: Nuke Missile.png (34×64). Sprite rotated to align with travel direction
  • Speed: 550 px/s
  • Detonates on: asteroid body contact (body_entered) OR approaching within 60px of any screen edge
  • A _detonated bool prevents double-detonation if both triggers fire on the same frame

NukeExplosion

New scene: scenes/entities/NukeExplosion.tscn / scripts/entities/NukeExplosion.gd

  • Destroys all asteroids in front of the player, so asteroids behind the player’s position are safe
  • The dividing line is the player’s position at fire time, perpendicular to their facing direction. A dot-product test determines which side each asteroid is on: (asteroid_pos - fire_origin).dot(direction) > 0 = in front = destroyed
  • Each destroyed asteroid gets its own Explosion.tscn spawned at its location so every kill has a visual
  • Asteroids are destroyed via nuke_destroy(), which skips HP and skips splits so no fragments survive. Still emits destroyed so score and wave-completion run normally
  • The player’s position (fire_origin) and facing direction are stored on the missile at fire time, then passed to the explosion on detonation
  • Animation: starts at scale 0.2, pops to 1.2 (TRANS_EXPO, NE1 frame), switches to NE2, expands to 1.7 while fading to alpha 0 (total ~0.7 s)
  • z_index = 5 so the fireball renders above everything

Bug fixed Initial implementation called asteroid.hit() once per asteroid. Asteroids have 3–4 HP (one per damage-state image) so a single hit only damaged them, so nothing actually died. Fixed by adding nuke_destroy() to Asteroid.gd which bypasses HP entirely and skips split-spawning.

Assets used

  • Game Assests/Powerups/Nuke-PU.png: 100×100 pickup icon
  • Game Assests/Powerups/Nuke Missile.png: 34×64 missile sprite
  • Game Assests/Nuke Explosion/NE1.png: 600×600 explosion frame 1
  • Game Assests/Nuke Explosion/Ne2.png: 600×600 explosion frame 2
📌
Open Items
Pending for future sessions
  • Level Complete: ThrusterDisplay position still needs manual alignment in the editor now that the ship is visible
  • Level Complete: remaining visual polish pass (user identified layout tweaks needed)
  • Star parallax: consider adding to PauseMenu, Settings, and CharacterShop scenes if they need the effect too (Splash now covered)
  • Mobile joystick input not wired to player movement
  • Audio bus muting on session start (respect saved music_enabled / sfx_enabled)
  • HUD nuke count display: update_nukes() is still a stub (pass); needs icon + counter in HUD scene
  • Rank-up nukes (stored in nukes_held) still have no activation; separate from the pickup nuke, it needs a button or gesture
  • Coin shop / IAP integration
  • Endless mode difficulty scaling (currently stays at level-0 speed forever)