Log In  

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:

  1. Entire program source code lists as 1024 characters or fewer inside PICO-8, including comments.
  2. Must be a playable game, not just an animation.
  3. No limits on music, sprites, or map, since they don't count toward PICO-8's character limit.
P#40831 2017-05-21 17:33 ( Edited 2017-05-21 21:47)

Cart #40832 | 2017-05-21 | Code ▽ | Embed ▽ | No License
17

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:

-- top’burn
-- @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.

P#40834 2017-05-21 17:47 ( Edited 2017-05-21 21:47)

[Please log in to post a comment]

Follow Lexaloffle:          
Generated 2024-04-19 10:10:09 | 0.040s | Q:13