+1 vote

I have an animated sprite of a rotating coin. The coin can be gold or silver and there is a separate animation for each color.

User action can cause the color to change. When this happens, I replace the animation of the sprite as well as restore the correct frame number so that the color transition would look seamless:

var oldFrame = $CoinSprite.frame
if $CoinSprite.animation == "Gold":
    $CoinSprite.animation = "Silver"
else:
    $CoinSprite.animation = "Gold"
$CoinSprite.frame = oldFrame

The problem is that while I can restore the frame, it goes back to the beginning of the frame. This little lost time cause the animation to loose synch with the other coins.

enter image description here

Is there a way to change the animation while retaining the "position" inside the frame? Is there a way to sync all coin instances?

asked Sep 29, 2018 in Engine by Artium Nihamkin (251 points)

2 Answers

+1 vote
Best answer

Here are four options:

  1. If your animation has a track for the Sprite texture, you can just swap out the gold sprite texture for the silver sprite texture, rather than have an entirely different animation for each color. This would cause a seamless color change without tampering at all with the time of the animation.

  2. You could also use the advance() method of the AnimationPlayer to advance the animation however many milliseconds you are behind.

  3. As an alternative, you could have your coin texture in grayscale and use the Sprite's modulate attribute to change the color.

  4. Alternatively, you could write a palette swap shader on the grayscale Sprite and just change the palette when your player selects a new color.

answered Sep 29, 2018 by Diet Estus (1,449 points)
selected Sep 30, 2018 by Artium Nihamkin

These are some great ideas. What I eventually did was to to add a root timer that increments a variable each tick. Then the coins set the frame according to the counter int the _process (instead of using the animation itself). If I had to do it again I would prbably use 1 or 3.

+1 vote

Maybe if you put all your coins in a group, and whenever a coin changes you can set the frame in each coin all at once by doing the following.

#This function calls when changing the animation, and is inside the coin script.
func on_coin_change():
    ...
    get_tree().set_group("name of coins group", "frame", frame)
answered Sep 29, 2018 by SIsilicon (3,705 points)

This is interesting idea, but it will cause all the coins to stutter at the time of the swap.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.