Conversation
Previously it had the NO_EDIT sprite frames assigned on the root node, but the ink blob one on the AnimatedSprite2D. At runtime, the former overwrote the latter. This is confusing. Set the same on both. Previously, it had a sound effect assigned on the AudioStreamPlayer2D but not on the root node, and again the root node's null stream would be set on the AudioStreamPlayer2D at runtime. Clear it.
We have found that this pattern can cause code to run in an unexpected order. We now prefer to early-return from the setter, and call it again explicitly from `_ready()`.
|
Play this branch at https://play.threadbare.game/branches/endlessm/wjt/customise-projectile-via-scene-only. (This launches the game from the start, not directly at the change(s) in this pull request.) |
Previously, all instances of the "fill game" used the same Projectile scene. To customise its appearance, the ThrowingEnemy scene had a whole series of properties that would be assigned each instantiated projectile, in addition to assigning a label & optional modulate color based on the target barrel. This is not a very "Godot-ish" way to do it. Conceptually, different projectiles should be different scenes that have similar structures and reuse common scripts. Instead, we have had to manually re-export properties from deep inside the projectile scene, and propagate their values from the ThrowingEnemy scene. Since commit 402f2ab ("ThrowingEnemy: Export the projectile scene") it has been possible to customise which projectile scene is instantiated by any specific enemy, but this isn't enough either for Stella or for Champ. In Stella, we wanted the invisible enemies to throw, each time, a random choice between a starfish (which matches the ship "barrel") or one of three fish (which don't). But this wasn't possible. Similarly in Champ we want the three different colours of fish to potentially be different sprites; they currently happen to be recoloured versions of the same asset that could be done with the projectile modulate logic but we don't want to limit contestants to this. So: 1. For each StoryQuest that previously reused the generic projectile scene, create one (or more!) scenes specific to the quest. This does introduce some duplication but I decided that the scenes are small enough that using inherited scenes is more trouble than it's worth. 2. Similarly, make a dedicated ink blob projectile scene for the core game. 3. Move the generic projectile scene to the NO_EDIT template, so that it will be duplicated when creating a new StoryQuest. 4. Remove the sprite_frames and hit_sound_stream properties from projectile.gd: these can be set by modifying the scene. 5. Remove the projectile_sprite_frames, projectile_hit_sound_stream, projectile_small_fx_scene, projectile_big_fx_scene, and projectile_trail_fx_scene properties from throwing_enemy.gd: these can be set by modifying the projectile scene that it spawns. 6. Add the ability to spawn different projectile scenes based on the target label. This is adapted from similar code in the Champ quest to use different sprite frames per label. Use this in Champ and Stella. In both cases define a custom throwing enemy scene, this time as an inherited scene: there are huge animations in the enemy scene so in this case I thought this was worth it. 7. Break the projectile-spawning code up a little. Having done this, simplify some of the StoryQuest-specific projectile customisations. Resolves #1873 Resolves #1874
a6ef16a to
7550a4f
Compare
| ## When launching a projectile, if the chosen label is found in this dictionary, | ||
| ## the associated scene will be used. If not, the default [member projectile_scene] | ||
| ## will be used. | ||
| @export var projectile_scene_for_label: Dictionary[String, PackedScene]: |
There was a problem hiding this comment.
This is a "colo(u)r of bikeshed" situation but maybe this should be projectile_scene_per_label. I want projectile_scene to be at the start of the property name because all properties in the Projectile group must begin with projectile_ for their names to be shortened in the inspector (#1869).
| script/source = "class_name ChampFillGameLogic | ||
| extends FillGameLogic | ||
| # | ||
| #@export var lab: String = \"\" | ||
| # | ||
| #func _ready() -> void: | ||
| #var color_per_label = {\"a\": Color(.3,.5,6), \"b\": Color(.9,.1,6),\"c\": Color(.1,.8,.2)} | ||
| #for enemy: ThrowingEnemy in get_tree().get_nodes_in_group(\"throwing_enemy\"): | ||
| #enemy.allowed_labels = allowed_labels | ||
| #enemy.color_per_label = color_per_label | ||
| " |
There was a problem hiding this comment.
This embedded script doesn't do anything so I removed it in passing.
| editor_draw_limits = true | ||
|
|
||
| [node name="ThrowingEnemies" type="Node2D" parent="OnTheGround" unique_id=1014610845] | ||
| visible = false |
There was a problem hiding this comment.
I moved this to the AnimatedSprite2D inside the enemy scene.
| else: | ||
| # Default to original projectile sprite frames | ||
| projectile.sprite_frames = preload("uid://b00dcfe4dtvkh") | ||
| if projectile.label in color_per_label: |
There was a problem hiding this comment.
@felixwalberg I like this design. I moved the spirit of this into throwing_enemy.gd - but selecting a per-label scene not SpriteFrames.
There was a problem hiding this comment.
To do:
- Resave every scene that references this scene to update the path
- Test that this this actually get duplicated & relinked correctly by the tool - I assume so but actually this will be the first PackedScene property.
Rework how projectiles are customised
Previously, all instances of the "fill game" used the same Projectile
scene. To customise its appearance, the ThrowingEnemy scene had a whole
series of properties that would be assigned each instantiated
projectile, in addition to assigning a label & optional modulate color
based on the target barrel.
This is not a very "Godot-ish" way to do it. Conceptually,
different projectiles should be different scenes that have similar
structures and reuse common scripts. Instead, we have had to manually
re-export properties from deep inside the projectile scene, and
propagate their values from the ThrowingEnemy scene.
Since commit 402f2ab
("ThrowingEnemy: Export the projectile scene") it has been possible to
customise which projectile scene is instantiated by any specific enemy,
but this isn't enough either for Stella or for Champ. In Stella, we
wanted the invisible enemies to throw, each time, a random choice
between a starfish (which matches the ship "barrel") or one of three
fish (which don't). But this wasn't possible. Similarly in Champ we want
the three different colours of fish to potentially be different sprites;
they currently happen to be recoloured versions of the same asset that
could be done with the projectile modulate logic but we don't want to
limit contestants to this.
So:
For each StoryQuest that previously reused the generic projectile
scene, create one (or more!) scenes specific to the quest. This does
introduce some duplication but I decided that the scenes are small
enough that using inherited scenes is more trouble than it's worth.
Similarly, make a dedicated ink blob projectile scene for the core
game.
Move the generic projectile scene to the NO_EDIT template, so that it
will be duplicated when creating a new StoryQuest.
Remove the sprite_frames and hit_sound_stream properties from
projectile.gd: these can be set by modifying the scene.
Remove the projectile_sprite_frames, projectile_hit_sound_stream,
projectile_small_fx_scene, projectile_big_fx_scene, and
projectile_trail_fx_scene properties from throwing_enemy.gd: these
can be set by modifying the projectile scene that it spawns.
Add the ability to spawn different projectile scenes based on the
target label. This is adapted from similar code in the Champ quest to
use different sprite frames per label. Use this in Champ and Stella.
In both cases define a custom throwing enemy scene, this time as an
inherited scene: there are huge animations in the enemy scene so in
this case I thought this was worth it.
Break the projectile-spawning code up a little. Having done this,
simplify some of the StoryQuest-specific projectile customisations.
Resolves #1873
Resolves #1874