Kronos 1.0, Lightweight Timer Manager for PICO-8

What is Kronos?
This is my first experiment with PICO-8, one of the basic element of an application, as I am used to work.
Kronos is a fast, simple timer manager. It allows you to schedule delayed or recurring actions using a simple and intuitive API.
Whether ou're creating game logic, effects, cutscenes or test harnesses, Kronos lets you easily manage multiple timers, track their status, and trigger custom functions when they expire.
How It Works.
Kronos maintains an internal list of timers, each with:
- A unique ID (either auto-assigned or manually specified).
- A tick countdown (in frames).
- An optional callback function.
- An optional repeat flag (for recurring timers)
- Every time _update() is called, Kronos decrements all active timers.
- Checks for timers that have reached 0.
- Triggers their callback (if provided).
- Removes expired timers (or resets them if they are repeatable).
- Recycles their ID for future reuse.
How to Use It.
Initialization.
Simply include the Kronos library in your project (it's just one tab). No setup is required other than calling:
krns._addtmr(...) |
Adding a Timer.
There are two ways to create a timer:
1. Auto-ID timer:
krns._addtmr(ticks, callback) |
2. Manual-ID timer:
krns._addtmr(id, ticks, callback) |
where
- id is the id of the timer. Any timer with the same id will be overwritten.
- ticks is the number of frames until the timer expires.
- callback is an optional function that will be called when the timer completes. It should return true to confirm it ran.
Another optional value is a boolean parameter, to tell the timer to repeat. Default is false.
krns._addtmr(id, ticks, callback, true) |
To run the Kronos system you need to add to the _update() function
krns._upd() |
Every time _update() is called, Kronos:
- Decrements all active timers.
- Checks for timers that have reached 0.
- Triggers their callback (if provided).
- Removes expired timers (or resets them if they are repeatable).
- Recycles their ID for future reuse.
Handling Timer Events
The callback function you provide can trigger anything like spawning particles, playing a sound, or launching another timer. When you had ha timer you need to add a function as parameter. This function can do something, but it must return true to track the event completed.
krns._addtmr(60, function() sfx(0) return true end) |
Removing a Timer
You can remove a timer early by its ID:
krns._deltmr(3) |
Debug Overlay
Kronos includes a built-in simple debug overlay:
krns.dbg() |
This shows:
- A list of active timer IDs.
- A list of recycled (free) IDs.
It draws a small info box at the bottom of the screen, perfect for testing or development builds.
Visual Demo
The included demo simulates a timer stress test:
- A random number of timers is started on launch.
- Each timer shows a progress bar and remaining ticks.
- When a timer completes, it may respawn a new one.
- A sprite-based logo is displayed at the top of the screen.
You can use this demo as:
- A benchmark or visual test.
- A reference for integrating Kronos in your own project.
Import Instructions
To use Kronos in your own cart:
- Copy the contents of the Kronos tab into your project.
- Optionally include the 'join()' helper function (if not already present).
- Use 'krns._addtmr(...)', 'krns._upd()', 'krns._deltmr(...)', and 'krns.dbg()' as needed.
Credits & License
Kronos was created by Francesco De Simone A.K.A. Digimorf as a reusable system for timer scheduling in PICO-8.
Feel free to use it in your projects, credit is appreciated but not required.
License: MIT / CC0 / Public Domain (your choice)
Any feedback positive or negative is appreciated, feel free to post your comments, improvementcs or suggestion.
Enjoy!



With your code, normal ids and auto-generated ids can easily collide. I would start the automatic-IDs with 0x8000 and important, don't reuse automatic manual ids.
also for tokens. kronos_addtimer need 1 token, kronos.addtimer needs 2 token.
But i personal prefer automatic-ids only. And in this case, simple use the table-entry for the timer.
kronos={} function kronos_addtimer(tick,fn,rep) return add(kronos,{t=tick,f=fn,r=rep,tt=tick}) end function kronos_deltimer(x) del(kronos,x) end function kronos_update() for k in all(kronos) do k.t-=1 if k.t<=0 then k.f(k) if (k.r) k.t=k.tt else del(kronos,k) end end end -- simple example mytimer=kronos_addtimer(6000,function(t) t.count+=1 end,true) mytimer.count=0 ... mytimer=kronos_deltimer(mytimer) -- delete timer - and nil mytimer-variable! |


Hi GPI,
Thank you for your reply, and good job with all of your cartridges! I like your work very much.
Actually, I decided to include also the opportunity for the user to specify the ID for any needs. And the manual control over the ID lets the user to quickly redefine active timer. But this is not a big deal.
What I didn’t know is that the access to functions and properties of the structure take more than one token, so you are suggesting that if I want to optimize more the memory use of this tool, I need to simplify it he written.
I could design a more light version and include it as an alternative version.
Is the access you suggested me faster than the access throug the structure of the object?
Do you have any other suggestions for Kronos?
Thank you very much, I appreciated.
[Please log in to post a comment]