Space Invaders: 1K Challenge

Show off your games, demos and other (playable) creations.
Post Reply
User avatar
ivan
Party member
Posts: 1530
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Space Invaders: 1K Challenge

Post by ivan » Fri Dec 01, 2017 5:23 pm

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
Last edited by ivan on Fri Dec 01, 2017 5:36 pm, edited 6 times in total.

User avatar
ivan
Party member
Posts: 1530
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: Space Invaders: 1K Challenge

Post by ivan » Fri Dec 01, 2017 5:28 pm

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
Attachments
invaders.love
version 1
(701 Bytes) Downloaded 110 times

User avatar
sefan
Prole
Posts: 22
Joined: Fri Jul 31, 2015 7:03 am
Contact:

Re: Space Invaders: 1K Challenge

Post by sefan » Sat Dec 02, 2017 8:20 pm

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
Attachments
space invaders.love
(1.46 KiB) Downloaded 73 times

User avatar
ivan
Party member
Posts: 1530
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: Space Invaders: 1K Challenge

Post by ivan » Sat Dec 02, 2017 9:48 pm

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!

User avatar
sefan
Prole
Posts: 22
Joined: Fri Jul 31, 2015 7:03 am
Contact:

Re: Space Invaders: 1K Challenge

Post by sefan » Sun Dec 03, 2017 9:42 am

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

User avatar
easy82
Party member
Posts: 184
Joined: Thu Apr 18, 2013 10:46 pm
Location: Hungary

Re: Space Invaders: 1K Challenge

Post by easy82 » Thu Dec 21, 2017 2:44 pm

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.
Attachments
invaders-clone-1k.love
(745 Bytes) Downloaded 76 times
Last edited by easy82 on Thu Dec 21, 2017 7:23 pm, edited 1 time in total.

User avatar
ivan
Party member
Posts: 1530
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: Space Invaders: 1K Challenge

Post by ivan » 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!

User avatar
easy82
Party member
Posts: 184
Joined: Thu Apr 18, 2013 10:46 pm
Location: Hungary

Re: Space Invaders: 1K Challenge

Post by easy82 » Thu Dec 21, 2017 7:27 pm

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

Post Reply

Who is online

Users browsing this forum: No registered users and 7 guests