pico-8 cartridge // http://www.pico-8.com version 8 __lua__ --lands of yocta --by trasevol_dog function _init() cls() -- draw_text("l o a d i n g . . .",64,64) draw_text("l o a d i n g . . .",64,64) flip() vhei=12 load_voxeldata() local midhei=flr(vhei/2) lorder={} for i=0,vhei-1 do local order={} for ll=0,i do if ll0 then local dt=t*0.05+0.6 posx=monox+42*cos(dt) posy=monoy+42*sin(dt) cama=dt+0.5 if titlescreen>0 and titlescreen<2 or titlescreen>=2.05 then local k=flr((2-titlescreen)*5) fade(k,drk,true) titlescreen-=0.05 if titlescreen>=2.5 and titlescreen<=2.55 then add_shake(8) sfx(18) end if titlescreen>=2 and titlescreen<=2.05 then add_shake(8) sfx(19) end if titlescreen<=0 then start_game() pal() end end if titlescreen>=2 and btnp(4) then titlescreen=2-0.05 add_shake(8) sfx(9) end return end if (endtrig>0 and endtrig<53) or (endtrig>=54 and endtrig<91) then endtrig+=0.1 end if endtrig>0 and btn(4) then endtrig+=1 if endtrig>=54 then local rpx,rpy=posx-cabinx,posy-cabiny mapp={} mapp=make_world() posx,posy=cabinx+rpx,cabiny+rpy monok=5 drawdist=40 --remove cube frome table for y=2,5 do local lin=_vox[y] for x=2,5 do local clm=lin[x][75] for z=5,8 do clm[z]=nil end end end _vox[2][3][75][5]=6 _vox[2][3][75][6]=10 end end update_player() update_monolith() foreach(animate,update_animate) -- foreach(actors,update_actor) if btnp(4,1) then add_shake(4) debug=not debug end end function _draw() if whitescreen then cls(7) whitescreen=false return end if endtrig>0 then local k=flr(endtrig) if endtrig<5 then fade(k,light,true) elseif endtrig<54 then pal() cls(7) camera() local strs={ "hi!", "thank you for playing!", "this was pretty fun to make", "i wrote about it", "at trasevol.dog/voxelz", "thank you again!", "~ trasevol_dog ~", "press Ž to continue" } local kk=flr((endtrig-5)/6+1) local k=min(#strs,kk) local y=64-(#strs-0.5)*7 for i=1,k do if i==kk then local kk=max(4-(endtrig-5)%6*2,0) fade(kk,light) end draw_text(strs[i],64,y) y+=14 end return elseif endtrig<59 then local k=4-flr(endtrig-53) fade(k,light,true) else pal() endtrig=0 end end do local y=hei/vhei*128+shky cls() rectfill(0,y,127,y,1) end draw_sky() camera(shkx,shky-4) draw_voxel(drawdist,hei) -- if titlescreen>0 and titlescreen<=4.5 then -- for y=32,79 do -- fade(flr(-y/8-t/0.1)%5,light) -- for x=48,79 do -- pset(x,y,pget(x,y)) -- end -- end -- -- for c=0,15 do -- pal(c,c) -- end -- end if titlescreen>0 and titlescreen<=3 then if titlescreen>=2.05 then local dt=titlescreen-2 local y=-max(dt-0.5,0)*128 fade(flr(dt*7),drk) pal(1,0) pal(13,1) spr(128,0,y,16,8) for i=0,15 do pal(i,i) end else pal(1,0) --pal(13,1) spr(128,0,0,16,8) pal(1,1) --pal(13,13) draw_text("trasevol_dog presents",64,1,1,0,true) draw_text("z/Ž x/—: ",70,70,2,0,true) draw_text("”‹‘ƒ: ",70,79,2,0,true) draw_text("”+”: ",70,88,2,0,true) draw_text("rotate",70,70,0,2,true) draw_text("walk",70,79,0,2,true) draw_text("run",70,88,0,2,true) if t%0.4<0.3 then draw_text("press z/Ž to start",64,112,1,0,true) end end end camera() if titlescreen<=0 then draw_compass(64,5,96) end if stat(1)<0.91 then drawdist+=1 elseif stat(1)>0.95 then drawdist-=3 elseif stat(1)>0.95 then drawdist-=1 end if debug or btn(4,1) then rectfill(0,0,48,24,0) local y=1 print("cpu:"..flr(stat(1)*100).."%",1,y,7) y+=8 print("draw dist:"..drawdist,1,y,7) y+=8 print("memory:"..flr(stat(0)/1024*100).."%",1,y,7) y+=8 end end function update_player() camacc=0.2 if endtrig==0 then if btn(4) then camva+=camacc end if btn(5) then camva-=camacc end end cama+=camva*0.01 camva*=0.8 if abs(camva)<0.05 then camva=0 end local acc=0.04 local facc if lfrelease<0.1 then facc=acc*2.5 else facc=acc end if endtrig==0 then if btn(0) then hspd+=acc*1.5 end if btn(1) then hspd-=acc*1.5 end if btn(2) then vspd+=facc end if btn(3) then vspd-=acc end end if lfpress and not btn(2) then lfrelease=0.05 elseif btn(2) and lfrelease<0.1 then lfrelease=0.08 end lfpress=btn(2) lfrelease+=0.01 nposx=posx+vspd*cos(cama)+hspd*cos(cama+0.25) nposy=posy+vspd*sin(cama)+hspd*sin(cama+0.25) --local ti=mapp[flrs[flr(nposx)%mapwt]][flrs[flr(nposy)%mapwt]] local ti=mapp[flr(nposy/8)%mapw][flr(nposx/8)%mapw] if walls[ti] then local tix=mapp[flr(posy/8)%mapw][flr(nposx/8)%mapw] if walls[tix] then nposx=posx end local tiy=mapp[flr(nposy/8)%mapw][flr(posx/8)%mapw] if walls[tiy] then nposy=posy end end posx=nposx posy=nposy vspd*=0.9 hspd*=0.7 if monok==4 and endtrig==0 and ti==74 then endtrig+=0.1 end if abs(vspd)>0.05 or abs(hspd)>0.05 then bob=lerp(bob,2*cos(t*6),0.2) if bob<=-1.005 then if abs(vspd)>0.5 then sfx(14+flr(rnd(4)),3) else sfx(10+flr(rnd(4)),3) end end if bob>=1.005 and abs(vspd)>0.5 then sfx(14+flr(rnd(4)),3) end else bob=lerp(bob,0,0.2) end end function update_monolith() if monok==4 then local lit=flr(monot/0.02) local plit=max(lit-monocolk,0) for y=2,5 do local lin=_vox[y] for x=0,7 do local clm=lin[x][76] for zz=plit,lit do local z=zz%12 local c=monocols[zz-plit+1] if clm[z] then clm[z]=c end end end end --put cube on table!! for y=2,5 do local lin=_vox[y] for x=2,5 do local clm=lin[x][75] local c=x+y+flr(monot/0.02) for z=5,8 do local c=(c+z)%cubecolk+1 clm[z]=cubecols[c] end end end monot+=0.01 return elseif monok>4 then return end local monod=sqrdist((posx-monox)*0.1,(posy-monoy)*0.1) -- abs(posx-monox)+abs(posy-monoy) if monod76 then local mx,my=flr(monox/8),flr(monoy/8) if (x-mx)%3<1 and (y-my)%3<1 then lin[x]=76 else lin[x]=0 end end end end animate={} for y=2,5 do local lin=_vox[y] for x=0,7 do local clm=lin[x][76] for z=0,11 do if clm[z] then clm[z]=5 end end end end monok+=1 end elseif monod64*8) or (posx>64*8 and posy<64*8) then if chance(0.2) and stat(16)==-1 then sfx(flr(rnd(3))+1,0) end end if posx>64*8 or posy<64*8 then if chance(0.2) and stat(17)==-1 then sfx(flr(rnd(5))+4,1) end end end function draw_compass(x,y,w) do local x=x-w/2 local y=y-3 rect(x-1,y-1,x+w+1,y+8,0) rect(x,y,x+w,y+6,7) rectfill(x,y+7,x+w,y+7,13) x+=1 y+=1 rectfill(x,y,x+w-2,y+4,0) end local letters={'e','n','w','s'} for i=0,7 do local a=angle_diff(cama,i/8) a*=-w*4 if abs(a)pb[2] then for y=pb[2],pa[2] do rxs[y]=round(lerp(pb[1],pa[1],(y-pb[2])/(pa[2]-pb[2]))) end elseif pa[2]=0.25 and cama%1<0.75 then if cama%1>=0.5 then ystarta,yenda,ypacea=may,max(miy,posy),-1 ystartb,yendb,ypaceb=miy,min(may,posy),1 else ystarta,yenda,ypacea=miy,min(may,posy),1 ystartb,yendb,ypaceb=may,max(miy,posy),-1 end local xstart,xend,xpace -- if cama%1>0.5 then if cama%1<0.25 or cama%1>=0.75 then xstart,xend,xpace=2,1,-1 else xstart,xend,xpace=1,2,1 end pal(5,0) local hvhei=vhei*0.5 for yy=ystarta,yenda,ypacea do local ty=yy%8 local lin=_vox[ty] local linh=_voxh[ty] local fy=mapp[flrs[yy%mapwt]] local cy=yy-posy local cyocy=cy*ocy local cyosy=cy*osy local xorder={lxs[yy],rxs[yy]} for xx=xorder[xstart],xorder[xend],xpace do local cx=xx-posx local d=(cx*osx+cyosy) if d<=-3 then local ti=fy[flrs[xx%mapwt]] local tx=xx%8 local clm=lin[tx][ti] local mh=linh[tx][ti] local x=3.99*(cx*ocx+cyocy) local sca=-(1/d*.7)*48 local w=2.5*sca x=x*sca+64 local order=lorder[mh] local drawfoo=_drawfoo[ti] for ll=0,mh do local l=order[ll] local c=clm[l] if c then local y=(-4*(l-hvhei))*sca+8*hei+bob+4 --if d<-drawdist+6 then -- _drawfoo[ti](x,y,w,drk[c]) -- --else drawfoo(x,y,w,c) --end end end end end end for yy=ystartb,yendb,ypaceb do local ty=yy%8 local lin=_vox[ty] local linh=_voxh[ty] local fy=mapp[flrs[yy%mapwt]] local cy=yy-posy local cyocy=cy*ocy local cyosy=cy*osy local xorder={lxs[yy],rxs[yy]} for xx=xorder[xstart],xorder[xend],xpace do local cx=xx-posx local d=(cx*osx+cyosy) if d<=-3 then local ti=fy[flrs[xx%mapwt]] local tx=xx%8 local clm=lin[tx][ti] local mh=linh[tx][ti] local x=3.99*(cx*ocx+cyocy) local sca=-(1/d*.7)*48 local w=2.5*sca x=x*sca+64 local order=lorder[mh] local drawfoo=_drawfoo[ti] for ll=0,mh do local l=order[ll] local c=clm[l] if c then local y=(-4*(l-hvhei))*sca+8*hei+bob+4 --if d<-drawdist+6 then -- _drawfoo[ti](x,y,w,drk[c]) --else drawfoo(x,y,w,c) --end end end end end end end function square(x,y,hw,c) rectfill(x-hw,y-hw,x+hw,y+hw,c) end function circle(x,y,r,c) circfill(x,y,r+1,c) end function draw_sky() for s in all(stars) do local x=angle_diff(cama,s.x) if abs(x)<0.13 then x=64-x*8*127 spr(s.s,x-4,s.y-4) end end local ma=angle_diff(cama,moonx) if abs(ma)<0.13 then ma=64-ma*8*127 pal(1,0) spr(10,ma-8,moony-8,2,2) pal(1,1) end end function draw_text(str,x,y,al,c,extra) local c=c or 0 local al=al or 1 if al==1 then x-=#str*2 elseif al==2 then x-=#str*4 end y-=3 if extra then print(str,x,y-2,0) print(str,x-1,y-1,0) print(str,x+1,y-1,0) print(str,x-2,y,0) print(str,x+2,y,0) print(str,x-2,y+1,0) print(str,x+2,y+1,0) print(str,x-1,y+2,0) print(str,x+1,y+2,0) print(str,x,y+3,0) end print(str,x-1,y+1,13) print(str,x+1,y+1,13) print(str,x,y+2,13) print(str,x-1,y,7) print(str,x+1,y,7) print(str,x,y-1,7) print(str,x,y+1,7) print(str,x,y,c) end function fade(k,refplt,scrn) local scrn=scrn and 1 or 0 for c=0,15 do local cc=c for i=1,k do cc=refplt[cc] end pal(c,cc,scrn) end end function create_actor(x,y) local e={ x=x, y=y, z=0, t=0 } add(actors,e) end function create_animate(tix,tiy,tib) local ti={ tix=tix, tiy=tiy, b=tib, t=rnd(1) } add(animate,ti) end function start_game() cama=0.125 camva=0 posx=96.5*8 posy=96.5*8 vspd=0 hspd=0 bob=0 t=0 drawdist=4 end function make_world() local map={} for y=0,mapw-1 do map[y]={} end for y=0,63 do --garden for x=64,127 do local ti if chance(3) then ti=77+rnd(2) elseif chance(6) then ti=16+rnd(4) elseif chance(15) then ti=5+rnd(11) elseif chance(75) then ti=rnd(5) else ti=0 end map[y][x]=flr(ti) end end for y=64,127 do --stony for x=0,63 do local ti if chance(10) then ti=92+rnd(12) elseif chance(3) then ti=84+rnd(4) elseif chance(3) then ti=16+rnd(8) elseif chance(2) then ti=5+rnd(11) elseif chance(10) then ti=rnd(5) elseif chance(30) then ti=88+rnd(4) else ti=0 end map[y][x]=flr(ti) end end for y=64,127 do --swamps for x=64,127 do local ti if chance(15) then ti=104+rnd(8) elseif chance(25) then ti=80+rnd(4) elseif chance(20) then ti=16+rnd(8) elseif chance(75) then ti=1+rnd(5) else ti=0 end map[y][x]=flr(ti) end end for y=0,63 do --forest for x=0,63 do local ti if (x+y)%2==0 and chance(50) or chance(10) then ti=77+rnd(3) elseif chance(10) then ti=5+rnd(11) elseif chance(2) then ti=80+rnd(4) elseif chance(1) then ti=104+rnd(8) elseif chance(75) then ti=1+rnd(5) else ti=0 end map[y][x]=flr(ti) end end --cabin repeat cabinx,cabiny=flr(rnd(3))+10.5,flr(rnd(3))+2.5 until (cabinx~=11.5 or cabiny~=3.5) for x=0,2 do for y=0,3 do map[cabiny*8+2+y][cabinx*8+2+x]=sget(x,16+y)+64 end end map[cabiny*8+6][cabinx*8+3]=0 --water local wp={{3,3},{3,11},{11,3},{11,11},{cabinx-0.5,cabiny-0.5}} for i=0,23 do local x,y,b repeat x,y=flr(rnd(15)),flr(rnd(15)) b=true for p in all(wp) do if x==p[1] and y==p[2] then b=false break end end until b add(wp,{x,y}) local k=flr(rnd(5))+1 local sx,sy=k*8,16 local dx,dy=x*8+4,y*8+4 for xx=0,7 do for yy=0,7 do local ti=sget(sx+xx,sy+yy) if ti>0 then ti=(ti-1)*4+24 map[dy+yy][dx+xx]=ti end end end end animate={} for y=0,mapwm do local lin=map[y] for x=0,mapwm do local ti=lin[x] if ti>=24 and ti<64 then create_animate(x,y,ti) end end end cabinx*=8 cabinx+=3.5 cabinx*=8 cabiny*=8 cabiny+=3.5 cabiny*=8 --walls map[0][0]=112 map[127][0]=113 map[127][127]=114 map[0][127]=115 for i=1,126 do map[i][0]=116 map[127][i]=117 map[i][127]=118 map[0][i]=119 end --monolith if not monok then monox,monoy,monok=96,32,1 map[monoy][monox]=76 map[monoy-1][monox]=0 map[monoy+1][monox]=0 map[monoy][monox-1]=0 map[monoy][monox+1]=0 monox=monox*8+4 monoy=monoy*8+4 end --spawn for x=95,97 do for y=95,97 do map[y][x]=flr(rnd(4)) end end map[96][96]=0 return map end function init_sky() stars={} for i=0,149 do local s={ x=rnd(512), y=8+rnd(32), s=rnd(4)<3 and flr(rnd(3)) or flr(rnd(7)) } add(stars,s) end moonx=0.14*512 moony=20 for i=0,1 do for s in all(stars) do for s2 in all(stars) do if s~=s2 then local d=sqrdist((s.x-s2.x)*.01,(s.y-s2.y)*.01) if ((s.s>3 or s2.s>3) and d<0.08) or d<0.03 then local a=atan2(s.x-s2.x,s.y-s2.y) s.x+=.5*cos(a) s.y+=.5*sin(a) s2.x-=.5*cos(a) s2.y-=.5*sin(a) end end end local d=sqrdist((s.x-moonx)*.01,(s.y-moony)*.01) if d<0.12 then local a=atan2(s.x-moonx,s.y-moony) s.x+=4*cos(a) s.y+=4*sin(a) end end end for s in all(stars) do s.x=flr(s.x%512)/512 s.y=flr(s.y) end moonx=0.14 end function gif_loop() drawdist=48 posx=31.5*8+24*cos(t*0.3) posy=31.5*8+24*sin(t*0.3) cama=t*0.3+0.5 _update() _draw() flip() extcmd("rec") for i=0,332 do posx=31.5*8+24*cos(t*0.3) posy=31.5*8+24*sin(t*0.3) cama=t*0.3+0.5 _update() _draw() flip() end extcmd("video") end function load_voxeldata() local newwalls={} for ti in all(walls) do newwalls[ti]=true end walls=newwalls decompress_spsh(voxset1) _vox,_voxh=load_voxtiles(4,64,0) decompress_spsh(voxset2) _vox,_voxh=load_voxtiles(12,16,64,_vox,_voxh) decompress_spsh(voxset3) _vox,_voxh=load_voxtiles(8,32,80,_vox,_voxh) decompress_spsh(voxset4) _vox,_voxh=load_voxtiles(12,8,112,_vox,_voxh) voxset1=nil voxset2=nil voxset3=nil voxset4=nil -- decompress_spsh(enemdata) -- --_actorvox,_actorvoxh=load_voxtiles(8,8,8,16) -- _actorvox,_actorvoxh=load_voxtiles(8,16,0) -- actordata=nil _drawfoo={} for ti in all(circles) do _drawfoo[ti]=circle end for i=0,#_vox[0][0] do if not _drawfoo[i] then _drawfoo[i]=square end end circles=nil reload(0x0,0x0,0x2000) end function load_voxtiles(hei,num,start,vox,voxh) local vox=vox or {} local voxh=voxh or {} local pdy,pdx if hei<=4 then pdy=0.25 pdx=4 elseif hei<=8 then pdy=0.5 pdx=8 else pdy=1 pdx=0 end for y=0,7 do local lin=vox[y] or {} local linh=voxh[y] or {} for x=0,7 do local clm=lin[x] or {} local clmh=linh[x] or {} for p=0,num-1 do local poss=clm[start+p] or {} local py=flr(p*pdy)*8 local px=flr(p*pdx)%16*8 local mh=-1 for z=0,hei-1 do local c=sget(px+z*8+x,py+y) if c>0 then poss[z]=c mh=z end end clm[start+p]=poss clmh[start+p]=mh end lin[x]=clm linh[x]=clmh end vox[y]=lin voxh[y]=linh end return vox,voxh end function vget(x,y,z) return _vox[z][y][x] end function vset(x,y,z,c) _vox[z][y][x]=c end function angle_diff(a1,a2) local a=a2-a1 return (a+0.5)%1-0.5 end dec2hex={[0]='0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'} hex2dec={["0"]=0,["1"]=1,["2"]=2,["3"]=3,["4"]=4,["5"]=5,["6"]=6,["7"]=7,["8"]=8,["9"]=9,["a"]=10,["b"]=11,["c"]=12,["d"]=13,["e"]=14,["f"]=15} function compress_spsh() local str="" local l=-1 local c=sget(0,0) for y=0,127 do for x=0,127 do local cc=sget(x,y) if c~=cc or l==15 then str=str..dec2hex[c]..dec2hex[l] c=cc l=0 else l+=1 end end end str=str..dec2hex[c]..dec2hex[l] return str end function decompress_spsh(str,toscreen) local hline if toscreen then hline=function(cur,l,c) local x1,y1=cur%128,flr(cur/128) cur+=l local x2,y2=cur%128,flr(cur/128) if y1==y2 then rectfill(x1,y1,x2,y1,c) else rectfill(x1,y1,127,y1,c) rectfill(0,y2,x2,y2,c) end end else hline=function(cur,l,c) for i=cur,cur+l-1 do sset(i%128,i/128,c) end end end local cur=0 local k=#str for lin=1,k,2 do local c=hex2dec[sub(str,lin,lin)] local l=hex2dec[sub(str,lin+1,lin+1)]+1 hline(cur,l,c) cur+=l end end function chance(a) return rnd(100)