PICO-8 allows 65536 characters, which on one hand is a tight limit for some projects. But, on the other hand, we've seen amazing things from Tweet jam in 140 characters or fewer.
That made me wonder...can a whole PICO-8 game be written in 1024 characters (1k)? There are some impressive JavaScript 1k demos. Let's see what we can do!
Rules:
- Entire program source code lists as 1024 characters or fewer inside PICO-8, including comments.
- Must be a playable game, not just an animation.
- No limits on music, sprites, or map, since they don't count toward PICO-8's character limit.
This is my PICO-1k jam entry. The entire source code is 1024 characters in PICO-8, including the comment at the top. Arrows to fly, button (z on keyboard) to fire.
--top*burn
a=48n=32k=64_={}camera(-k,-k)c=16x=0y=0t=0o=0g=0q,b,r,s,h=sqrt,btn,rnd,spr,sspr::a::l=t%8/4map(0,0,-k,-k,c,c)for j=3,k do
z=j/4h(q(q(z))*c-l,1,k+k,1,-j*n,j,k*4*z,1)end
l=l<1o=max(o-1,0)f=b(4)and o<n
if f then m(r(3))o+=2
if(o>n)o=98
end
i=l and o>n and s(124,-k,-40,4,1)or h(0,56,min(o,n),6,-k,-a),l and t>650or h(a,n,n-t/n,8,n,-a)
i=b(1)p=24m=sfx
if(i and x<c)x+=2 p=c
if(b(0)and-k<x)x-=2 p=c
if(b(2)and y<n)y+=1 p=k
if(b(3)and-n<y)y-=1 p=74
s(86,x+8,a,4,2)
for e in all(_)do e.x+=e.d e.z+=.1 j=e.d<0w=88z=4/e.z
if(e.l==0or e.z>k)del(_,e)
if(e.l)e.l-=1 j=r(2)>1goto e
h(56,k,c,c,e.x*z+24*z,a*z,c*z,c*z,j)w=k
if(f and max(abs(u/z-e.x-21),abs(v/z-e.y-8))<8)e.l=8m(3)g+=.75
::e::h(0,w,56,24,e.x*z,e.y*z,56*z,24*z,j)end
if(r(98)<1)d=sgn(r(2)-1)add(_,{x=r(n)-d*k-c,d=d,y=r(k)-a,z=1})
z=.7u=x*z+13v=y*z-8s(2,u,v)
if(f and l)s(c,u*.9,v*z)s(17,u,y*z-5)z+=.1 s(38,x*z+10,y*z-2,2,1)z+=.1 s(46,x*z+14,y*z+1,2,1)
s(p,x,y,6,3,i)s(240,-30,-41,g,1)flip()t+=1
if(t<999)goto a
::g::s(137+t%2*k,t%192-140,-n,7,1)flip()t+=1
goto g
|
Here's the source with comments to make it more understandable:
-- topburn
-- @casualeffects
-- a pico-8 game in 1024
-- characters (this is the
-- version with comments, which
-- is larger!)
--
-- common constants:
-- k = 64
-- a = 48
-- n = 32
-- c = 16
--
-- common functions:
-- q = sqrt
-- b = btn
-- s = spr
-- h = sspr
-- r = rnd
-- m = sfx
--
-- t = timer (frame count)/fuel
-- x,y = plane position
-- z = scale factor
-- _ = enemy array
-- p = plane sprite index
-- i = right button (during plane code)
-- j = flip sprite left-right
-- o = gun overheat status
-- f = true if firing
-- u,v = reticle coords
-- e = enemy
-- w = enemy sprite y
-- l = modulo counter (for background) and blink (for hud and bullets)
-- g = kills
-- d = temp var
--
-- enemies:
-- x,y,z = coords
-- l = life
--
-- use 1<0 for "false" and 1>0 for "true"
-- use "p=a and b or c" for "if a then b else c"
-- any letter > f can be run against a number to start a new statement
-- += and single-line "if" require a newline
--background
a=48n=32k=64_={}camera(-k,-k)c=16x=0y=0t=0o=0g=0q,b,r,s,h=sqrt,btn,rnd,spr,sspr::a::l=t%8/4map(0,0,-k,-k,c,c)for j=3,k do
z=j/4h(q(q(z))*c-l,1,k+k,1,-j*n,j,k*4*z,1)end
-- hud
l=l<1o=max(o-1,0)f=b(4)and o<n
if f then m(r(3))o+=2
if(o>n)o=98
end
-- blinking gauges
p=l and o>n and s(124,-k,-40,4,1)or h(0,56,min(o,n),6,-k,-a),l and t>650or h(a,n,n-t/n,8,n,-a)
--player shadow + flying code
i=b(1)p=24m=sfx
if(i and x<c)x+=2 p=c
if(b(0)and-k<x)x-=2 p=c
if(b(2)and y<n)y+=1 p=k
if(b(3)and-n<y)y-=1 p=74
-- plane shadow
s(86,x+8,a,4,2)
--enemies
for e in all(_)do e.x+=e.d e.z+=.1 j=e.d<0w=88z=4/e.z
if(e.l==0or e.z>k)del(_,e)
if(e.l)e.l-=1 j=r(2)>1goto e
-- explosion
h(56,k,c,c,e.x*z+24*z,a*z,c*z,c*z,j)w=k
if(f and max(abs(u/z-e.x-21),abs(v/z-e.y-8))<8)e.l=8m(3)g+=.75
::e::h(0,w,56,24,e.x*z,e.y*z,56*z,24*z,j)end
-- new enemy
if(r(98)<1)d=sgn(r(2)-1)add(_,{x=r(n)-d*k-c,d=d,y=r(k)-a,z=1})
-- player reticle + bullets
z=.7u=x*z+13v=y*z-8s(2,u,v)
if(f and l)s(c,u*.9,v*z)s(17,u,y*z-5)z+=.1 s(38,x*z+10,y*z-2,2,1)z+=.1 s(46,x*z+14,y*z+1,2,1)
-- player plane + kills
s(p,x,y,6,3,i)s(240,-30,-41,g,1)flip()t+=1
if(t<999)goto a
-- game over
::g::s(137+t%2*k,t%192-140,-n,7,1)flip()t+=1
goto g
|
As you can see, I took advantage of some funny aspects of the parser. Letters that unambiguously are not part of a hexadecimal number can be jammed right against a number to save the whitespace...except for += and similar operators, which oddly require a space at the end. Single-line IF statements require a newline at the end of course, but many other statements do not.
In a few places I used the fact that AND and OR operators can work with any value in PICO-8 to trigger sprite drawing only in certain circumstances.
The sprite sheet is specifically laid out to minimize the length of numbers needed and allow some funny math formulas to work. Unfortunately, I couldn't save enough characters to afford to play background music.
[Please log in to post a comment]



