Fireworks
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 :)

Silent CG fireworks are pet friendly
-- 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
Comments
No comments here yet