Page 1 of 1

Space Invaders: 1K Challenge

Posted: Fri Dec 01, 2017 5:23 pm
by ivan
It's that time of year again!
The goal of this challenge is to create a Space Invaders clone, but here is the catch:
1.all of the code must be contained a single Lua file which should be under 1K (1024 ANSI characters)
2.no external assets or files allowed (can't use external images, sound files, fonts, etc)
3.the game should reset when you destroy all invaders or when they reach the bottom
4.the player should not be able to "break" the game (for example, by moving off-screen)

Extra credit:
difficulty should increase, animations, sound effects, hiscore or points, graphics that automatically scale to the window
The more authentic your clone, the better!

PS. Please include a .love file and instructions/controls.

Previous challenges:
Asteroids Breakout Terminal

Re: Space Invaders: 1K Challenge

Posted: Fri Dec 01, 2017 5:28 pm
by ivan
This is what I got so far

Code: Select all

L=love;G=L.graphics;O=L.keyboard.isDown;P=pairs;H=G.draw;Z={{11,8,"001401401000140G0001101110110G111110G011014010100011011000"},{17,8,"400011144400111444001114440011144GG10GGGGGGG11"}}for a,v in P(Z)do v[3]=v[3]:gsub("4","0000"):gsub("G","1111111"):gsub("1","ÿÿÿÿ"):gsub("0","ÿÿÿ ")Z[a]=G.newImage(L.image.newImageData(unpack(v)))end;function R()I={}for y=0,4 do for x=0,10 do I[y*11+x]={x=x*24,y=y*16}end end;N=55;x,y,u,v,w=120,280,120,280,0;U,W,V,X,Y=0,.1,.1,4,0 end;R()function L.update(b)W=W-b;if W<=0 then W=V;U=U+1;Y=0;if U%55==0 then X,Y=-X,6 end;Q=U%5*11;for a,c in P(I)do c.x=c.x+(a>=Q and a<=Q+10 and X or 0)c.y=c.y+Y;N=c.y>280 and 0 or N end end;D=0;if O("a")and x>0 then D=-96 elseif O("d")and x<283 then D=96 end;x=x+D*b;w=v<0 and 0 or w;if w>0 then for a,c in P(I)do if u>c.x and u<c.x+11 and v<c.y+8 and v>c.y then I[a]=nil;w=0;N=N-1;V=N/55*.1 end end end;if w==0 then u,v=x+9,y;w=O("w")and 256 or w end;v=v-w*b;if N<=0 then R()end end;function L.draw()for a,c in P(I)do H(Z[1],c.x,c.y)end;H(Z[2],x,y)G.line(u,v,u,v-5)end
It's 1,036 bytes after minification, so I'm over the limit by 12 characters!
Before copy/pasting: make sure your text editor is in ANSI mode, not UTF8!!!
Here is the original code:

Code: Select all

L=love
G=L.graphics
O=L.keyboard.isDown
P=pairs
H=G.draw
Z=
{
{11,8,"001401401000140G0001101110110G111110G011014010100011011000"},
{17,8,"400011144400111444001114440011144GG10GGGGGGG11"}
}
for i,v in P(Z) do
  v[3]=(((v[3]:gsub("4","0000")):gsub("G","1111111")):gsub("1","ÿÿÿÿ")):gsub("0","ÿÿÿ ")
  Z[i]=G.newImage(L.image.newImageData(unpack(v)))
end
function R()
  I={}
  for y=0,4 do
    for x=0,10 do
      I[y*11+x]={x=x*24,y=y*16}
    end
  end
  N=55
  x,y,u,v,w=120,280,120,280,0
  U,W,V,X,Y=0,.1,.1,4,0
end
R()
function L.update(_)
  W=W-_
  if W<=0 then
    W=V
    U=U+1
    Y=0
    if U%55 == 0 then
      X,Y = -X,6
    end
    Q = U%5*11
    for i,t in P(I) do
      t.x= t.x+((i >= Q and i <= Q+10) and X or 0)
      t.y= t.y+Y
      N=t.y > 280 and 0 or N
    end
  end
  D=0
  if O("a") and x > 0 then
    D=-96
  elseif O("d") and x < 283 then
    D=96
  end
  x=x+D*_
  w = v < 0 and 0 or w
  if w > 0 then
    for i,t in P(I) do
      if u > t.x and u < t.x+11 and v < t.y+8 and v > t.y then
        I[i] = nil
        w = 0
        N=N-1
        V=N/55*.1
      end
    end
  end
  if w == 0 then
    u,v = x + 9,y
    w = O("w") and 256 or w
  end
  v=v-w*_
  if N <= 0 then
    R()
  end
end
function L.draw()
  for i,t in P(I) do
    H(Z[1],t.x,t.y)
  end
  H(Z[2],x,y)
  G.line(u,v,u,v-5)
end
Controls
a,s: move
w: shoot

Re: Space Invaders: 1K Challenge

Posted: Sat Dec 02, 2017 8:20 pm
by sefan
My code so far:

Code: Select all

L=love G=L.graphics R=G.rectangle K=L.keyboard.isDown F="fill" N={5,5,5,5,5,5,5,5,5,5,5} x=0 B=0 V=0 D=1 I=0 O=0 P=0 function L.draw()W,H=G.getDimensions() S=W/30 y=H-S if K("a")and x-1>0 then x=x-1 end if K("d")and x+1<W-S then x=x+1 end if K("w") and D>0 then B=x V=y D=0 end if I<1 then O=O+.05 else O=O-.05 end if O>S then I=1 P=P+S end if O<-S then I=0 P=P+S end V=V-1 if D<1 then R(F,B,V,1,S)end if V<0 then D=1 end for i=1,11 do for j=1,4 do if B>2*i*S+O and B<2*i*S+O+S and V>2*j*S+P and V<2*j*S+P+S and N[i] > j and D<1 then D=1 N[i]=N[i]-1 end if N[i] > j then R(F,2*i*S+O,2*j*S+P,S,S) end end end R(F,x,y,S,S)end
Only boxes and lines right now. But a one line code with 623 characters.
A and D to move. W to shoot.

Original code (945 characters):

Code: Select all

L=love
G=L.graphics
R=G.rectangle
K=L.keyboard.isDown
F="fill"
N={5,5,5,5,5,5,5,5,5,5,5}
x=0

B=0
V=0
D=1

I=0
O=0
P=0

function L.draw()
    W,H=G.getDimensions()
    S=W/30
    y=H-S

    if K("a")and x-1>0 then
        x=x-1
    end
    if K("d")and x+1<W-S then
        x=x+1
    end
    if K("w") and D>0 then
        B=x
        V=y
        D=0
    end

    if I<1 then
        O=O+.05
    else
        O=O-.05
    end
    if O>S then 
        I=1
        P=P+S
    end
    if O<-S then
        I=0
        P=P+S
    end
    V=V-1

    if D<1 then
        R(F,B,V,1,S)
    end
    if V<0 then
        D=1
    end
    for i=1,11 do
        for j=1,4 do
            if B>2*i*S+O and B<2*i*S+O+S and V>2*j*S+P and V<2*j*S+P+S and N[i] > j and D<1 then
                D=1
                N[i]=N[i]-1
            end
            if N[i] > j then
                R(F,2*i*S+O,2*j*S+P,S,S)
            end
        end
    end
    R(F,x,y,S,S)
end

Re: Space Invaders: 1K Challenge

Posted: Sat Dec 02, 2017 9:48 pm
by ivan
Not bad, Sefan. it's a decent try.
Would be nice if the game reset when the invaders reach the bottom.
Plus, on my resolution I can move to the right and "seemingly evade" their attack altogether. :)
Note that you can probably shave off a few bytes from:
if I<1 then O=O+.05 else O=O-.05 end
by using something like:
O=O+.05*(I<1 and 1 or -1
Good job!

Re: Space Invaders: 1K Challenge

Posted: Sun Dec 03, 2017 9:42 am
by sefan
Thanks Ivan. I will improve the code :)
Looked through your code. I think you can win a lot of characters by skipping love.update and put it all in love.draw. The line "function L.update(_)" is 20 characters and you can reuse same for-loop for calculation and drawing.
One more thing you can do to save some characters if you have a IF with INT:

