Skip to content
Branch: master
Find file History

Latest commit

Fetching latest commit…
Cannot retrieve the latest commit at this time.


Type Name Latest commit message Commit time
Failed to load latest commit information.

Fast PICO-8 particle system by Morgan McGuire @CasualEffects. Free for reuse in any context, but please retain my name in the code.

  • Direct memory rendering
  • Performance optimized for clamping via bitwise operations
  • Gravity
  • Maximum particle lifetimes
  • O(1) insertion and removal

Ignores palette settings and camera offset for speed. Adjust your particle positions directly.

PICO-8 assigns a virtual cycle count to each operation. My code is optimized to minimize PICO-8 cycles in the emulator, regardless of what the load is on the actual machine executing the code.

There are two clever tricks going on here. The first is that:

band(bor(particle.x, particle.y), 0xff80) != 0

is equivalent to the much slower:

particle.x < 0 or particle.y < 0 or particle.x > 127 or particle.y > 127

Because if the sign bit or any bit higher than the 0x7f needed for expressing 127 is set in either number, then the coordinates are out of bounds.

The second trick is that I'm directly writing to PICO-8 video memory. Since the pixels are 4-bit ("one nibble"), I have to do some masking to ensure that the code writes to the correct nibble. I haven't found a way to avoid that branch without incuring more operations.

Because PICO-8 doesn't support Lua's table.setn, I manually manage the array length. This gives O(1) insertion and removal. The particles are reordered during simulation. It is possible to still achieve O(1) without reordering, but the constant overhead is higher, then.

The waterfall demo is written so that the top portion is the reusable particle system and the bottom portion is the demo.

You can’t perform that action at this time.