From 3ec8cb809552357b727029114c3259f370f9a273 Mon Sep 17 00:00:00 2001 From: henry Date: Tue, 30 Jun 2026 08:27:04 +0100 Subject: [PATCH 1/2] Added vanguard+ weapon icon. --- graphics/vanguard+.png | Bin 0 -> 272 bytes graphics/vanguard+.png.import | 40 ++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 graphics/vanguard+.png create mode 100644 graphics/vanguard+.png.import diff --git a/graphics/vanguard+.png b/graphics/vanguard+.png new file mode 100644 index 0000000000000000000000000000000000000000..dee5a9786317dbc8951a20525944508e8d3eff3f GIT binary patch literal 272 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJV{wqX6T`Z5GB1IggaDrqS0JsV zVB)G_lV)kyA7*{OQ0?Y|w0DPR{r+S&^JzfVJ_GY9dES}&LEb7xHkS7GB?bvi(RmM( zXaA2s`{eZPKmY&#pS^Z_OI>?rR#s$KP?=NL8Y82d;mOylclA&A>dH6xoxJBf&<=%? zAirP+plW27#MsK#aXLrj~)i Date: Tue, 30 Jun 2026 13:50:31 +0100 Subject: [PATCH 2/2] Set up power up spawner to test weapon collection functions. --- scenes/player.gd | 18 ++++++ scenes/player.tscn | 7 ++- scenes/power_up_spawner.tscn | 19 ++++++ scenes/world.tscn | 3 + scripts/event_bus.gd | 3 + scripts/power_up_spawner.gd | 105 ++++++++++++++++++++++++++++++++ scripts/power_up_spawner.gd.uid | 1 + scripts/weapon_component.gd | 2 +- 8 files changed, 156 insertions(+), 2 deletions(-) create mode 100644 scenes/power_up_spawner.tscn create mode 100644 scripts/power_up_spawner.gd create mode 100644 scripts/power_up_spawner.gd.uid diff --git a/scenes/player.gd b/scenes/player.gd index ace3c7a..12ea90b 100644 --- a/scenes/player.gd +++ b/scenes/player.gd @@ -5,6 +5,7 @@ class_name Player extends Area2D @onready var movement_component: MovementComponent = %MovementComponent @onready var shoot_component: ShootComponent = %ShootComponent @onready var weapon_component: WeaponComponent = %WeaponComponent +@onready var powerup_spawner := _find_powerup_spawner() # Get the viewport size for positioning @onready var screensize = get_viewport().content_scale_size @@ -55,3 +56,20 @@ func _process(delta) -> void: if input_component.cycle_weapon: weapon_component.cycle_weapon() $EffectsComponent.apply_effect(flash_effect) + +func _on_help_box_area_entered(area: Area2D) -> void: + # Check if the colliding area is a powerup pickup. + if not area.has_meta("weapon_shot"): + return + var weapon_shot: WeaponShot = area.get_meta("weapon_shot") + weapon_component.collect_weapon(weapon_shot) + powerup_spawner.pickup_collected() + area.queue_free() + + +func _find_powerup_spawner() -> PowerUpSpawner: + # The spawner is a sibling under Level — find it by searching parent. + var level: Node2D = get_parent() as Node2D + if level == null: + return null + return level.get_node_or_null("PowerupSpawner") as PowerUpSpawner diff --git a/scenes/player.tscn b/scenes/player.tscn index a39f299..4464b6d 100644 --- a/scenes/player.tscn +++ b/scenes/player.tscn @@ -128,7 +128,11 @@ shape = SubResource("RectangleShape2D_qlg0r") disabled = true debug_color = Color(1, 0.5058824, 0.21960784, 0.41960785) -[node name="HelpBox" type="CollisionShape2D" parent="." unique_id=938667427] +[node name="HelpBoxArea" type="Area2D" parent="." unique_id=938667427] +collision_layer = 2 +collision_mask = 1 + +[node name="HelpBoxShape" type="CollisionShape2D" parent="HelpBoxArea" unique_id=938667428] position = Vector2(0, 3) shape = SubResource("RectangleShape2D_tuyoq") debug_color = Color(0, 1, 0, 0.41960785) @@ -174,4 +178,5 @@ script = ExtResource("12_effcomp") target_node = NodePath("../Ship") metadata/_custom_type_script = "uid://65d3hbrpm21x" +[connection signal="area_entered" from="HelpBoxArea" to="." method="_on_help_box_area_entered"] [connection signal="timeout" from="WeaponCooldown" to="." method="_on_weapon_cooldown_timeout"] diff --git a/scenes/power_up_spawner.tscn b/scenes/power_up_spawner.tscn new file mode 100644 index 0000000..d099e50 --- /dev/null +++ b/scenes/power_up_spawner.tscn @@ -0,0 +1,19 @@ +[gd_scene format=3 uid="uid://du5nub2keaty3"] + +[ext_resource type="Script" uid="uid://qf6mgn4117o" path="res://scripts/power_up_spawner.gd" id="1_85wk8"] +[ext_resource type="Script" uid="uid://7n1itonn35fm" path="res://scripts/weapon_shot.gd" id="2_07x44"] +[ext_resource type="Resource" uid="uid://b75ae840k03dy" path="res://resources/player_weapon_resources/stock.tres" id="3_0eev3"] +[ext_resource type="Resource" uid="uid://cck3gmnhu5agc" path="res://resources/player_weapon_resources/tri.tres" id="4_qqjui"] +[ext_resource type="Resource" uid="uid://ds53sryglmf27" path="res://resources/player_weapon_resources/spread.tres" id="5_mwa7c"] +[ext_resource type="Resource" uid="uid://bhc6aja38vyr" path="res://resources/player_weapon_resources/vanguard.tres" id="6_vphcr"] +[ext_resource type="Resource" uid="uid://c41aoyka7nfr8" path="res://resources/player_weapon_resources/vanguard+.tres" id="7_g67dp"] + +[node name="PowerUpSpawner" type="Node2D" unique_id=1191463626] +script = ExtResource("1_85wk8") +all_weapon_shots = Array[ExtResource("2_07x44")]([ExtResource("3_0eev3"), ExtResource("4_qqjui"), ExtResource("5_mwa7c"), ExtResource("6_vphcr"), ExtResource("7_g67dp")]) + +[node name="SpawnTimer" type="Timer" parent="." unique_id=173111015] +wait_time = 5.0 +autostart = true + +[connection signal="timeout" from="SpawnTimer" to="." method="_on_spawn_timer_timeout"] diff --git a/scenes/world.tscn b/scenes/world.tscn index 515828a..e415429 100644 --- a/scenes/world.tscn +++ b/scenes/world.tscn @@ -6,6 +6,7 @@ [ext_resource type="PackedScene" uid="uid://c3scm07fgpkcp" path="res://scenes/notification_display.tscn" id="3_71j4m"] [ext_resource type="PackedScene" uid="uid://6wq3ynesnsha" path="res://scenes/player.tscn" id="3_k0juu"] [ext_resource type="Script" uid="uid://eblemtukrey6" path="res://scripts/utility/fps_display.gd" id="4_qfnet"] +[ext_resource type="PackedScene" uid="uid://du5nub2keaty3" path="res://scenes/power_up_spawner.tscn" id="7_i7141"] [node name="World" type="Node2D" unique_id=1317852169] @@ -92,3 +93,5 @@ hframes = 4 frame = 3 [node name="Player" parent="Level" unique_id=652131079 instance=ExtResource("3_k0juu")] + +[node name="PowerupSpawner" parent="Level" unique_id=1191463626 instance=ExtResource("7_i7141")] diff --git a/scripts/event_bus.gd b/scripts/event_bus.gd index fc12a05..fa3dcc0 100644 --- a/scripts/event_bus.gd +++ b/scripts/event_bus.gd @@ -4,4 +4,7 @@ extends Node signal weapon_changed(weapon_name: String, player_node: Node2D, player_sprite_size: Vector2, origin_offset: float) +# Emitted when a powerup is collected by the player. +signal powerup_collected(weapon_shot: WeaponShot, player_node: Node2D) + @warning_ignore_restore("unused_signal") diff --git a/scripts/power_up_spawner.gd b/scripts/power_up_spawner.gd new file mode 100644 index 0000000..8185b71 --- /dev/null +++ b/scripts/power_up_spawner.gd @@ -0,0 +1,105 @@ +class_name PowerUpSpawner extends Node2D + +@export var spawn_interval: float = 5.0 +@export var test_mode: bool = true + +@onready var screensize: Vector2 = get_viewport().content_scale_size +@onready var spawn_timer: Timer = $SpawnTimer + +# All weapon resources to spawn as pickups. +# Populate in the editor with your weapon_shot resources. +@export var all_weapon_shots: Array[WeaponShot] = [] + +var _pickups_spawned: int = 0 +var _pickups_remaining: int = 0 + +func _ready() -> void: + if spawn_timer == null: + return + spawn_timer.wait_time = spawn_interval + + +func _on_spawn_timer_timeout() -> void: + if test_mode: + _spawn_test_pickups() + else: + # TODO: normal mode — spawn a single random pickup. + pass + + +func _spawn_test_pickups() -> void: + for weapon: WeaponShot in all_weapon_shots: + if weapon == null or weapon.shot_name.is_empty(): + continue + var pickup := _create_pickup(weapon) + if not is_instance_valid(pickup): + continue # skipped — no valid icon + + # Random position within viewport, with edge padding. + var margin: float = 15.0 + pickup.position = Vector2( + randf_range(margin, screensize.x - margin), + randf_range(margin, screensize.y - margin) + ) + + add_child(pickup) + _pickups_spawned += 1 + _pickups_remaining = _pickups_spawned + + # Pause the timer while pickups are on screen; resume when all gone. + if spawn_timer != null: + spawn_timer.stop() + + +func pickup_collected() -> void: + # Called by the player when a pickup is collected. + # Decrement counter; resume timer once all pickups are gone. + _pickups_remaining = max(0, _pickups_remaining - 1) + if _pickups_remaining <= 0: + if spawn_timer != null: + spawn_timer.start() + _pickups_spawned = 0 + + +func _create_pickup(weapon: WeaponShot) -> Area2D: + var pickup := Area2D.new() + pickup.name = "PowerUpPickup" + + # Icon texture — load from graphics/ matching the weapon's shot_name. + var icon_path := "res://graphics/" + weapon.shot_name.replace(" ", "") + ".png" + var icon_tex := load(icon_path) as Texture2D + if icon_tex == null: + printerr("[PowerUpSpawner] No texture found for weapon: ", weapon.shot_name) + pickup.queue_free() # return a dead node — caller skips it + return pickup + + var icon := TextureRect.new() + icon.texture = icon_tex + icon.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED + icon.size = Vector2(16, 16) + pickup.add_child(icon) + + # Collision shape — small rectangle matching the icon. + var shape := RectangleShape2D.new() + shape.size = Vector2(14, 14) + var collision := CollisionShape2D.new() + collision.shape = shape + pickup.add_child(collision) + + # Store the weapon reference so we know what to give the player. + pickup.set_meta("weapon_shot", weapon) + + # Configure collision so HelpBoxArea (Layer 2, Mask 1) detects it. + pickup.collision_layer = 1 + pickup.collision_mask = 0 + + return pickup + + + + + +# --- Timer control --- + +# Direct stop/start — no guard conditions. The timer's paused property +# can cause deadlock if the guard checks "not paused" after stop(). diff --git a/scripts/power_up_spawner.gd.uid b/scripts/power_up_spawner.gd.uid new file mode 100644 index 0000000..7121649 --- /dev/null +++ b/scripts/power_up_spawner.gd.uid @@ -0,0 +1 @@ +uid://qf6mgn4117o diff --git a/scripts/weapon_component.gd b/scripts/weapon_component.gd index 63a916b..94ed851 100644 --- a/scripts/weapon_component.gd +++ b/scripts/weapon_component.gd @@ -8,7 +8,7 @@ var _current_weapon_index = 0 var _current_power_level = 0 var _cycled_weapon: WeaponShot = null -@onready var effects_component: EffectComponent = get_node("EffectsComponent") +@onready var effects_component: EffectComponent = get_node("../EffectsComponent") func _ready() -> void: # Set the default weapon to be stock, i.e. index 1