Code: Select all

--15 characters
if x==0 then
end
--or
if x<=0 then
end

--14 characters
if x<1 then
end

Re: Space Invaders: 1K Challenge

Posted: Thu Dec 21, 2017 2:44 pm
by easy82
Here goes mine!

1. Code length is 1K (1024 chars)
2. No external assets used
3. Restart when invaders win or fail
4. Players cannot break the game

Extras:
- Increasing difficulty (homage to the original)
- Different invader types in retro colors
- Pixelated graphics (~ scale to window)
- Invader animations and explosions
- Score counter and player lives
- Game over state

It was developed on Android, so you can move the ship by touching the left or the right side of the screen.
You can also move the ship by pressing A or D on the keyboard.
Shooting is automatic!

Minified:

Code: Select all

L=love;G=L.graphics;P=G.print;D=L.keyboard.isDown;M=L.mouse;H=math;o=0;n=3;a=255;b=10;function S()k=0;l=0;p=65;q="Rgg00"t={}for e=1,5 do t[e]={}for f=1,9 do t[e][f]=q:sub(e,e)end end;u=20;v=b;w=1;z=.1 end;function Y(c,x,y)P(c,x,y)P(c,x+3,y,0,-1,1)end;G.setDefaultFilter("nearest")G.setNewFont(8)S()function love.draw()G.push()G.scale(6)if n>0 then d=0;for e=5,1,-1 do G.setColor(e%5*a,e%2*a,e%3*a)for f=1,9 do x=u+f*b-5;y=v+e*b-5;c=t[e][f]if(x+y)%9==0 then r="Rg0"s="PqQ"g=r:find(c)h=s:find(c)c=g and s:sub(g,g)or(h and r:sub(h,h)or c)end;c=c=="*"and" "or c;if c~=" "then d=1;if k>x-3 and k<x+6 and l>y and l<y+9 then c="*"z=z-.002;o=o+b;k=p;l=90 end end;t[e][f]=c;Y(c,x,y)end;if d==1 and y>82 then n=n-1;S()end end;u=u+w;if u%40==0 then w=w*-1;v=v+3 end;if d==0 then o=o+b^3;S()end;if l<0 then k=p;l=90 end;P("'",k,l)l=l-3;p=M.isDown(1)and(M.getX()<400 and p-2 or p+2)or p;p=D("a")and p-2 or(D("d")and p+2 or p)p=H.max(5,H.min(125,p))end;Y("k",p,90)P(o,3,3)P(n,122,3)G.rectangle("line",1,1,131,98)G.pop()L.timer.sleep(z)end
Original:

