Indie developer of small games featuring small animals, small spaceships and big fun!
Newer...
Older...
18th April 2021
Link (seems better for mobile)
Some fairly simple particle fireworks just for fun.
Press X to switch the screen effect on/off. For more about that see here: fading stars
Every sixth of a second, 50-100 Particles are emitted at a random point on the screen with random angle/velocity determined by a tiny bit of trig. They're given colours in the top half of the PICO-8 palette (7+) and as the particles get old the colour changes according to the same mapping that the screen fade effect uses to a darker colour.
If they run out of life or become black then the particles are deleted.
There are two possible update functions for each particle - one with a wiggle :)
-- update: tidied code a bit, updated fade effect.
-- update 2: added a flash when the fireworks detonate. Other tweaks. Happy Fifth of November :)
function _update60() if btnp(❎) then g_fade=not g_fade end -- update particle positions and dispose of the dead for part=#g_parts,1,-1 do if not g_parts[part]:upd() then -- if the update returns false kill the firework deli(g_parts,part) end end if p%rint(5,18)==0 then -- add a new firework local col=rint(9,7) cls(g_scpal_map[g_scpal_map[col]]) add_parts({vel,wiggle},rint(50,50),rnd'128',rnd'128',rnd'5',rnd'5',3,5,120,col,rnd(15-col+1)) end p=(p+1)%192 end ------------------------------------------------------------------------------------------ --returns random integer (vs float from rnd) function rint(...) return rndr(...)&-1 end ------------------------------------------------------------------------------------------ -- generates a random direction function rnd_dir(m) local angle,d=rnd(),rnd(m) return d*sin(angle),d*cos(angle) end ------------------------------------------------------------------------------------------ -- rndr(t,r)==rnd(t)+r function rndr(t,r) return rnd(t)+(r and r or 0) end -- particle update function function vel(t) t.x+=t.vx*0.9 -- slow the particles a bit "friction" t.y+=t.vy*0.9 t.vy+=0.04 -- "gravity" t.l-=1 if t.l%20==19 and t.l<60 then -- older fireworks use darker colours t.c=g_scpal_map[t.c] end return t.y<128 and t.c>0 -- if firework is too old or black then signal to kill it end -- alternative particle update function function wiggle(t) t.x+=t.vx*0.7+sin(t.l/20)*0.3*t.vy -- slow the particles a bit "friction" t.y+=t.vy*0.7+cos(t.l/20)*0.3*t.vx t.vy+=0.04 -- "gravity" t.l-=1 if t.l%20==19 and t.l<60 then -- older fireworks use darker colours t.c=g_scpal_map[t.c] end return t.y<128 and t.c>0 -- if firework is too old or black then signal to kill it end ------------------------------------------------------------------------------------------ -- particles are single pixel fx only function add_parts( upd,n,-- update function x,y,-- position vx,-- x vel with random component vy,vr,-- y vel l,lr,-- lifetime c,cr) -- colour for i=1,n do local vrx,vry=rnd_dir(vr) add(g_parts,{x=x,y=y,vx=vrx,vy=vry,l=rint(l,lr),c=rint(cr,c),upd=rnd(upd)}) end end function _draw() if g_fade then scr_fade(p&3) else cls() end -- draw particles for p in all(g_parts) do if p.circ then circ(p.x,p.y,100-p.l*3,p.c) else pset(p.x,p.y,p.c) end end end ------------------------------------------------------------------------------------------ -- fades a quarter of the screen at a time -- scan line by scan line, left pixel then right pixel byte by byte -- which line, side of pair is dictated by p function scr_fade(p) -- local tables seem to be faster. -- change start line based on oddness value local d,m=0x6000+p%2*64,p&2==0 and g_8bit_map0 or g_8bit_map1 -- for half of the 128 lines on the screen for j=0,0x1f80,128 do -- for every 4bytes of this line for a=d+j,j+d+60,4 do -- map every pair of pixels to a mapped pair -- 4 bytes at a time -- shorter and quicker poke(a,m[@a],m[@(a+1)],m[@(a+2)],m[@(a+3)]) end end end pal(15,135,1) -- light yellow g_scpal_map={[0]=0,unpack(split'0,1,1,2,1,13,6,2,4,9,3,13,5,4,10')} --g_scpal_map g_8bit_map0,g_8bit_map1={},{} for i=0,255 do g_8bit_map0[i]=(i&0xf0)+g_scpal_map[i&0xf] g_8bit_map1[i]=g_scpal_map[i\16&0xf]*16+i%16 end g_parts={} p=0 g_fade=1