From 2bf70d2b495c63cb18fdcc88048fa9dcbbf7ff38 Mon Sep 17 00:00:00 2001 From: Ruslan Ignatov Date: Sun, 21 Dec 2025 01:28:57 +0300 Subject: [PATCH] Reworked lightning effect --- game/entities/weapons/abstract_projectile.gd | 6 +- .../cannon/abstract_cannon_projectile.gd | 2 +- .../launcher/abstract_launcher_projectile.gd | 2 +- .../abstract_minelayer_projectile.gd | 2 +- .../railgun/abstract_railgun_projectile.gd | 2 +- .../shrapnel/abstract_shrapnel_projectile.gd | 2 +- .../tesla/abstract_tesla_projectile.gd | 95 +++++++++++++++---- .../tesla/abstract_tesla_projectile.tscn | 60 +++--------- .../weapons/tesla/abstract_tesla_weapon.tscn | 8 +- 9 files changed, 107 insertions(+), 72 deletions(-) diff --git a/game/entities/weapons/abstract_projectile.gd b/game/entities/weapons/abstract_projectile.gd index 2aa567b..29c6551 100644 --- a/game/entities/weapons/abstract_projectile.gd +++ b/game/entities/weapons/abstract_projectile.gd @@ -43,7 +43,7 @@ func _on_screen_exited() -> void: func _on_out_of_screen_timer_timeout() -> void: - queue_free() + delete() func _try_to_damage(body: Node2D, damage: AbstractDamage) -> bool: @@ -55,6 +55,10 @@ func _try_to_damage(body: Node2D, damage: AbstractDamage) -> bool: func _process_hit_for_projectile(_collided_body: Node2D) -> void: + delete() + + +func delete() -> void: queue_free() diff --git a/game/entities/weapons/cannon/abstract_cannon_projectile.gd b/game/entities/weapons/cannon/abstract_cannon_projectile.gd index 1786611..a0eac2e 100644 --- a/game/entities/weapons/cannon/abstract_cannon_projectile.gd +++ b/game/entities/weapons/cannon/abstract_cannon_projectile.gd @@ -15,4 +15,4 @@ func _process_hit_for_projectile(_collided_body: Node2D) -> void: func _on_explosion_particles_finished() -> void: - queue_free() + delete() diff --git a/game/entities/weapons/launcher/abstract_launcher_projectile.gd b/game/entities/weapons/launcher/abstract_launcher_projectile.gd index 17d8a0f..d831d24 100644 --- a/game/entities/weapons/launcher/abstract_launcher_projectile.gd +++ b/game/entities/weapons/launcher/abstract_launcher_projectile.gd @@ -71,4 +71,4 @@ func _process_hit_for_projectile(_collided_body: Node2D) -> void: func _on_explosion_particles_finished() -> void: - queue_free() + delete() diff --git a/game/entities/weapons/minelayer/abstract_minelayer_projectile.gd b/game/entities/weapons/minelayer/abstract_minelayer_projectile.gd index 300533b..706ef85 100644 --- a/game/entities/weapons/minelayer/abstract_minelayer_projectile.gd +++ b/game/entities/weapons/minelayer/abstract_minelayer_projectile.gd @@ -115,4 +115,4 @@ func _process_hit_for_projectile(_collided_body: Node2D) -> void: func _on_explosion_particles_finished() -> void: - queue_free() + delete() diff --git a/game/entities/weapons/railgun/abstract_railgun_projectile.gd b/game/entities/weapons/railgun/abstract_railgun_projectile.gd index f858526..ff41385 100644 --- a/game/entities/weapons/railgun/abstract_railgun_projectile.gd +++ b/game/entities/weapons/railgun/abstract_railgun_projectile.gd @@ -7,6 +7,6 @@ extends AbstractDirectHitProjectile func _process_hit_for_projectile(_collided_body: Node2D) -> void: if piercing == 0: - queue_free() + delete() else: piercing -= 1 diff --git a/game/entities/weapons/shrapnel/abstract_shrapnel_projectile.gd b/game/entities/weapons/shrapnel/abstract_shrapnel_projectile.gd index c613017..928ab46 100644 --- a/game/entities/weapons/shrapnel/abstract_shrapnel_projectile.gd +++ b/game/entities/weapons/shrapnel/abstract_shrapnel_projectile.gd @@ -16,4 +16,4 @@ func _physics_process(delta: float) -> void: func _process_distance(delta: float) -> void: _traveled_distance += _velocity.length() * delta if max_distance > 0 and _traveled_distance > max_distance: - queue_free() + delete() diff --git a/game/entities/weapons/tesla/abstract_tesla_projectile.gd b/game/entities/weapons/tesla/abstract_tesla_projectile.gd index 6800703..e690232 100644 --- a/game/entities/weapons/tesla/abstract_tesla_projectile.gd +++ b/game/entities/weapons/tesla/abstract_tesla_projectile.gd @@ -2,6 +2,11 @@ class_name AbstractTeslaProjectile extends AbstractDirectHitProjectile +const SPIKE_WIDTH = 1 +const SPIKE_MIN_LENGTH = 10.0 +const SPIKE_MAX_LENGTH = 50.0 + + @export_range(0.01, 0.5) var jink_min_delay: float = 0.01 @export_range(0.01, 0.5) var jink_max_delay: float = 0.01 @export_range(0, 360) var deviation_angle: int = 0 @@ -10,35 +15,59 @@ extends AbstractDirectHitProjectile var _collided_foes : Array[AbstractShip] = [] +var _is_dead := false +var _is_expanding := true +var _removed_point_count := 0 + +var _spikes_by_point_count : Dictionary[int, Array] = {} + @onready var jinkTimer : Timer = $JinkTimer +@onready var lifeTimer : Timer = $LifeTimer -@onready var particles_huge : GPUParticles2D = $ParticlesHuge -@onready var particles_large : GPUParticles2D = $ParticlesLarge -@onready var particles_medium : GPUParticles2D = $ParticlesMedium -@onready var particles_small : GPUParticles2D = $ParticlesSmall +@onready var line : Line2D = $Line2D func _ready() -> void: super._ready() _start_jink_timer() + line.reparent(get_tree().current_scene) + line.global_position = Vector2.ZERO + line.add_point(position) + + +func _physics_process(delta: float) -> void: + super._physics_process(delta) + + if _is_dead: + line.remove_point(0) + _removed_point_count += 1 + + if _removed_point_count in _spikes_by_point_count: + var lines := _spikes_by_point_count[_removed_point_count] + for l : Line2D in lines: + l.queue_free() + + if line.get_point_count() == 0: + delete() + + if _is_expanding: + line.add_point(position) func _process_hit_for_projectile(collided_body: Node2D) -> void: if collided_body is AbstractShip: _collided_foes.append(collided_body) - match _collided_foes.size(): - 1: particles_huge.emitting = false - 2: particles_large.emitting = false - 3: particles_medium.emitting = false damage.value = floor(damage.value/2.0) - if damage.value == 0: - queue_free() - else: - _apply_random_deviation() - _start_jink_timer() + _velocity = _apply_random_deviation(_velocity) + _start_jink_timer() + + +func delete() -> void: + line.queue_free() + super.delete() func _start_jink_timer() -> void: @@ -51,20 +80,52 @@ func _on_jink_timer_timeout() -> void: if foe: _target_foe(foe) if position.distance_to(foe.position) > no_deviation_distance: - _apply_random_deviation() + _velocity = _apply_random_deviation(_velocity) else: - _apply_random_deviation() + _velocity = _apply_random_deviation(_velocity) + + _create_spike() _start_jink_timer() +func _create_spike() -> void: + if _is_dead: return + + var point_count := line.get_point_count() + if not point_count in _spikes_by_point_count: + _spikes_by_point_count[point_count] = [] + + var spike_direction := _apply_random_deviation(_velocity).normalized() + var spike_length := randf_range(SPIKE_MIN_LENGTH, SPIKE_MAX_LENGTH) + var second_point := position + spike_direction * spike_length + + var spike : Line2D = line.duplicate() + get_parent().add_child(spike) + spike.clear_points() + spike.add_point(position) + spike.add_point(second_point) + spike.width = SPIKE_WIDTH + spike.width_curve = null + + _spikes_by_point_count[point_count].append(spike) + + func _target_foe(foe: AbstractShip) -> void: var current_speed := _velocity.length() var foe_direction := position.direction_to(foe.position) _velocity = current_speed * foe_direction -func _apply_random_deviation() -> void: +func _apply_random_deviation(vector: Vector2) -> Vector2: var deviation_rad := deg_to_rad(deviation_angle) var random_angle := randfn(0.0, deviation_rad / 6.0) - _velocity = _velocity.rotated(random_angle) + return vector.rotated(random_angle) + + +func _on_life_timer_timeout() -> void: + _is_dead = true + + +func _on_out_of_screen_timer_timeout() -> void: + _is_expanding = false diff --git a/game/entities/weapons/tesla/abstract_tesla_projectile.tscn b/game/entities/weapons/tesla/abstract_tesla_projectile.tscn index 538fb25..ebb1c6b 100644 --- a/game/entities/weapons/tesla/abstract_tesla_projectile.tscn +++ b/game/entities/weapons/tesla/abstract_tesla_projectile.tscn @@ -1,12 +1,8 @@ -[gd_scene load_steps=11 format=3 uid="uid://bi64687wtxi4d"] +[gd_scene load_steps=7 format=3 uid="uid://bi64687wtxi4d"] [ext_resource type="PackedScene" uid="uid://cdv5n4t47hr8i" path="res://game/entities/weapons/abstract_direct_hit_projectile.tscn" id="1_1oexk"] [ext_resource type="Script" uid="uid://bxcoa2eps0tt1" path="res://game/entities/weapons/tesla/abstract_tesla_projectile.gd" id="2_q73is"] [ext_resource type="Script" uid="uid://c27v705giygv4" path="res://game/data/damage/energy_damage.gd" id="3_l65ib"] -[ext_resource type="Texture2D" uid="uid://cqdctagygc0c0" path="res://particle_textures/energy_large.tres" id="4_1121u"] -[ext_resource type="Texture2D" uid="uid://d2k7bcwqr5v2q" path="res://particle_textures/energy_huge.tres" id="4_wtuxv"] -[ext_resource type="Texture2D" uid="uid://dk3t14mrgjmma" path="res://particle_textures/energy_medium.tres" id="5_wtuxv"] -[ext_resource type="Texture2D" uid="uid://c6aixtu6lbfud" path="res://particle_textures/energy_small.tres" id="7_eyfoy"] [sub_resource type="Resource" id="Resource_1121u"] resource_local_to_scene = true @@ -17,18 +13,9 @@ metadata/_custom_type_script = "uid://c27v705giygv4" [sub_resource type="CircleShape2D" id="CircleShape2D_l65ib"] radius = 5.0 -[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_wtuxv"] -particle_flag_disable_z = true -emission_shape = 2 -emission_sphere_radius = 5.0 -angle_min = -179.99998 -angle_max = 180.00002 -inherit_velocity_ratio = 0.5 -spread = 15.0 -initial_velocity_min = 1.0 -initial_velocity_max = 1.0 -gravity = Vector3(0, 0, 0) -turbulence_enabled = true +[sub_resource type="Curve" id="Curve_ptgbh"] +_data = [Vector2(0, 1), 0.0, 0.0, 0, 0, Vector2(0.10909091, 0.31467384), 0.0, 0.0, 0, 0, Vector2(0.2090909, 0.88342386), 0.0, 0.0, 0, 0, Vector2(0.3181818, 0.29701078), 0.0, 0.0, 0, 0, Vector2(0.4113636, 0.92934775), 0.0, 0.0, 0, 0, Vector2(0.53636366, 0.28943247), 0.0, 0.0, 0, 0, Vector2(0.7113636, 0.9399456), 0.0, 0.0, 0, 0, Vector2(0.8090909, 0.2792815), 0.0, 0.0, 0, 0, Vector2(0.9090909, 0.9399456), 0.0, 0.0, 0, 0, Vector2(1, 0.21837574), 0.0, 0.0, 0, 0] +point_count = 10 [node name="AbstractTeslaProjectile" instance=ExtResource("1_1oexk")] collision_layer = 0 @@ -47,35 +34,16 @@ shape = SubResource("CircleShape2D_l65ib") [node name="JinkTimer" type="Timer" parent="." index="2"] one_shot = true -[node name="ParticlesHuge" type="GPUParticles2D" parent="." index="3"] -amount = 32 -texture = ExtResource("4_wtuxv") -lifetime = 0.3 -preprocess = 0.1 -process_material = SubResource("ParticleProcessMaterial_wtuxv") +[node name="Line2D" type="Line2D" parent="." index="4"] +z_index = 10 +width = 3.0 +width_curve = SubResource("Curve_ptgbh") +default_color = Color(0.25490198, 0.6509804, 0.9647059, 1) +joint_mode = 1 -[node name="ParticlesLarge" type="GPUParticles2D" parent="." index="4"] -amount = 32 -texture = ExtResource("4_1121u") -lifetime = 0.4 -preprocess = 0.1 -process_material = SubResource("ParticleProcessMaterial_wtuxv") - -[node name="ParticlesMedium" type="GPUParticles2D" parent="." index="5"] -amount = 32 -texture = ExtResource("5_wtuxv") -lifetime = 0.5 -preprocess = 0.1 -process_material = SubResource("ParticleProcessMaterial_wtuxv") - -[node name="ParticlesSmall" type="GPUParticles2D" parent="." index="6"] -amount = 32 -texture = ExtResource("7_eyfoy") -lifetime = 0.5 -preprocess = 0.1 -process_material = SubResource("ParticleProcessMaterial_wtuxv") - -[node name="OutOfScreenTimer" parent="." index="7"] -wait_time = 1.0 +[node name="LifeTimer" type="Timer" parent="." index="5"] +wait_time = 0.5 +autostart = true [connection signal="timeout" from="JinkTimer" to="." method="_on_jink_timer_timeout"] +[connection signal="timeout" from="LifeTimer" to="." method="_on_life_timer_timeout"] diff --git a/game/entities/weapons/tesla/abstract_tesla_weapon.tscn b/game/entities/weapons/tesla/abstract_tesla_weapon.tscn index 44e18de..6bd2b3e 100644 --- a/game/entities/weapons/tesla/abstract_tesla_weapon.tscn +++ b/game/entities/weapons/tesla/abstract_tesla_weapon.tscn @@ -2,7 +2,7 @@ [ext_resource type="PackedScene" uid="uid://1o2ta17yc5bp" path="res://game/entities/weapons/abstract_weapon.tscn" id="1_rpud7"] [ext_resource type="Script" uid="uid://ctv408wdwvttc" path="res://game/entities/weapons/tesla/abstract_tesla_weapon.gd" id="2_08si3"] -[ext_resource type="Texture2D" uid="uid://c6aixtu6lbfud" path="res://particle_textures/energy_small.tres" id="5_dhfvk"] +[ext_resource type="Texture2D" uid="uid://dk3t14mrgjmma" path="res://particle_textures/energy_medium.tres" id="4_2dxgo"] [ext_resource type="Texture2D" uid="uid://6hh66k8s4a1e" path="res://images/weapons.png" id="7_ub67s"] [sub_resource type="AtlasTexture" id="AtlasTexture_ucdpq"] @@ -133,6 +133,8 @@ animations = [{ [sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_ifsj2"] lifetime_randomness = 0.5 particle_flag_disable_z = true +emission_shape = 1 +emission_sphere_radius = 6.03 angle_min = -179.99998 angle_max = 180.00002 inherit_velocity_ratio = 0.5 @@ -152,8 +154,8 @@ animation = &"player_idle" [node name="GPUParticles2D" type="GPUParticles2D" parent="." index="1"] amount = 16 -texture = ExtResource("5_dhfvk") -lifetime = 0.1 +texture = ExtResource("4_2dxgo") +lifetime = 0.2 fixed_fps = 10 process_material = SubResource("ParticleProcessMaterial_ifsj2")