From 1f82869e4f65a346d59791c5f180426c0b69eec1 Mon Sep 17 00:00:00 2001 From: Ruslan Ignatov Date: Sat, 29 Nov 2025 19:09:17 +0300 Subject: [PATCH] Added projectiles timeouts. Added GatlingWeapon animation --- game/controllers/enemy_swamp_controller.gd | 4 +- game/controllers/player_controller.gd | 3 +- game/entities/weapons/abstract_projectile.gd | 9 ++ .../entities/weapons/abstract_projectile.tscn | 7 ++ .../weapons/gatling/gatling_reloader.gd | 68 --------------- .../weapons/gatling/gatling_reloader.gd.uid | 1 - .../weapons/gatling/gatling_weapon.gd | 17 ++-- .../weapons/gatling/gatling_weapon.tscn | 87 ++++++++++++++++--- .../weapons/launcher/launcher_projectile.tscn | 3 + .../weapons/minelayer/minelayer_projectile.gd | 16 ++-- .../minelayer/minelayer_projectile.tscn | 15 ++-- .../weapons/tesla/tesla_projectile.tscn | 3 + project.godot | 4 +- 13 files changed, 125 insertions(+), 112 deletions(-) delete mode 100644 game/entities/weapons/gatling/gatling_reloader.gd delete mode 100644 game/entities/weapons/gatling/gatling_reloader.gd.uid diff --git a/game/controllers/enemy_swamp_controller.gd b/game/controllers/enemy_swamp_controller.gd index 49c9708..4da0cba 100644 --- a/game/controllers/enemy_swamp_controller.gd +++ b/game/controllers/enemy_swamp_controller.gd @@ -32,7 +32,7 @@ func create_enemy() -> void: _update_enemy.call_deferred(enemy) -func _on_enemy_update_timer_timeout() -> void: +func _on_enemy_update_timer_timeout() -> void: var enemies := get_tree().get_nodes_in_group("enemies") if enemies.is_empty(): return @@ -69,7 +69,7 @@ func _target_enemy_to_player(enemy: AbstractEnemyShip, player: PlayerShip) -> vo AbstractWeapon.Type.HOMING: _update_enemy_target_position(enemy, player, LONG_DISTANCE, INDIRECT_OFFSET) AbstractWeapon.Type.MINES: - _update_enemy_target_position(enemy, player, SHORT_DISTANCE, INDIRECT_OFFSET) + _update_enemy_target_position(enemy, player, MEDIUM_DISTANCE, INDIRECT_OFFSET) func _update_enemy_target_position( diff --git a/game/controllers/player_controller.gd b/game/controllers/player_controller.gd index a6a07d4..d000e34 100644 --- a/game/controllers/player_controller.gd +++ b/game/controllers/player_controller.gd @@ -27,7 +27,8 @@ func _physics_process(delta: float) -> void: func _input(event: InputEvent) -> void: if event.is_action_pressed("blink"): var input_direction := _get_input_direction() - blink.emit(input_direction) + if not input_direction.is_zero_approx(): + blink.emit(input_direction) func _get_input_direction() -> Vector2: return Input.get_vector("move_left", "move_right", "move_up", "move_down") diff --git a/game/entities/weapons/abstract_projectile.gd b/game/entities/weapons/abstract_projectile.gd index 47a0d9c..7a647b2 100644 --- a/game/entities/weapons/abstract_projectile.gd +++ b/game/entities/weapons/abstract_projectile.gd @@ -12,6 +12,7 @@ const ENEMY_PROJECTILE_LAYER = 16 @onready var collision : CollisionShape2D = $CollisionShape2D +@onready var out_of_screen_timer : Timer = $OutOfScreenTimer var direction : Vector2 @@ -66,7 +67,15 @@ func _update_collision_rotation(velocity: Vector2) -> void: collision.rotation = velocity.angle() - 0.5 * PI +func _on_screen_entered() -> void: + out_of_screen_timer.stop() + + func _on_screen_exited() -> void: + out_of_screen_timer.start() + + +func _on_out_of_screen_timer_timeout() -> void: queue_free() diff --git a/game/entities/weapons/abstract_projectile.tscn b/game/entities/weapons/abstract_projectile.tscn index bde77fa..789d480 100644 --- a/game/entities/weapons/abstract_projectile.tscn +++ b/game/entities/weapons/abstract_projectile.tscn @@ -13,5 +13,12 @@ shape = SubResource("CircleShape2D_4b2nh") [node name="VisibleOnScreenNotifier2D" type="VisibleOnScreenNotifier2D" parent="."] +[node name="OutOfScreenTimer" type="Timer" parent="."] +process_callback = 0 +wait_time = 0.1 +one_shot = true + [connection signal="body_entered" from="." to="." method="_on_body_entered"] +[connection signal="screen_entered" from="VisibleOnScreenNotifier2D" to="." method="_on_screen_entered"] [connection signal="screen_exited" from="VisibleOnScreenNotifier2D" to="." method="_on_screen_exited"] +[connection signal="timeout" from="OutOfScreenTimer" to="." method="_on_out_of_screen_timer_timeout"] diff --git a/game/entities/weapons/gatling/gatling_reloader.gd b/game/entities/weapons/gatling/gatling_reloader.gd deleted file mode 100644 index 921b150..0000000 --- a/game/entities/weapons/gatling/gatling_reloader.gd +++ /dev/null @@ -1,68 +0,0 @@ -extends Resource -class_name GatlingReloader - - -@export_range(1, 1500) var firerate : int = 1: - set(value): - firerate = value - _calculate_delay() - -@export_range(1, 25) var spin_out_time : int = 1: - set(value): - spin_out_time = value - _calculate_delay() - - -const INITIAL_DELAY = 1.0 - - -var _target_delay : float -var _current_delay : float = INITIAL_DELAY -var _delay_decrement : float -var _cooldown : float -var _last_delta : float - - -func _init() -> void: - resource_local_to_scene = true - - -func _ready() -> void: - _calculate_delay() - - -func process(delta: float) -> void: - if _cooldown > 0: - _cooldown -= delta - - if _current_delay < INITIAL_DELAY: - _decrease_delay(_delay_decrement * -delta) - - _last_delta = delta - - -func can_shoot() -> bool: - _decrease_delay(_delay_decrement * 2 * _last_delta) - return _cooldown <= 0 - - -func shoot() -> void: - _cooldown = _current_delay - - -func reload() -> void: - pass - - -func get_process_percent() -> int: - return 100 - int(_cooldown * 100 / _current_delay) - - -func _calculate_delay() -> void: - _target_delay = 60.0 / firerate - _delay_decrement = (INITIAL_DELAY - _target_delay)/spin_out_time - - -func _decrease_delay(delay_decrement: float) -> void: - _current_delay = _current_delay - delay_decrement - _current_delay = clampf(_current_delay, _target_delay, INITIAL_DELAY) diff --git a/game/entities/weapons/gatling/gatling_reloader.gd.uid b/game/entities/weapons/gatling/gatling_reloader.gd.uid deleted file mode 100644 index 5ee3cc2..0000000 --- a/game/entities/weapons/gatling/gatling_reloader.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://oslebeau3f4b diff --git a/game/entities/weapons/gatling/gatling_weapon.gd b/game/entities/weapons/gatling/gatling_weapon.gd index 2eed6a7..0dd1a24 100644 --- a/game/entities/weapons/gatling/gatling_weapon.gd +++ b/game/entities/weapons/gatling/gatling_weapon.gd @@ -1,14 +1,8 @@ extends AbstractWeapon -@export var reloader : GatlingReloader - - @onready var sprite : AnimatedSprite2D = $AnimatedSprite2D - - -func _physics_process(delta: float) -> void: - reloader.process(delta) +@onready var particles : GPUParticles2D = $GPUParticles2D func set_belonging(belonging: Belonging) -> void: @@ -18,9 +12,14 @@ func set_belonging(belonging: Belonging) -> void: func shoot(ship_velocity: Vector2) -> bool: - _can_shoot = reloader.can_shoot() var is_shot := super.shoot(ship_velocity) if is_shot: - reloader.shoot() + _can_shoot = false + sprite.play(PREFIXES[_belonging] + SHOT_POSTFIX) + particles.restart() return is_shot + + +func _on_animated_sprite_2d_animation_finished() -> void: + _can_shoot = true diff --git a/game/entities/weapons/gatling/gatling_weapon.tscn b/game/entities/weapons/gatling/gatling_weapon.tscn index c26c2c0..82587ce 100644 --- a/game/entities/weapons/gatling/gatling_weapon.tscn +++ b/game/entities/weapons/gatling/gatling_weapon.tscn @@ -1,25 +1,52 @@ -[gd_scene load_steps=10 format=3 uid="uid://c4mlppn5i55bp"] +[gd_scene load_steps=16 format=3 uid="uid://c4mlppn5i55bp"] [ext_resource type="PackedScene" uid="uid://1o2ta17yc5bp" path="res://game/entities/weapons/abstract_weapon.tscn" id="1_gblx7"] [ext_resource type="Script" uid="uid://c1bsvmj7xhnxe" path="res://game/entities/weapons/gatling/gatling_weapon.gd" id="1_kg6du"] [ext_resource type="PackedScene" uid="uid://yfvluap3uy1r" path="res://game/entities/weapons/gatling/gatling_projectile.tscn" id="2_ylc0n"] -[ext_resource type="Script" uid="uid://oslebeau3f4b" path="res://game/entities/weapons/gatling/gatling_reloader.gd" id="4_g81jq"] +[ext_resource type="Texture2D" uid="uid://b2tpy3y2bpuat" path="res://particle_textures/flame_small.tres" id="4_ydc6p"] [ext_resource type="Texture2D" uid="uid://6hh66k8s4a1e" path="res://images/weapons.png" id="5_ydc6p"] -[sub_resource type="Resource" id="Resource_oppha"] -script = ExtResource("4_g81jq") -firerate = 600 -spin_out_time = 3 -metadata/_custom_type_script = "uid://oslebeau3f4b" +[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_v064d"] +particle_flag_disable_z = true +angle_min = -179.99998 +angle_max = 180.00002 +inherit_velocity_ratio = 0.5 +initial_velocity_min = 5.0 +initial_velocity_max = 25.0 +gravity = Vector3(0, 0, 0) [sub_resource type="AtlasTexture" id="AtlasTexture_ydc6p"] atlas = ExtResource("5_ydc6p") region = Rect2(160, 176, 32, 16) +[sub_resource type="AtlasTexture" id="AtlasTexture_pjn33"] +atlas = ExtResource("5_ydc6p") +region = Rect2(192, 176, 32, 16) + +[sub_resource type="AtlasTexture" id="AtlasTexture_kkima"] +atlas = ExtResource("5_ydc6p") +region = Rect2(224, 176, 32, 16) + +[sub_resource type="AtlasTexture" id="AtlasTexture_i25po"] +atlas = ExtResource("5_ydc6p") +region = Rect2(160, 176, 32, 16) + [sub_resource type="AtlasTexture" id="AtlasTexture_v064d"] atlas = ExtResource("5_ydc6p") region = Rect2(160, 160, 32, 16) +[sub_resource type="AtlasTexture" id="AtlasTexture_pm1cd"] +atlas = ExtResource("5_ydc6p") +region = Rect2(192, 160, 32, 16) + +[sub_resource type="AtlasTexture" id="AtlasTexture_t1uk2"] +atlas = ExtResource("5_ydc6p") +region = Rect2(224, 160, 32, 16) + +[sub_resource type="AtlasTexture" id="AtlasTexture_colwf"] +atlas = ExtResource("5_ydc6p") +region = Rect2(160, 160, 32, 16) + [sub_resource type="SpriteFrames" id="SpriteFrames_pjn33"] animations = [{ "frames": [{ @@ -32,24 +59,62 @@ animations = [{ }, { "frames": [{ "duration": 1.0, +"texture": SubResource("AtlasTexture_pjn33") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_kkima") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_i25po") +}], +"loop": false, +"name": &"enemy_shot", +"speed": 30.0 +}, { +"frames": [{ +"duration": 1.0, "texture": SubResource("AtlasTexture_v064d") }], "loop": true, "name": &"player_idle", "speed": 10.0 +}, { +"frames": [{ +"duration": 1.0, +"texture": SubResource("AtlasTexture_pm1cd") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_t1uk2") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_colwf") +}], +"loop": false, +"name": &"player_shot", +"speed": 30.0 }] [node name="GatlingWeapon" instance=ExtResource("1_gblx7")] script = ExtResource("1_kg6du") -reloader = SubResource("Resource_oppha") sector_angle = 5 Projectile = ExtResource("2_ylc0n") type = 1 -[node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="." index="0"] +[node name="GPUParticles2D" type="GPUParticles2D" parent="." index="0"] +position = Vector2(17, 0) +emitting = false +amount = 32 +texture = ExtResource("4_ydc6p") +lifetime = 0.09999999999999999 +one_shot = true +process_material = SubResource("ParticleProcessMaterial_v064d") + +[node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="." index="1"] position = Vector2(6, 0) sprite_frames = SubResource("SpriteFrames_pjn33") -animation = &"player_idle" +animation = &"player_shot" -[node name="Muzzle" parent="." index="1"] +[node name="Muzzle" parent="." index="2"] position = Vector2(14, 0) + +[connection signal="animation_finished" from="AnimatedSprite2D" to="." method="_on_animated_sprite_2d_animation_finished"] diff --git a/game/entities/weapons/launcher/launcher_projectile.tscn b/game/entities/weapons/launcher/launcher_projectile.tscn index 963c21a..88159fa 100644 --- a/game/entities/weapons/launcher/launcher_projectile.tscn +++ b/game/entities/weapons/launcher/launcher_projectile.tscn @@ -123,4 +123,7 @@ shape = SubResource("CircleShape2D_kxgpk") process_material = SubResource("ParticleProcessMaterial_iqm85") amount_ratio = 0.05 +[node name="OutOfScreenTimer" parent="." index="13"] +wait_time = 3.0 + [connection signal="finished" from="ExplosionParticles" to="." method="_on_explosion_particles_finished"] diff --git a/game/entities/weapons/minelayer/minelayer_projectile.gd b/game/entities/weapons/minelayer/minelayer_projectile.gd index af24829..bc82500 100644 --- a/game/entities/weapons/minelayer/minelayer_projectile.gd +++ b/game/entities/weapons/minelayer/minelayer_projectile.gd @@ -18,6 +18,8 @@ const OFF_TIMES = [ ] const ON_TIME = 0.05 +const SCROLL_VELOCITY = Vector2(-50, 0) + enum SpriteState { ON, @@ -43,15 +45,11 @@ func _physics_process(delta: float) -> void: func _process_acceleration(delta: float) -> void: - var current_deceleration := deceleration * delta - if _velocity.length() > current_deceleration: - _velocity -= _velocity.normalized() * current_deceleration - else: - _velocity = Vector2.ZERO - - -func _on_livetime_timer_timeout() -> void: - queue_free() + var delta_velocity := SCROLL_VELOCITY - _velocity + var new_direction := delta_velocity.normalized() + var current_deceleration := clampf(delta_velocity.length(), 0.0, deceleration * delta) + + _velocity += new_direction * current_deceleration func _on_blast_body_entered(body: Node2D) -> void: diff --git a/game/entities/weapons/minelayer/minelayer_projectile.tscn b/game/entities/weapons/minelayer/minelayer_projectile.tscn index 3af1147..d1fbeb7 100644 --- a/game/entities/weapons/minelayer/minelayer_projectile.tscn +++ b/game/entities/weapons/minelayer/minelayer_projectile.tscn @@ -59,24 +59,21 @@ collision_mask = 0 damage = SubResource("Resource_ckqco") shape = SubResource("CircleShape2D_px1i2") -[node name="LivetimeTimer" type="Timer" parent="." index="5"] -wait_time = 60.0 -one_shot = true -autostart = true - -[node name="SpriteOnTimer" type="Timer" parent="." index="6"] +[node name="SpriteOnTimer" type="Timer" parent="." index="5"] one_shot = true -[node name="SpriteOffTimer" type="Timer" parent="." index="7"] +[node name="SpriteOffTimer" type="Timer" parent="." index="6"] one_shot = true -[node name="ExplosionParticles" parent="." index="8" instance=ExtResource("5_ckqco")] +[node name="ExplosionParticles" parent="." index="7" instance=ExtResource("5_ckqco")] process_material = SubResource("ParticleProcessMaterial_ckqco") amount_ratio = 0.5 +[node name="OutOfScreenTimer" parent="." index="8"] +wait_time = 5.0 + [connection signal="body_entered" from="Blast" to="." method="_on_blast_body_entered"] [connection signal="body_exited" from="Blast" to="." method="_on_blast_body_exited"] -[connection signal="timeout" from="LivetimeTimer" to="." method="_on_livetime_timer_timeout"] [connection signal="timeout" from="SpriteOnTimer" to="." method="_on_sprite_on_timer_timeout"] [connection signal="timeout" from="SpriteOffTimer" to="." method="_on_sprite_off_timer_timeout"] [connection signal="finished" from="ExplosionParticles" to="." method="_on_explosion_particles_finished"] diff --git a/game/entities/weapons/tesla/tesla_projectile.tscn b/game/entities/weapons/tesla/tesla_projectile.tscn index 415f349..0d3bce5 100644 --- a/game/entities/weapons/tesla/tesla_projectile.tscn +++ b/game/entities/weapons/tesla/tesla_projectile.tscn @@ -75,4 +75,7 @@ lifetime = 0.5 preprocess = 0.1 process_material = SubResource("ParticleProcessMaterial_wtuxv") +[node name="OutOfScreenTimer" parent="." index="7"] +wait_time = 1.0 + [connection signal="timeout" from="JinkTimer" to="." method="_on_jink_timer_timeout"] diff --git a/project.godot b/project.godot index d6de065..28d343f 100644 --- a/project.godot +++ b/project.godot @@ -301,14 +301,14 @@ move_right={ shoot_weapon_1={ "deadzone": 0.2, "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":32,"key_label":0,"unicode":32,"location":0,"echo":false,"script":null) -, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194325,"key_label":0,"unicode":0,"location":2,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194326,"key_label":0,"unicode":0,"location":2,"echo":false,"script":null) , Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":0,"pressure":0.0,"pressed":true,"script":null) ] } shoot_weapon_2={ "deadzone": 0.2, "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194325,"key_label":0,"unicode":0,"location":1,"echo":false,"script":null) -, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194326,"key_label":0,"unicode":0,"location":2,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194325,"key_label":0,"unicode":0,"location":2,"echo":false,"script":null) , Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":2,"pressure":0.0,"pressed":true,"script":null) ] }