From dce433e0687997eac07eeda174c04cb601abc1cd Mon Sep 17 00:00:00 2001 From: Nikolai Fedorov Date: Thu, 23 Apr 2026 14:57:14 +0300 Subject: [PATCH] add hit and merge vfx --- scripts/Enemy.gd | 4 ++++ scripts/FX.gd | 51 +++++++++++++++++++++++++++++++++++++++++++ scripts/FX.gd.uid | 1 + scripts/KickSystem.gd | 1 + scripts/Player.gd | 1 + 5 files changed, 58 insertions(+) create mode 100644 scripts/FX.gd create mode 100644 scripts/FX.gd.uid diff --git a/scripts/Enemy.gd b/scripts/Enemy.gd index 630f839..a4c062d 100644 --- a/scripts/Enemy.gd +++ b/scripts/Enemy.gd @@ -141,6 +141,7 @@ func _chase(delta: float) -> void: contact_timer = CONTACT_CD if target.has_method("take_damage"): target.take_damage(damage_to_player) + FX.hit_spark(target.global_position + Vector3(0, 0.5, 0), get_parent(), Color(0.95, 0.18, 0.08)) if randf() < 0.3: var knock_dir := diff.normalized() if dist > 0.01 else -global_transform.basis.z knock_dir.y = 0.0 @@ -225,6 +226,7 @@ func _try_enemy_kick() -> void: var player_toughness: int = target.get("toughness_tier") if target.get("toughness_tier") != null else 0 if player_toughness < kick_tier: target.call("receive_kick", kick_dir, 12.0 + kick_tier * 10.0) + FX.hit_spark(target.global_position + Vector3(0, 0.5, 0), get_parent(), Color(0.95, 0.18, 0.08)) enemy_kick_timer = ENEMY_KICK_COOLDOWN func _fly(delta: float) -> void: @@ -328,9 +330,11 @@ func _on_merge_complete() -> void: var merge_type := _next_enemy_type(enemy_type) var new_level: int = enemy_level + 1 var new_wave: int = wave_num + var par := get_parent() if is_instance_valid(merge_partner): merge_pos = (global_position + merge_partner.global_position) / 2.0 merge_partner.queue_free() + FX.merge_smoke(merge_pos + Vector3(0, 0.3, 0), par) queue_free() emit_signal("merged", true) var tree := get_tree() diff --git a/scripts/FX.gd b/scripts/FX.gd new file mode 100644 index 0000000..0beb214 --- /dev/null +++ b/scripts/FX.gd @@ -0,0 +1,51 @@ +class_name FX + +# Small burst of colored spheres flying outward from impact point. +static func hit_spark(pos: Vector3, parent: Node, color: Color = Color(1.0, 0.72, 0.1)) -> void: + const COUNT := 8 + for i in range(COUNT): + var m := MeshInstance3D.new() + var sphere := SphereMesh.new() + sphere.radius = 0.12 + sphere.height = 0.24 + sphere.radial_segments = 4 + sphere.rings = 2 + var mat := StandardMaterial3D.new() + mat.albedo_color = color + mat.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED + mat.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA + m.material_override = mat + m.mesh = sphere + parent.add_child(m) + m.global_position = pos + + var angle := TAU * float(i) / float(COUNT) + randf() * 0.6 + var dist := randf_range(0.7, 1.8) + var end := pos + Vector3(cos(angle) * dist, randf_range(0.3, 1.3), sin(angle) * dist) + + var tw := m.create_tween().set_parallel(true) + tw.tween_property(m, "global_position", end, 0.28) + tw.tween_property(m, "scale", Vector3(0.05, 0.05, 0.05), 0.28) + tw.tween_method(func(a: float): mat.albedo_color.a = a, 1.0, 0.0, 0.28) + tw.chain().tween_callback(m.queue_free) + +# Expanding smoke sphere for merges. +static func merge_smoke(pos: Vector3, parent: Node) -> void: + var m := MeshInstance3D.new() + var sphere := SphereMesh.new() + sphere.radius = 0.4 + sphere.height = 0.8 + var mat := StandardMaterial3D.new() + mat.albedo_color = Color(0.90, 0.90, 0.90, 0.85) + mat.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED + mat.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA + mat.cull_mode = BaseMaterial3D.CULL_DISABLED + m.material_override = mat + m.mesh = sphere + parent.add_child(m) + m.global_position = pos + + var tw := m.create_tween().set_parallel(true) + tw.tween_property(m, "scale", Vector3(5.5, 3.5, 5.5), 0.55) + tw.tween_method(func(a: float): mat.albedo_color.a = a, 0.85, 0.0, 0.55) + tw.chain().tween_callback(m.queue_free) diff --git a/scripts/FX.gd.uid b/scripts/FX.gd.uid new file mode 100644 index 0000000..b0b5fa3 --- /dev/null +++ b/scripts/FX.gd.uid @@ -0,0 +1 @@ +uid://dqx8r64rkj7j diff --git a/scripts/KickSystem.gd b/scripts/KickSystem.gd index d082563..90ca8c4 100644 --- a/scripts/KickSystem.gd +++ b/scripts/KickSystem.gd @@ -60,3 +60,4 @@ static func _execute_recipe(a: Node3D, b: Node3D, recipe: Dictionary) -> void: var result := scene.instantiate() as Node3D parent.add_child(result) result.global_position = pos + FX.merge_smoke(pos + Vector3(0, 0.3, 0), parent) diff --git a/scripts/Player.gd b/scripts/Player.gd index d7f17b4..e550776 100644 --- a/scripts/Player.gd +++ b/scripts/Player.gd @@ -189,6 +189,7 @@ func _do_kick() -> void: else: force = 80.0 best.call("receive_kick", best_dir, force) + FX.hit_spark(best.global_position + Vector3(0, 0.4, 0), get_parent()) _squish_effect() func _try_interact() -> void: