Something went wrong. Try again.
an npmx inspired game for PICO-8 npicomx.vinnymac.dev
games pico-8 adventure npmx
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108-- packages: crates, pile, shouts, grab / deliver
function slot_xy(s) local p=pilepos[s] return p[1],p[2]-pdrop -- pdrop tweens the crates into the pileend
function spawn_one(s,good) local dv=(not good) and rnd(1)<devil_pct add(pkgs,{name=dv and rnd(badnames) or rnd(goodnames), devil=dv,st=0,slot=s,x=0,y=0,rat=0,vx=0,vy=0})end
function fill_cage() for s=1,#pilepos do spawn_one(s,s==1) endend
function free_slot() local u={} for p in all(pkgs) do if p.st==0 then u[p.slot]=true end end for s=1,#pilepos do if not u[s] then return s end endend
function lay_pile() for p in all(pkgs) do if p.st==0 then p.x,p.y=slot_xy(p.slot) end end end
function add_name(nm,x,y,burn) add(names,{name=nm,x=x,y=y,vy=burn and -0.7 or -0.4, t=0,life=burn and 44 or 38,c=burn and 9 or 10})end
function pick_msg(list) local on={} for n in all(shouts) do on[n.s]=true end local free={} for m in all(list) do if not on[m] then add(free,m) end end return rnd(free)end
function emit_shout(p) local s=pick_msg(shoutmsg) -- pop from pkg into own lane so simultaneous shouts don't overlap if s then add(shouts,{s=s,x=p.x-2+rnd(6),y=p.y-10-#shouts*8, vx=(rnd(1)-0.5)*0.4,vy=-0.1-rnd(0.06),t=0,life=64}) endend
function emit_evil(p) local s=pick_msg(evilmsg) if s then add(shouts,{s=s,x=p.x,y=p.y-6, vx=(rnd(1)-0.5)*0.4,vy=-0.2,t=0,life=50,evil=true}) endend
-- good pkg at balloon: save it, start phase 2. demons rattle out before reaching here.function deliver(p) saved+=1 add_name(p.name,p.x,p.y-8,false) sfx(2) poof(p.x,p.y-4) frz=3 shake=3 phase=2 bird.on=false bf.carry=nil del(pkgs,p)end
function do_grab_deliver() if bf.carry then if ov(bf.x,bf.y,balx,baly,22,30) then deliver(bf.carry) end -- AT the balloon, not just anywhere right of it (else you "deliver" in L2's out-of-bounds room) elseif phase==1 and bf.x<74 and bf.y>54 then -- fly over the pile + grab a RANDOM pkg local avail={} for p in all(pkgs) do if p.st==0 then add(avail,p) end end local best=rnd(avail) if best then best.st=1 bf.carry=best if best.devil then best.rat=45+devil_grace best.rat_delay=12 end if has_bird and birdt<0 then birdt=0 end -- this level's first pickup wakes the bird; thereafter it auto-respawns until you leave the level frz=2 shake=2 sfx(1) end endend
function do_drop() local p=bf.carry if not p then return end p.st=3 p.vx=bf.vx*0.5 p.vy=1 p.x=bf.x p.y=bf.y+6 bf.carry=nil sfx(4)end
function draw_pile() if lvl==4 then cloud(46,92)cloud(54,93) -- cloud platform under the crate pile else fillp(0x5a5a) rectfill(41,93,72,96,0x10) fillp() end -- dithered shadow under the pile -- shadow heap behind the 4 bright crates for depth; offset -pdrop tumbles in with them local d=pdrop pal(4,2)pal(15,4) -- body->dark, brace->brown = shadow spr(35,42,86-d)spr(35,64,86-d) -- side bases (floor): poke L/R edges spr(35,42,79-d)spr(35,64,79-d)spr(35,53,72-d) -- L/R upper corners + back peak pal() local sx=39 line(sx,80,sx,95,4) -- post for i=0,5 do line(sx-i,75+i,sx+i,75+i,10) end -- yellow warning triangle line(sx-5,80,sx+5,80,9) -- triangle base print("!",sx-1,77,2) -- bangend
function draw_pkg(p) local sx,sy=0,0 local shaking=p.rat>0 and not (p.rat_delay and p.rat_delay>0) if shaking then local mag=p.rat<12 and 3 or 2 sx=rnd(mag*2)-mag sy=flr(rnd(2))-1 if p.rat%6<3 then for i=1,15 do pal(i,7) end end end spr(35,p.x-4+sx,p.y-4+sy) if shaking then pal() endend