Do anyone know how constant is the duration of a frame in PICO-8?
I am considering making samething that will use rhythm and decided to use the frames as a time basis. First thing I implemented was a simple metronome.
Code below:
This function rounds a number n to the nearest integer that is multiple of m:
function round_mult(n, m) -- n is the number to be -- rounded. -- m is the integer -- significance. -- returns the nearest -- multiple of m. if (n % m) == 0 then return n else v_up = flr(n) + 1 v_up = n + (m - n % m) v_dn = flr(n) v_dn = n - (n % m) if (v_up - n) <= (n - v_dn) then return v_up else return v_dn end end end |
On the metronome itself, I want to put a bpm and use the nearest bpm that can fit inside a frame time.
function _init() bpm = 50 -- this is not necessarily the actual bpm ingame. btime = 60/bpm -- time per beat in seconds subdivs = 4 -- subdivisions of a beat fps = stat(7) -- framerate ftime = 1/fps -- time per frame bframes = round_mult( btime / ftime, subdivs) -- the actual bpm to be used, but in frames instead of seconds curframe = 1 -- frame count starts at 1 end function _update() if curframe == bframes then sfx(1) -- this is the end of a beat curframe = 1 elseif (curframe % (bframes / subdivs)) == 0 then sfx(0) -- this is a subdivision of a beat curframe = curframe + 1 else curframe = curframe + 1 end end function _draw() cls() print(tostr(curframe)) end |
The thing is, I recorded the beeps and I noticed (using audacity) that the times of the beats are not always the same. It differs a little bit. Can frames take slightly longer or shorter times to occur inside PICO-8?
maybe look into _update60() and be sure to use the console and not the web browser.
Take care to use the local
keyword for local variables. Otherwise you're declaring globals, even inside of functions.
PICO-8 calls _update() 30x per second, or _update60() 60x per second, depending on which is present.
Any timing you do that uses the update clock cannot be any more precise than to the level of 1/30th or 1/60th of a second.
PICO-8's music clock seems to run at 120Hz. You can see this by setting an SFX to run at SPD=120, which actually means its notes are all 120 clock ticks long, so each note in the SFX will be one second long.
Similarly to the update clock, you can't play a note at a time any more precise than 1/120th of a second. The precise time it plays likely depends on how much time has elapsed during the current frame. I haven't tested this, though, so I don't know if calling sfx() triggers the sound change immediately, buffers it for the next 1/120th, or buffers it for the next update.
If it doesn't buffer the triggered sound, then for consistent timing, it's probably best to trigger new sounds at the start of the update, because the remainder of most games' updates usually take variable amounts of time. That isn't always viable for triggered sounds, but for unconditional stuff like a beat, it'd work.
^Much better long answer of what I was gettin' at. ^
As always, Felice. ;p
It depends on what your use-case is, but instead of counting frames, I've found stat(26) i.e. "ticks played on current pattern" to be a useful source of timing which isn't affected by potential frameskips (but you do have to be playing music...it made even more sense in my use-case because I specifically wanted to maintain synchronization/timing with the music on a tween animation).
I suppose you could also use the undocumented time() or t() to similar effect, without having to have music playing.
[Please log in to post a comment]