Added Coin Sparkle Effects (#350)

* Just the Coin Sparkle stuff

FYI, if a property in the json is formatted like `exa.exb` then it reads `exa` as another object and `exb` as a property in `exa` assuming the root `property_node` contains this object.
Also primarily for Resource Packs to change how the particles work and should explain how I got there with my personal SMAS skin.

* Added Coin Sparkle Texture to Scene

Of course I broke it in some form.
This commit is contained in:
KirbyKidJ
2025-09-28 03:30:45 -07:00
committed by GitHub
parent f6a31f8508
commit 6d23f9dcd4
10 changed files with 108 additions and 15 deletions

View File

@@ -85,6 +85,9 @@
"loop": true
}
},
"properties": {
"can_spawn_particles": true
},
"variations": {
"default": {"source": "StaticCoin.png", "rect": [0, 0, 64, 16]},
"Underground": {"source": "StaticCoin.png", "rect": [0, 16, 64, 16]},

View File

@@ -31,6 +31,9 @@
"loop": true
}
},
"properties": {
"can_spawn_particles": true
},
"variations": {
"default": {
"source": "SpinningCoin.png",

View File

@@ -0,0 +1,10 @@
{
"properties": {
"amount": 3,
"process_material.emission_shape": 1,
"material.particles_anim_h_frames": 8
},
"variations": {
"default": {"source": "CoinSparkle.png", "rect": [0, 0, 64, 8]}
}
}

View File

@@ -0,0 +1,42 @@
[gd_scene load_steps=6 format=3 uid="uid://b1ytbn4cu7msu"]
[ext_resource type="Texture2D" uid="uid://dkebo0uw0dkkw" path="res://Assets/Sprites/Particles/CoinSparkle.png" id="1_0guw6"]
[ext_resource type="Script" uid="uid://cbal8ms2oe1ik" path="res://Scripts/Classes/Components/ResourceSetterNew.gd" id="2_wdqt2"]
[ext_resource type="JSON" path="res://Assets/Sprites/Particles/CoinSparkle.json" id="3_wdqt2"]
[sub_resource type="CanvasItemMaterial" id="CanvasItemMaterial_0guw6"]
particles_animation = true
particles_anim_h_frames = 8
particles_anim_v_frames = 1
particles_anim_loop = false
[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_wdqt2"]
particle_flag_disable_z = true
emission_shape = 1
emission_sphere_radius = 16.0
gravity = Vector3(0, 0, 0)
anim_speed_min = 2.0
anim_speed_max = 2.0
[node name="CoinSparkle" type="GPUParticles2D"]
material = SubResource("CanvasItemMaterial_0guw6")
emitting = false
amount = 3
texture = ExtResource("1_0guw6")
lifetime = 0.5
one_shot = true
explosiveness = 0.7
interpolate = false
fract_delta = false
process_material = SubResource("ParticleProcessMaterial_wdqt2")
[node name="ResourceSetterNew" type="Node" parent="." node_paths=PackedStringArray("node_to_affect", "property_node")]
script = ExtResource("2_wdqt2")
node_to_affect = NodePath("..")
property_node = NodePath("..")
property_name = "texture"
mode = 1
resource_json = ExtResource("3_wdqt2")
metadata/_custom_type_script = "uid://cbal8ms2oe1ik"
[connection signal="ready" from="." to="." method="set_emitting" binds= [true]]

View File

@@ -62,9 +62,10 @@ sprite_frames = SubResource("SpriteFrames_nu35s")
autoplay = "default"
frame_progress = 0.487032
[node name="ResourceSetterNew" type="Node" parent="Sprite" node_paths=PackedStringArray("node_to_affect")]
[node name="ResourceSetterNew" type="Node" parent="Sprite" node_paths=PackedStringArray("node_to_affect", "property_node")]
script = ExtResource("3_uahob")
node_to_affect = NodePath("..")
property_node = NodePath("../..")
property_name = "sprite_frames"
resource_json = ExtResource("4_thymr")
metadata/_custom_type_script = "uid://cbal8ms2oe1ik"

View File

@@ -51,9 +51,10 @@ sprite_frames = SubResource("SpriteFrames_sax2u")
autoplay = "default"
frame_progress = 0.710764
[node name="ResourceSetterNew" type="Node" parent="Sprite" node_paths=PackedStringArray("node_to_affect")]
[node name="ResourceSetterNew" type="Node" parent="Sprite" node_paths=PackedStringArray("node_to_affect", "property_node")]
script = ExtResource("3_7mdmn")
node_to_affect = NodePath("..")
property_node = NodePath("../..")
property_name = "sprite_frames"
resource_json = ExtResource("4_b5lmc")
metadata/_custom_type_script = "uid://cbal8ms2oe1ik"

View File

@@ -1,4 +1,8 @@
[gd_scene load_steps=3 format=3 uid="uid://b1ytbn4cu7msu"]
[gd_scene load_steps=6 format=3 uid="uid://b1ytbn4cu7msu"]
[ext_resource type="Texture2D" uid="uid://dkebo0uw0dkkw" path="res://Assets/Sprites/Particles/CoinSparkle.png" id="1_4p5kk"]
[ext_resource type="Script" uid="uid://cbal8ms2oe1ik" path="res://Scripts/Classes/Components/ResourceSetterNew.gd" id="2_wdqt2"]
[ext_resource type="JSON" path="res://Assets/Sprites/Particles/CoinSparkle.json" id="3_igsqc"]
[sub_resource type="CanvasItemMaterial" id="CanvasItemMaterial_0guw6"]
particles_animation = true
@@ -18,6 +22,7 @@ anim_speed_max = 2.0
material = SubResource("CanvasItemMaterial_0guw6")
emitting = false
amount = 3
texture = ExtResource("1_4p5kk")
lifetime = 0.5
one_shot = true
explosiveness = 0.7
@@ -25,8 +30,13 @@ interpolate = false
fract_delta = false
process_material = SubResource("ParticleProcessMaterial_wdqt2")
[node name="Timer" type="Timer" parent="."]
autostart = true
[node name="ResourceSetterNew" type="Node" parent="." node_paths=PackedStringArray("node_to_affect", "property_node")]
script = ExtResource("2_wdqt2")
node_to_affect = NodePath("..")
property_node = NodePath("..")
property_name = "texture"
mode = 1
resource_json = ExtResource("3_igsqc")
metadata/_custom_type_script = "uid://cbal8ms2oe1ik"
[connection signal="ready" from="." to="." method="set_emitting" binds= [true]]
[connection signal="timeout" from="Timer" to="." method="queue_free"]

View File

@@ -168,7 +168,16 @@ func apply_properties(properties := {}) -> void:
if value is Array:
property_node.set(i, Vector2(value[0], value[1]))
else:
property_node.set(i, properties[i])
var obj = property_node
for p in i.split("."):
if not is_instance_valid(obj): continue
if obj.get(p) is Object:
if obj.has_method("duplicate"):
obj.set(p, obj[p].duplicate(true))
obj = obj[p]
else:
obj.set(p, properties[i])
continue
func get_variation_json(json := {}) -> Dictionary:
var level_theme = Global.level_theme

View File

@@ -3,6 +3,8 @@ const COIN_SPARKLE = preload("res://Scenes/Prefabs/Particles/CoinSparkle.tscn")
@export var spinning_coin_scene: PackedScene = null
var can_spawn_particles := true
signal collected
func area_entered(area: Area2D) -> void:
@@ -11,11 +13,16 @@ func area_entered(area: Area2D) -> void:
func collect() -> void:
collected.emit()
$Hitbox.area_entered.disconnect(area_entered)
Global.coins += 1
DiscoLevel.combo_meter += 10
Global.score += 200
AudioManager.play_sfx("coin", global_position)
queue_free()
if can_spawn_particles:
summon_particle()
$Sprite.queue_free()
else:
queue_free()
func summon_block_coin() -> void:
var node = spinning_coin_scene.instantiate()
@@ -25,5 +32,5 @@ func summon_block_coin() -> void:
func summon_particle() -> void:
var node = COIN_SPARKLE.instantiate()
node.global_position = global_position
add_sibling(node)
node.finished.connect(queue_free)
add_child(node)

View File

@@ -2,19 +2,26 @@ extends Node2D
const COIN_SPARKLE = preload("res://Scenes/Prefabs/Particles/CoinSparkle.tscn")
var velocity := Vector2(0, -300)
var can_spawn_particles := true
func _ready() -> void:
Global.coins += 1
Global.score += 200
AudioManager.play_sfx("coin", global_position)
func _physics_process(delta: float) -> void:
global_position += velocity * delta
velocity.y += (15 / delta) * delta
if get_node_or_null("Sprite") != null:
global_position += velocity * delta
velocity.y += (15 / delta) * delta
func vanish() -> void:
queue_free()
if can_spawn_particles:
summon_particle()
$Sprite.queue_free()
else:
queue_free()
func summon_particle() -> void:
var node = COIN_SPARKLE.instantiate()
node.global_position = global_position
add_sibling(node)
node.finished.connect(queue_free)
add_child(node)