Code: Select all

L=love
G=L.graphics
P=G.print
D=L.keyboard.isDown
M=L.mouse
H=math
o=0
n=3
a=255
b=10
  
function S()
  k=0
  l=0
  p=65
  q="Rgg00"
  t={}
  for j=1,5 do
    t[j]={}
    for i=1,9 do
      t[j][i]=q:sub(j,j)
    end
  end
  u=20
  v=b
  w=1
  z=.1
end

function Y(c,x,y)
  P(c,x,y)
  P(c,x+3,y,0,-1,1)
end

G.setDefaultFilter("nearest")
G.setNewFont(8)
S()

function love.draw()
  G.push()
  G.scale(6)
  
  if n>0 then
  
    d=0
    for j=5,1,-1 do
      G.setColor(j%5*a,j%2*a,j%3*a)
      
      for i=1,9 do
        x=u+i*b-5
        y=v+j*b-5
        c=t[j][i]
      
        if (x+y)%9==0 then
          r="Rg0"
          s="PqQ"
          g=r:find(c)
          h=s:find(c)
          c=g and s:sub(g,g) or (h and r:sub(h,h) or c)
        end
        
        c=c=="*" and " " or c
        
        if c~=" " then
          d=1
          if k>x-3 and k<x+6 and l>y and l<y+9 then
            c="*"
            z=z-.002
            o=o+b
            k=p
            l=90
          end
        end
      
        t[j][i]=c
        Y(c,x,y)
      end
      
      if d==1 and y>82 then
        n=n-1
        S()
      end
    end

    u=u+w
    if u%40==0 then
      w=w*-1
      v=v+3
    end
  
    if d==0 then
      o=o+b^3
      S()
    end
  
    if l<0 then
      k=p
      l=90
    end
    P("'",k,l)
    l=l-3
    
    p=M.isDown(1) and (M.getX()<400 and p-2 or p+2) or p
    p=D("a") and p-2 or (D("d") and p+2 or p)
    p=H.max(5,H.min(125,p))
  end
  
  Y("k",p,90)
  P(o,3,3)
  P(n,122,3)
  G.rectangle("line",1,1,131,98)

  G.pop()
  L.timer.sleep(z)
end
Edit: I've changed the framing rectangle size.

Re: Space Invaders: 1K Challenge

Posted: Thu Dec 21, 2017 5:59 pm
by ivan
Very clever approach to handling the graphics.
I had no idea that those glyphs were included in the default love2d font. :)
Well done, easy82!

Re: Space Invaders: 1K Challenge

Posted: Thu Dec 21, 2017 7:27 pm
by easy82
ivan wrote: Thu Dec 21, 2017 5:59 pm Very clever approach to handling the graphics.
I had no idea that those glyphs were included in the default love2d font. :)
Well done, easy82!
Thanks Ivan! :) I like these mini challenges, I had fun making it. Well the glyphs are ordinary characters like 'R', but they are drawn twice: a normal, and a mirrored one. :D