RhenaudTheLukark / CreateYourFrisk

Rhenaud The Lukark's Unitale fork
GNU General Public License v3.0
132 stars 56 forks source link

[Feature] Add ability for sprites to blink #104

Closed CerBor closed 2 years ago

CerBor commented 2 years ago

Hello. In the battle, when the soul gets hurt, it gets invulnerable and also blinks for some seconds. Can someone please add ability for sprites to blink?

DimitriBarronmore commented 2 years ago

Making sprites blink in code is exceptionally simple, particularly if you don't need it to be 100% accurate to how the soul blinks while the player has invincibility frames. All you need is to use a timer and change the opacity of the sprite to 0 and back at regular intervals. It takes only a couple of lines and can be tailored nicely to your needs, whereas building this into the sprite object would be needlessly limited in comparison.

If you want the exact look of the hurt player then a quick peek into the code is plenty enough to give you what you need. Looking at the player code, we can see that the lines responsible for the player blinking are 434-438:

// if the invulnerability timer has more than 0 seconds (usually when you get hurt), blink to reflect the hurt state
        if (invulTimer > 0.0f) {
            invulTimer -= Time.deltaTime;
            selfImg.enabled = !(invulTimer % BLINK_CYCLE_SECONDS > BLINK_CYCLE_SECONDS / 2.0f) || invulTimer <= 0.0f;
        }

BLINK_CYCLE_SECONDS is a constant equal to 0.18f, and controls the time a full blink (invisible and visible again) takes. To translate the process:

This might seem a bit daunting, but truthfully this code can be simplified quite a lot and depending on your purposes it may well be easier to use your own way of checking the timer. For certain purposes I often rather enjoy just setting the sprite's alpha to a sine wave.

For that matter, it's also an entirely valid solution to just add a second fully transparent sprite of the same size and have CYF switch between them using sprite.SetAnimation, which would give you exactly the same blink with something like Player.sprite.loopmode = "LOOP"; Player.sprite.SetAnimation({"soul", "blank"}, 0.18 / 2). Then you just need to keep track of turning it back off.

CerBor commented 2 years ago

Oh, thank you