Controls:

  • Left/Right-Arrow: Turn Left/Right
  • Up/Down-Arrow: Accelerate Vertically
  • Z/X: Accelerate Forward/Backward

I made this because I wanted to make a 3D game in Pico-8 for the PICO-1K Jam 2025, though that proved to be rather difficult to do performantly and within 1KB. It's less of a game now and more a spaceship simulator. I started with cubes, but that proved hard to keep in budget, so I switched to pyramids. I did manage to fit in some diffuse shading though! :) I also got the code down to 1022 with the help of Shrinko8 and some further hand tuning!

The "30" in the top left is the current framerate, which it should never drop below.

Here's the code if you're curious: (And, yes, it is 2 lines! Those pesky newlines would take space!)

local o,d,f,l,n={},{{-1,-1,-1},{-1,1,-1},{1,1,-1},{-1,1,1}},{{1,3,2},{1,2,4},{2,3,4},{1,4,3}},{0,0,0},{5,13,7,15,9,1,11,3,6,14,4,12,10,2,8,0}function x(u)local o=0for l=1,#n do if n[l]/16>=u do o+=2^l end end return o end function e(l,o)local l={o[4]*l[1],o[4]*l[2],o[4]*l[3]}local l={l[1]*o[7]-l[3]*o[8],l[2],l[3]*o[7]+l[1]*o[8]}local o={o[1]+l[1],o[2]+l[2],o[3]+l[3]}return o end function r(o)return{o[1]*l[4]+o[3]*l[5],o[2],o[3]*l[4]-o[1]*l[5]}end function lo(o)return{o[1]/2,o[2]/2,(-128*o[3]-1)/(128+1/128),-o[3]}end function a(o)return{flr(o[1]/o[4]*128+128/2)+1/2,flr(o[2]/o[4]*128+128/2)+1/2,o[3]/o[4],1}end function i(o,n,l,f)local l=(f-o[l])/(n[l]-o[l])if l>=0and 1>=l do return{o[1]+l*(n[1]-o[1]),o[2]+l*(n[2]-o[2]),o[3]+l*(n[3]-o[3]),o[4]+l*(n[4]-o[4])}end end function g(o)local o={{o[2][1]-o[1][1],o[2][2]-o[1][2],o[2][3]-o[1][3]},{o[3][1]-o[1][1],o[3][2]-o[1][2],o[3][3]-o[1][3]}}return{o[1][2]*o[2][3]-o[1][3]*o[2][2],o[1][3]*o[2][1]-o[1][1]*o[2][3],o[1][1]*o[2][2]-o[1][2]*o[2][1]}end ::o:: flip()cls()if btn(4)do l[2]+=-1end if btn(5)do l[2]+=1end if btn(2)do l[1]+=-1end if btn(3)do l[1]+=1end if btn(0)do l[3]+=-1end if btn(1)do l[3]+=1end l[3]%=128l[4]=cos(l[3]/128)l[5]=-sin(l[3]/128)if rnd(1)-1/2>rnd(1/2)and#o<10do add(o,{rnd(128/2)-128/2/2,rnd(128/2)-128/2/2,-rnd(128/2)-128/2/2,rnd(2)+1,rnd(2)+1,rnd(2)+1})end local n={}for n=#o,1,-1do o[n][1]+=l[5]*l[2]/128o[n][2]+=-l[1]/128o[n][3]+=-l[4]*l[2]/128o[n][6]+=o[n][5]/128o[n][6]%=1o[n][7]=cos(o[n][6])o[n][8]=-sin(o[n][6])if 1/128>rnd(1/2)do deli(o,n)else for c=1,#f do local f={e(d[f[c][1]],o[n]),e(d[f[c][2]],o[n]),e(d[f[c][3]],o[n])}local l=g(f)local e,o=max(0,l[1]/sqrt(l[1]^2+l[2]^2+l[3]^2)),{r(f[1]),r(f[2]),r(f[3])}local l=g(o)if 0<l[1]*o[1][1]+l[2]*o[1][2]+l[3]*o[1][3]do local o,l={lo(o[1]),lo(o[2]),lo(o[3])},{}local n={a(o[1]),a(o[2]),a(o[3])}for n=1,#o do local f=o[1+(n-1)%#o]local f=i(f,o[n],3,0)if f do add(l,a(f))end if o[n][3]>0do add(l,a(o[n]))end end for o=2,#l-1do local n,f,d=l[1],l[o],l[o+1]local o,l=min(min(n[1],f[1]),d[1]),max(max(n[1],f[1]),d[1])for l=o,l do if l<0or l>128do else local o={}add(o,i(n,f,1,l))add(o,i(f,d,1,l))add(o,i(d,n,1,l))if#o>0do for l=1,#o do for n=l+1,#o do if o[l][2]>o[n][2]do o[l],o[n]=o[n],o[l]end end end fillp(x(e))line(o[1][1],o[1][2],o[#o][1],o[#o][2],2+ceil(c)+128/2/2/2)end end end end end end end end?stat(7),7
goto o


Comments

Log in with itch.io to leave a comment.

Nice getting the triangle draws within the byte limit, and keeping to 30 fps!