From 98294afeabd902ac494bc99c05426593ba62207e Mon Sep 17 00:00:00 2001 From: Ruslan Ignatov Date: Mon, 24 Nov 2025 16:40:43 +0300 Subject: [PATCH] Added ExplosionParticles --- game/entities/other/explosion_particles.gd | 40 ++++++++++++++ .../entities/other/explosion_particles.gd.uid | 1 + game/entities/other/explosion_particles.tscn | 47 ++++++++++++++++ .../weapons/cannon/cannon_projectile.gd | 16 ++++++ .../weapons/cannon/cannon_projectile.tscn | 20 ++++++- .../weapons/launcher/launcher_projectile.gd | 14 +++++ .../weapons/launcher/launcher_projectile.tscn | 21 ++++++- .../weapons/minelayer/minelayer_projectile.gd | 55 ++++++++++++++----- .../minelayer/minelayer_projectile.tscn | 20 ++++++- 9 files changed, 216 insertions(+), 18 deletions(-) create mode 100644 game/entities/other/explosion_particles.gd create mode 100644 game/entities/other/explosion_particles.gd.uid create mode 100644 game/entities/other/explosion_particles.tscn diff --git a/game/entities/other/explosion_particles.gd b/game/entities/other/explosion_particles.gd new file mode 100644 index 0000000..535b64e --- /dev/null +++ b/game/entities/other/explosion_particles.gd @@ -0,0 +1,40 @@ +class_name ExplosionParticles +extends Node2D + + +signal finished + + +@export var process_material: ParticleProcessMaterial +@export_range(0, 1) var amount_ratio: float = 1 + + +@onready var particles_huge : GPUParticles2D = $ParticlesHuge +@onready var particles_large : GPUParticles2D = $ParticlesLarge +@onready var particles_medium : GPUParticles2D = $ParticlesMedium + + +var _emiting_count := 0 + + +var emitting : bool = false: + set(value): + emitting = value + if particles_huge: particles_huge.emitting = emitting; _emiting_count += 1 + if particles_large: particles_large.emitting = emitting; _emiting_count += 1 + if particles_medium: particles_medium.emitting = emitting; _emiting_count += 1 + + +func _ready() -> void: + particles_huge.amount_ratio = amount_ratio + particles_large.amount_ratio = amount_ratio + particles_medium.amount_ratio = amount_ratio + particles_huge.process_material = process_material + particles_large.process_material = process_material + particles_medium.process_material = process_material + + +func _on_particles_finished() -> void: + _emiting_count -= 1 + if _emiting_count == 0: + finished.emit() diff --git a/game/entities/other/explosion_particles.gd.uid b/game/entities/other/explosion_particles.gd.uid new file mode 100644 index 0000000..f2bd774 --- /dev/null +++ b/game/entities/other/explosion_particles.gd.uid @@ -0,0 +1 @@ +uid://dhnjdam04g4tb diff --git a/game/entities/other/explosion_particles.tscn b/game/entities/other/explosion_particles.tscn new file mode 100644 index 0000000..70be893 --- /dev/null +++ b/game/entities/other/explosion_particles.tscn @@ -0,0 +1,47 @@ +[gd_scene load_steps=6 format=3 uid="uid://bhxib2ltpkcbf"] + +[ext_resource type="Texture2D" uid="uid://gh7mwehpqfco" path="res://particle_textures/flame_medium.tres" id="1_6awlt"] +[ext_resource type="Script" uid="uid://dhnjdam04g4tb" path="res://game/entities/other/explosion_particles.gd" id="1_w1d42"] +[ext_resource type="Texture2D" uid="uid://b13al44e8ofsx" path="res://particle_textures/flame_large.tres" id="2_w1d42"] +[ext_resource type="Texture2D" uid="uid://blp4o1c7y66wv" path="res://particle_textures/flame_huge.tres" id="3_lplfr"] + +[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_w1d42"] +lifetime_randomness = 0.2 +particle_flag_disable_z = true +emission_shape = 1 +emission_sphere_radius = 1.0 +angle_min = -179.99998 +angle_max = 180.00002 +spread = 180.0 +gravity = Vector3(0, 0, 0) +turbulence_enabled = true +turbulence_noise_speed = Vector3(0.1, 0.1, 0.1) + +[node name="ExplosionParticles" type="Node2D"] +script = ExtResource("1_w1d42") +process_material = SubResource("ParticleProcessMaterial_w1d42") + +[node name="ParticlesMedium" type="GPUParticles2D" parent="."] +emitting = false +amount = 512 +texture = ExtResource("1_6awlt") +lifetime = 0.25 +one_shot = true + +[node name="ParticlesLarge" type="GPUParticles2D" parent="."] +emitting = false +amount = 512 +texture = ExtResource("2_w1d42") +lifetime = 0.25 +one_shot = true + +[node name="ParticlesHuge" type="GPUParticles2D" parent="."] +emitting = false +amount = 512 +texture = ExtResource("3_lplfr") +lifetime = 0.25 +one_shot = true + +[connection signal="finished" from="ParticlesMedium" to="." method="_on_particles_finished"] +[connection signal="finished" from="ParticlesLarge" to="." method="_on_particles_finished"] +[connection signal="finished" from="ParticlesHuge" to="." method="_on_particles_finished"] diff --git a/game/entities/weapons/cannon/cannon_projectile.gd b/game/entities/weapons/cannon/cannon_projectile.gd index 86a4890..296cc7e 100644 --- a/game/entities/weapons/cannon/cannon_projectile.gd +++ b/game/entities/weapons/cannon/cannon_projectile.gd @@ -1,2 +1,18 @@ class_name CannonProjectile extends BlastProjectile + + +@onready var sprite : Sprite2D = $Sprite2D +@onready var explosion_particles : ExplosionParticles = $ExplosionParticles + + +func _process_hit_for_projectile(_collided_body: Node2D) -> void: + sprite.hide() + explosion_particles.emitting = true + set_physics_process(false) + collision_mask = 0 + blast.collision_mask = 0 + + +func _on_explosion_particles_finished() -> void: + queue_free() diff --git a/game/entities/weapons/cannon/cannon_projectile.tscn b/game/entities/weapons/cannon/cannon_projectile.tscn index e97754e..f7e2421 100644 --- a/game/entities/weapons/cannon/cannon_projectile.tscn +++ b/game/entities/weapons/cannon/cannon_projectile.tscn @@ -1,9 +1,10 @@ -[gd_scene load_steps=9 format=3 uid="uid://cgi7wd84kjnyw"] +[gd_scene load_steps=11 format=3 uid="uid://cgi7wd84kjnyw"] [ext_resource type="PackedScene" uid="uid://betr5ry5tc75e" path="res://game/entities/weapons/blast_projectile.tscn" id="1_20qwt"] [ext_resource type="Script" uid="uid://dfdh0o88as054" path="res://game/entities/weapons/cannon/cannon_projectile.gd" id="2_x3axw"] [ext_resource type="Script" uid="uid://dftb7hg5f06b5" path="res://game/health_system/damage/explosion_damage.gd" id="3_lb11p"] [ext_resource type="Texture2D" uid="uid://oj86smpsipw4" path="res://images/projectiles.png" id="4_bb01p"] +[ext_resource type="PackedScene" uid="uid://bhxib2ltpkcbf" path="res://game/entities/other/explosion_particles.tscn" id="5_ugryq"] [sub_resource type="AtlasTexture" id="AtlasTexture_ugryq"] atlas = ExtResource("4_bb01p") @@ -20,6 +21,18 @@ metadata/_custom_type_script = "uid://dftb7hg5f06b5" [sub_resource type="CircleShape2D" id="CircleShape2D_bb01p"] radius = 80.0 +[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_ugryq"] +lifetime_randomness = 0.2 +particle_flag_disable_z = true +emission_shape = 1 +emission_sphere_radius = 80.0 +angle_min = -179.99998 +angle_max = 180.00002 +spread = 180.0 +gravity = Vector3(0, 0, 0) +turbulence_enabled = true +turbulence_noise_speed = Vector3(0.1, 0.1, 0.1) + [node name="CannonProjectile" instance=ExtResource("1_20qwt")] collision_layer = 0 collision_mask = 0 @@ -37,3 +50,8 @@ collision_layer = 0 collision_mask = 0 damage = SubResource("Resource_ugryq") shape = SubResource("CircleShape2D_bb01p") + +[node name="ExplosionParticles" parent="." index="4" instance=ExtResource("5_ugryq")] +process_material = SubResource("ParticleProcessMaterial_ugryq") + +[connection signal="finished" from="ExplosionParticles" to="." method="_on_explosion_particles_finished"] diff --git a/game/entities/weapons/launcher/launcher_projectile.gd b/game/entities/weapons/launcher/launcher_projectile.gd index e44b56d..3d54540 100644 --- a/game/entities/weapons/launcher/launcher_projectile.gd +++ b/game/entities/weapons/launcher/launcher_projectile.gd @@ -9,6 +9,7 @@ extends BlastProjectile $Sprite2D_E, $Sprite2D_SE, $Sprite2D_S, $Sprite2D_SW, $Sprite2D_W, $Sprite2D_NW, $Sprite2D_N, $Sprite2D_NE, ] +@onready var explosion_particles : ExplosionParticles = $ExplosionParticles var target : AbstractShip = null @@ -54,3 +55,16 @@ func _update_sprite(velocity: Vector2) -> void: sprite.hide() sprites[index].show() + + +func _process_hit_for_projectile(_collided_body: Node2D) -> void: + for sprite in sprites: + sprite.hide() + explosion_particles.emitting = true + set_physics_process(false) + collision_mask = 0 + blast.collision_mask = 0 + + +func _on_explosion_particles_finished() -> void: + queue_free() diff --git a/game/entities/weapons/launcher/launcher_projectile.tscn b/game/entities/weapons/launcher/launcher_projectile.tscn index a3c7848..0bc561f 100644 --- a/game/entities/weapons/launcher/launcher_projectile.tscn +++ b/game/entities/weapons/launcher/launcher_projectile.tscn @@ -1,7 +1,8 @@ -[gd_scene load_steps=18 format=3 uid="uid://dukgbg13ujkv2"] +[gd_scene load_steps=20 format=3 uid="uid://dukgbg13ujkv2"] [ext_resource type="PackedScene" uid="uid://betr5ry5tc75e" path="res://game/entities/weapons/blast_projectile.tscn" id="1_0mcat"] [ext_resource type="Script" uid="uid://dkvur5bdwg3sr" path="res://game/entities/weapons/launcher/launcher_projectile.gd" id="2_6hdsf"] +[ext_resource type="PackedScene" uid="uid://bhxib2ltpkcbf" path="res://game/entities/other/explosion_particles.tscn" id="3_iqm85"] [ext_resource type="Texture2D" uid="uid://gh7mwehpqfco" path="res://particle_textures/flame_medium.tres" id="3_kos01"] [ext_resource type="Script" uid="uid://dftb7hg5f06b5" path="res://game/health_system/damage/explosion_damage.gd" id="3_ycnsk"] [ext_resource type="Texture2D" uid="uid://oj86smpsipw4" path="res://images/projectiles.png" id="4_kxgpk"] @@ -60,6 +61,18 @@ metadata/_custom_type_script = "uid://dftb7hg5f06b5" [sub_resource type="CircleShape2D" id="CircleShape2D_kxgpk"] radius = 16.0 +[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_iqm85"] +lifetime_randomness = 0.2 +particle_flag_disable_z = true +emission_shape = 1 +emission_sphere_radius = 16.0 +angle_min = -179.99998 +angle_max = 180.00002 +spread = 180.0 +gravity = Vector3(0, 0, 0) +turbulence_enabled = true +turbulence_noise_speed = Vector3(0.1, 0.1, 0.1) + [node name="LauncherProjectile" instance=ExtResource("1_0mcat")] collision_layer = 0 collision_mask = 0 @@ -105,3 +118,9 @@ collision_layer = 0 collision_mask = 0 damage = SubResource("Resource_kos01") shape = SubResource("CircleShape2D_kxgpk") + +[node name="ExplosionParticles" parent="." index="12" instance=ExtResource("3_iqm85")] +process_material = SubResource("ParticleProcessMaterial_iqm85") +amount_ratio = 0.05 + +[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 b1ad676..4561dc2 100644 --- a/game/entities/weapons/minelayer/minelayer_projectile.gd +++ b/game/entities/weapons/minelayer/minelayer_projectile.gd @@ -18,18 +18,21 @@ const OFF_TIMES = [ const ON_TIME = 0.05 -enum Sprite { +enum SpriteState { ON, OFF, + Disabled, } var _bodies_inside: Array[Node2D] = [] -var current_off_time_index := 0 +var _current_off_time_index := 0 +var _current_sprite_state : SpriteState: + set = _switch_sprite func _ready() -> void: - _switch_sprite(Sprite.OFF) + _current_sprite_state = SpriteState.OFF super._ready() @@ -52,7 +55,7 @@ func _on_livetime_timer_timeout() -> void: func _on_blast_body_entered(body: Node2D) -> void: _bodies_inside.append(body) - _switch_sprite(Sprite.ON) + _current_sprite_state = SpriteState.ON if sprite_on_timer.is_stopped() and sprite_off_timer.is_stopped(): sprite_on_timer.start(ON_TIME) @@ -67,33 +70,55 @@ func _on_blast_body_exited(body: Node2D) -> void: func _on_sprite_on_timer_timeout() -> void: - current_off_time_index += 1 + _current_off_time_index += 1 - if current_off_time_index >= OFF_TIMES.size(): + if _current_off_time_index >= OFF_TIMES.size(): _try_to_damage_by_blast() _process_hit_for_projectile(null) else: - _switch_sprite(Sprite.OFF) - sprite_off_timer.start(OFF_TIMES[current_off_time_index]) + _current_sprite_state = SpriteState.OFF + sprite_off_timer.start(OFF_TIMES[_current_off_time_index]) func _on_sprite_off_timer_timeout() -> void: - _switch_sprite(Sprite.ON) + _current_sprite_state = SpriteState.ON sprite_on_timer.start(ON_TIME) func _reset() -> void: - _switch_sprite(Sprite.OFF) + _current_sprite_state = SpriteState.OFF sprite_on_timer.stop() sprite_off_timer.stop() - current_off_time_index = 0 + _current_off_time_index = 0 -func _switch_sprite(sprite: Sprite) -> void: - match sprite: - Sprite.ON: +func _switch_sprite(new_state_state: SpriteState) -> void: + if _current_sprite_state == SpriteState.Disabled: return + + _current_sprite_state = new_state_state + match _current_sprite_state: + SpriteState.ON: sprite_on.show() sprite_off.hide() - Sprite.OFF: + SpriteState.OFF: sprite_on.hide() sprite_off.show() + SpriteState.Disabled: + sprite_on.hide() + sprite_off.hide() + + +@onready var sprite : Sprite2D = $Sprite2D +@onready var explosion_particles : ExplosionParticles = $ExplosionParticles + + +func _process_hit_for_projectile(_collided_body: Node2D) -> void: + _current_sprite_state = SpriteState.Disabled + explosion_particles.emitting = true + set_physics_process(false) + collision_mask = 0 + blast.collision_mask = 0 + + +func _on_explosion_particles_finished() -> void: + queue_free() diff --git a/game/entities/weapons/minelayer/minelayer_projectile.tscn b/game/entities/weapons/minelayer/minelayer_projectile.tscn index 6a524b4..3af1147 100644 --- a/game/entities/weapons/minelayer/minelayer_projectile.tscn +++ b/game/entities/weapons/minelayer/minelayer_projectile.tscn @@ -1,9 +1,10 @@ -[gd_scene load_steps=10 format=3 uid="uid://4mkklqt1g14f"] +[gd_scene load_steps=12 format=3 uid="uid://4mkklqt1g14f"] [ext_resource type="PackedScene" uid="uid://betr5ry5tc75e" path="res://game/entities/weapons/blast_projectile.tscn" id="1_ufc4r"] [ext_resource type="Script" uid="uid://76swcukelnii" path="res://game/entities/weapons/minelayer/minelayer_projectile.gd" id="2_hwwfa"] [ext_resource type="Script" uid="uid://dftb7hg5f06b5" path="res://game/health_system/damage/explosion_damage.gd" id="3_hll7s"] [ext_resource type="Texture2D" uid="uid://oj86smpsipw4" path="res://images/projectiles.png" id="4_px1i2"] +[ext_resource type="PackedScene" uid="uid://bhxib2ltpkcbf" path="res://game/entities/other/explosion_particles.tscn" id="5_ckqco"] [sub_resource type="AtlasTexture" id="AtlasTexture_ckqco"] atlas = ExtResource("4_px1i2") @@ -24,6 +25,18 @@ metadata/_custom_type_script = "uid://dftb7hg5f06b5" [sub_resource type="CircleShape2D" id="CircleShape2D_px1i2"] radius = 48.0 +[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_ckqco"] +lifetime_randomness = 0.2 +particle_flag_disable_z = true +emission_shape = 1 +emission_sphere_radius = 48.0 +angle_min = -179.99998 +angle_max = 180.00002 +spread = 180.0 +gravity = Vector3(0, 0, 0) +turbulence_enabled = true +turbulence_noise_speed = Vector3(0.1, 0.1, 0.1) + [node name="MinelayerProjectile" instance=ExtResource("1_ufc4r")] collision_layer = 0 collision_mask = 0 @@ -57,8 +70,13 @@ one_shot = true [node name="SpriteOffTimer" type="Timer" parent="." index="7"] one_shot = true +[node name="ExplosionParticles" parent="." index="8" instance=ExtResource("5_ckqco")] +process_material = SubResource("ParticleProcessMaterial_ckqco") +amount_ratio = 0.5 + [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"]