So I'm making a game that depends greatly on time and how fast a person responds and I noticed a little bug where it has a randomized time. For example: I have the method
wait pick random .01 to 3 seconds
set ghost effect to 0
reset timer
repeat 5
wait .05 seconds
change ghost effect by 20
and each time I run this, I get different times. It can't be the fact that I'm randomizing the wait time because the reset timer
method is after that block. I ran some tests and I concluded that 7 out of the 12 times i got 0.8 seconds, which is what I'm trying to get. 3 out of the 12 times, I got 0.7, and 2 out of the 12 times I got 0.6. If there is any way to make the timer more accurate or improve my code to reduce lag, it would be much appreciated.
One general solution would be to make how ghosted the sprite is be a "function" based on how long since the animation started. This would work something like this:
This animation animates the sprite changing all the way around the color effect wheel across four seconds. It'll be most clear how that works if we go over it step by step.
We want our animation to last for four seconds. But how do we actually make it last that long? As was seen in your script, just using a "repeat (40): wait 0.1 seconds" doesn't always result in waiting exactly four seconds. Instead, we use a "repeat until" loop: "repeat until (timer - animation start) > 4".
We get the "animation start" variable just by setting it to the current timer value when we start the animation. We'll see "timer - animation start" again later in; what it really means is the progress through the animation: "timer - animation start" starts at zero and gradually increases to four as the animation runs. (Of course, when it reaches 4, we want to stop the animation, and that's why we use the "repeat until" block.)
Here's the big question: how, given the current amount of time through the animation, can we decide what the color effect should be? It turns out, that's not so hard to answer, but we do need to think through it since it takes math. We want to transition from 0 to 200 over a period of 4 seconds. You can write that down as a rate: 200 units per 4 seconds, so, 200 / 4. Then we just multiply that rate by how far through the animation we are: (200 / 4 * progress). Progress is easy to get, again; we just reuse the "timer - animation start" blocks.
Do you believe that I'm right? Here's a list with some numbers to convince you (but really, you should try out this script yourself!):
To try this yourself, I do recommend implementing some "artificial lag". That just means adding a "wait (random 0.1 - 0.3) seconds" block to simulate the lag that might show up in a very complex project or on a slow computer.
Since we're just dealing with a basic math formula, it's very easy to change the numbers to get a different result. Here is a script which transitions from 0 to 100 over 2 seconds:
But here's a point where you might find a "gotcha" -- look at what happens if you add artificial lag:
The cat turns ghost-y.. but doesn't ENTIRELY disappear! Yikes! So, what caused this?
Here's the problem: The animation stops before (timer - animation start) is exactly 2 seconds. So, we never run that 2s step, where the ghost effect would be 100 - and we're left with a sprite that is not entirely ghosted.
Luckily, the solution is simple. Just make sure you additionally switch to the final state after the animation has ended. Of course, that just means attaching the appropriate "set effect" block right after the "repeat until" loop:
Now the sprite's ghost effect will be set to 100 immediately after the loop, regardless of whatever it ended with.
By the way, when you tested these scripts out for yourself - you did, didn't you? - did you notice that this animates very smoothly? In fact, it animates as smoothly as possible. It will always animate at the top framerate that the user's computer can handle, since it runs every Scratch frame (there is no "wait n seconds" block)! Also, a simple test of your understanding - how can you re-implement the "glide (n) seconds to (x) (y)" block using this? It's definitely possible!