1K Asteroids Challenge

Showcase your libraries, tools and other projects that help your fellow love users.
User avatar
ivan
Party member
Posts: 1911
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

1K Asteroids Challenge

Post by ivan »

Merry Christmas and welcome to the 1K Asteroids Challenge.
This time we're making a clone of the arcade classic Asteroids.
The more authentic and fun, the better.

Guidelines:
- the entire game must be contained in a single Lua file (1024 bytes or less)
- external assets (images, sounds, fonts) are not allowed
- asteroids, the player ship and bullets should wrap around the screen
- the gameplay must reset when you destroy all the asteroids or when you die
- bullets should have a limited range/lifetime
- the ship speed should not exceed that of the bullets

Extra credit:
- delta
- explosion effects
- score
- difficulty (asteroids should get bigger/break apart as you progress)
- different "models" for the asteroids
- sound effects
Last edited by ivan on Mon Dec 26, 2016 5:28 am, edited 6 times in total.
User avatar
ivan
Party member
Posts: 1911
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: 1K Asteroids Challenge

Post by ivan »

This was fun and it didn't take very long. It could be much more compact but I went a little overboard with the polygon generation. Also, I changed the controls a little bit, since in the original Asteroids the rotation of the ship is independent of its velocity. I think it's more fun this way.

Minified (1,004 bytes):

Code: Select all

L=love;D=L.keyboard.isDown;G=L.graphics;W,H=G.getDimensions()M=math;N=M.random;function L.load()S={8,0,-8,4,-8,-4,8,0,x=W/2,y=H/2,a=0,v=0}R={S}E=32;for d=1,E do b={x=N(W),y=N(H),a=N()*M.pi*2,v=N(64),e=1}for e=0,6 do c=N(8,16)a=e/6*M.pi*2;b[e*2+1]=M.cos(a)*c;b[e*2+2]=M.sin(a)*c end;b[15]=b[1]b[16]=b[2]R[#R+1]=b end end;function C(a,b)return b.e and(a.x-b.x)^2+(a.y-b.y)^2<128 end;function L.keypressed(f)if f=='space'then R[#R+1]={0,0,8,0,x=S.x,y=S.y,a=S.a,v=256,l=3}end end;function L.update(g)h,v=0,0;if D('a')then h=-2 elseif D('d')then h=2 elseif D('w')then v=128 elseif D('s')then v=-128 end;S.a=S.a+h*g;S.v=M.max(M.min(S.v+v*g,128),-128)for f,b in pairs(R)do b.x=(b.x+M.cos(b.a)*b.v*g)%W;b.y=(b.y+M.sin(b.a)*b.v*g)%H;if b.l then b.l=b.l-g;for e,i in pairs(R)do if C(b,i)then b.l=0;R[e]=nil;E=E-1 end end;if b.l<=0 then R[f]=nil end elseif C(S,b)then E=0 end end;if E==0 then L.load()end end;function L.draw()for j,b in pairs(R)do G.origin()G.translate(b.x,b.y)G.rotate(b.a)G.line(unpack(b))end end
Non-minified (for the curious):

Code: Select all

L=love
D=L.keyboard.isDown
G=L.graphics
W,H=G.getDimensions()
M=math
N=M.random

function L.load()
S={8,0,-8,4,-8,-4,8,0,x=W/2,y=H/2,a=0,v=0}
R={S}
E=32
for i=1,E do
b={x=N(W),y=N(H),a=N()*M.pi*2,v=N(64),e=1}
for j=0,6 do
c=N(8,16)
a=j/6*M.pi*2
b[j*2+1]=M.cos(a)*c
b[j*2+2]=M.sin(a)*c
end
b[15]=b[1]
b[16]=b[2]
R[#R+1]=b
end
end

function C(a,b)
return b.e and (a.x-b.x)^2+(a.y-b.y)^2<128
end

function L.keypressed(k)
if k=='space' then
R[#R+1]={0,0,8,0,x=S.x,y=S.y,a=S.a,v=256,l=3}
end
end

function L.update(dt)
h,v=0,0
if D('a')then
h=-2
elseif D('d')then
h=2
elseif D('w')then
v=128
elseif D('s')then
v=-128
end
S.a=S.a+h*dt
S.v=M.max(M.min(S.v+v*dt,128),-128)
for k,b in pairs(R)do
b.x=(b.x+M.cos(b.a)*b.v*dt)%W
b.y=(b.y+M.sin(b.a)*b.v*dt)%H
if b.l then
b.l=b.l-dt
for j,e in pairs(R)do
if C(b,e)then
b.l=0
R[j]=nil
E=E-1
end
end
if b.l<=0 then
R[k]=nil
end
elseif C(S,b)then
E=0
end
end
if E==0 then
L.load()
end
end

function L.draw()
for _,b in pairs(R)do
G.origin()
G.translate(b.x,b.y)
G.rotate(b.a)
G.line(unpack(b))
end
end
Controls: WASD and Space bar
Attachments
asteroids.1k.love
version 2
(724 Bytes) Downloaded 219 times
User avatar
Jasoco
Inner party member
Posts: 3725
Joined: Mon Jun 22, 2009 9:35 am
Location: Pennsylvania, USA
Contact:

Re: 1K Asteroids Challenge

Post by Jasoco »

I'm giving this a try right now. It's so challenging. I'm doing pretty well except that I'm not. I'm already near the limit and haven't even implemented bullets or broken up asteroids yet.

I don't even know how you'd do sound without an audio file in Löve but I'd be curious.

I'll post my result when I complete it.

Edit: Ha, about ~100 bytes passed the limit and it's still buggy and not complete.

Edit: Yeah, this is pretty difficult. My best was like ~1200 bytes so I decided to just add some more stuff to it and made it 1357 bytes.

It has colored entities (Added back when I gave up on the limit) and scoring and levels. (Also added) But it doesn't have rocks that break up. It also has a limit of 10 rocks and 10 bullets at once as all entities are loaded at once and just marked as dead and reused.

I also don't even use love.load or love.update and instead just grab Delta myself in love.draw.

Code: Select all

_=love G=_.graphics k=_.keyboard.isDown D=_.timer.getDelta M=math R,P=M.random,M.pi W,H,B=800,600,0 G.setLineWidth(2) q=pairs K=0 t=1 function _.draw() if not g then T=0 E={} for i=1,21 do E[i]={id=i,d=0,x=R()*W,y=R()*H,s=3,a=R()*(P*2),n=0,l=0,k=1,m=20} f=E[i]if i==1 then f.x,f.y,f.a,f.s,f.k=W/2,H/2,P,2,0 elseif i>1 and i<12 then f.k=-1 f.m=60 f.s=.2 end end g=1 end E[1].a=E[1].a+(k("a")and-P or k("d")and P or 0)*D() G.setColor(255,255,255) G.print("Score: "..K.."  Level: "..t, 0, 0) for i,e in q(E) do sp=i>11 and e.s*e.m or i>1 and 180 or(k("w") and 120 or 0) e.x=(e.x+M.cos(e.a)*D()*sp)%W e.y=(e.y+M.sin(e.a)*D()*sp)%H e.l=e.l-D() if e.l<=0 and e.k==-1 then e.d=1 end for j,u in q(E) do if i~=j then if M.sqrt((u.x-e.x)^2+(u.y-e.y)^2)<(e.s+u.s)*10 and u.d==0 then if e.k==0 and u.k==1 then g=nil K=0 T=0 t=1 elseif e.k==-1 and u.k==1 and e.d==0 then e.d,u.d=1,1 T=T+1 K=K+10*t if T>=10 then g=nil t=t+1 print("Level") end end end end end id=e.id b=(id>1 and id<12) if id ~= 1 then e.n=e.n+D() end G.setColor(id==1 and {255,255,255} or b and {255,0,0} or {0,255,0}) G.origin() G.translate(e.x,e.y) G.rotate(e.a) G.scale(1,id==1 and .8 or 1) if e.d==0 then G.circle("line",0,0,id==1 and 16 or b and 2 or e.s*10,id==1 and 3 or 7) end end end function _.keypressed(k) if k=="l" then B=(B+1)%10 e,p=E[B+2],E[1] e.x,e.y,e.a,e.l,e.d=p.x,p.y,p.a,5,0 end end
It was a fun challenge and took my entire night.
User avatar
0x72
Citizen
Posts: 55
Joined: Thu Jun 18, 2015 9:02 am

Re: 1K Asteroids Challenge

Post by 0x72 »

Merry Christmas!

The challenge was fun, thanks! :D

My entry:

994B

controls:
A: turn left
D: turn right
W: accelerate
L: fire

guidelines:
- all should be covered
extras:
- asteroids breaks into smaller pieces
- spaceship thruster "animation"
- points
cheating:
- the spaceship is circle (rather then triangle) to save a few bytes

Code: Select all

L=love
G=L.graphics
d=L.keyboard.isDown
r=L.math.random
C,S=math.cos,math.sin
X=table.remove
k=G.circle
l='line'
W,H=800,600
z=1
p=0
function K(q,s,x,y)for i=1,q do
A[#A+1]=s>5 and{x=x or r(W),y=y or r(H),u=r(-.8,.8),v=r(-.8,.8),s=s}or N
end end
function L.draw()if z then
I,O=W/2,H/2
U,Y=0,0
M,J=1,0
B={}A={}K(20,32)z=N
end
k(l,I,O,5)G[l](I,O,I+M*9,O+J*9)if d'w'then U,Y=U+M*.1,Y+J*.1
_=r()>.5 and k(l,I-M*6,O-J*6,3)end
I,O=I+U,O+Y
q=.1*(d'a'and-1 or d'd'and 1 or 0)M,J=C(q)*M-S(q)*J,S(q)*M+J*C(q)j=(U^2+Y^2)^.5
if j>5 then U,Y=U/j*5,Y/j*5 end
I,O=I%W,O%H
for i=#B,1,-1 do
b=B[i]b.l=b.l+1
b.x,b.y=(b.x+b.u)%W,(b.y+b.v)%H k(l,b.x,b.y,2)_=b.l>64 and X(B,i)end
if #A==0 then z=1 end
for i=#A,1,-1 do
a=A[i]s=a.s
a.x,a.y=(a.x+a.u)%W,(a.y+a.v)%H k(l,a.x,a.y,s,7)if(a.x-I)^2+(a.y-O)^2<s^2 then
z=1;p=0 end
for j=#B,1,-1 do
b=B[j]if(a.x-b.x)^2+(a.y-b.y)^2<s^2 then
X(B,j)X(A,i)K(2,s/2,a.x,a.y)p=p+1 end
end
end
G.print(p)end
function L.keypressed(k)B[#B+1]=k=='l'and{x=I,y=O,u=M*8,v=J*8,l=0}or N end
Attachments
asteroids_994B.love
(778 Bytes) Downloaded 182 times
User avatar
Jasoco
Inner party member
Posts: 3725
Joined: Mon Jun 22, 2009 9:35 am
Location: Pennsylvania, USA
Contact:

Re: 1K Asteroids Challenge

Post by Jasoco »

Suddenly I feel inadequate.
User avatar
Inny
Party member
Posts: 652
Joined: Fri Jan 30, 2009 3:41 am
Location: New York

Re: 1K Asteroids Challenge

Post by Inny »

I'm totally going to do this challenge. Give me a day or two.
User avatar
hatninja
Prole
Posts: 30
Joined: Sun Apr 07, 2013 1:31 am
Contact:

Re: 1K Asteroids Challenge

Post by hatninja »

Just made this, more could definitely be done but i'll do that when i don't feel tired.
It was really fun to make, though!

Guidelines: Ship speed isn't capped, but otherwise follows perfectly.
Extras: Uses delta time.

929 Bytes

Code: Select all

L=love;G=L.graphics;R=L.math.random;W,H=G.getDimensions()h="fill"M=math;i,j=M.sin,M.cos;k=L.keyboard.isDown;l=table.remove;m=os.time;o={}b={}function p()o={}b={}for t=1,30 do o[t]={R(0,W),R(0,H),j(R(0,9))*9,i(0,9)*9,9}end;a=W/2;c=H/2;d=0;e=0;f=0 end;function L.draw()q=2*L.timer.getDelta()s=#o>0 or p()d=k"left"and d-2*q or k"right"and d+2*q or d;g=k"up"and 9*q or k"down"and 9*-q or 0;e=e+j(d)*g;f=f+i(d)*g;a=(a+e*q)%W;c=(c+f*q)%H;b[#b+1]=k"space"and r and{a,c,j(d)*50,i(d)*50,m()+5}or n;r=not k"space"for t,u in pairs(o)do s=(a-u[1])*(a-u[1])+(c-u[2])*(c-u[2])<u[5]*u[5]and p()u[1]=(u[1]+u[3]*q)%W;u[2]=(u[2]+u[4]*q)%H;G.circle(h,u[1],u[2],u[5])end;for t,u in pairs(b)do u[1]=(u[1]+u[3]*q)%W;u[2]=(u[2]+u[4]*q)%H;G.circle(h,u[1],u[2],3)for v,w in pairs(o)do s=(u[1]-w[1])*(u[1]-w[1])+(u[2]-w[2])*(u[2]-w[2])<w[5]*w[5]and l(o,v)and l(b,t)end;s=m()>u[5]and l(b,t)end;G.origin()G.translate(a,c)G.rotate(d)G.line(-9,-9,9,0,-9,9)end
Source Code:

Code: Select all

local player_x,player_y,player_r,player_xspd,player_yspd,player_spd
local Fill,sin,cos,keyDown,tableRemove,osTime,reset,dt,oldSpace,Exec
--^ For easy minifying!
L=love
G=L.graphics
R=L.math.random
W,H=G.getDimensions()
Fill="fill"
M=math
sin,cos = M.sin,M.cos
keyDown=L.keyboard.isDown
tableRemove=table.remove
osTime=os.time

o={}
b={}
function reset()
	o={}b={}
	for i=1,30 do o[i]={R(0,W),R(0,H),cos(R(0,9))*9,sin(0,9)*9,9}end
	
	player_x=W/2
	player_y=H/2
	player_r=0
	player_xspd=0
	player_yspd=0
	
end

function L.draw()
	dt=2*L.timer.getDelta()
	
	Exec=#o>0 or reset()
	
	player_r=keyDown"left" and player_r-2*dt or keyDown"right" and player_r+2*dt or player_r
	player_spd=keyDown"up" and 9*dt or keyDown"down" and 9*-dt or 0
	player_xspd=player_xspd+cos(player_r)*player_spd
	player_yspd=player_yspd+sin(player_r)*player_spd
	player_x=(player_x+player_xspd*dt)%W
	player_y=(player_y+player_yspd*dt)%H
	
	b[#b+1]=keyDown"space"and oldSpace and {player_x,player_y,cos(player_r)*50,sin(player_r)*50,osTime()+5} or n
	oldSpace=not keyDown"space"
	
	for i,v in pairs(o) do
		Exec=(player_x-v[1])*(player_x-v[1])+(player_y-v[2])*(player_y-v[2]) < v[5]*v[5] and reset()
		
		v[1]=(v[1]+v[3]*dt)%W
		v[2]=(v[2]+v[4]*dt)%H
		G.circle(Fill,v[1],v[2],v[5])
	end
	
	for i,v in pairs(b) do
		v[1]=(v[1]+v[3]*dt)%W
		v[2]=(v[2]+v[4]*dt)%H
		G.circle(Fill,v[1],v[2],3)
		
		for k,a in pairs(o) do Exec=(v[1]-a[1])*(v[1]-a[1])+(v[2]-a[2])*(v[2]-a[2]) < a[5]*a[5] and tableRemove(o,k) and tableRemove(b,i) end
		Exec=osTime()>v[5] and tableRemove(b,i)
	end
	
	G.origin()
	G.translate(player_x,player_y)
	G.rotate(player_r)
	G.line(-9,-9,9,0,-9,9)
end
Attachments
Hat1kAsteroids.love
(2.83 KiB) Downloaded 157 times
User avatar
ivan
Party member
Posts: 1911
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: 1K Asteroids Challenge

Post by ivan »

Well done, some pretty good entries here.
So far, it looks like 0x72 did the best job in terms of gameplay.
And clever use of the "and" operator in order to avoid "if-then" statements, I'm going to steal that and use it in the next 1K challenge.
User avatar
Jasoco
Inner party member
Posts: 3725
Joined: Mon Jun 22, 2009 9:35 am
Location: Pennsylvania, USA
Contact:

Re: 1K Asteroids Challenge

Post by Jasoco »

Using "and" to avoid "if" whenever possible is my favorite thing to do now. If I'm creative enough I can combine so many into one line and avoid half a dozen ifs and locals. Well I guess we don't really bother with locals when doing these challenges. I also tried to avoid as many functions as possible since the word "function" itself takes a whole 8 bytes not including the function name and brackets.

I'll definitely wait for the next 1K challenge. The Terminal one doesn't really appeal to me though.
User avatar
Ikroth
Citizen
Posts: 79
Joined: Thu Jul 18, 2013 4:44 am

Re: 1K Asteroids Challenge

Post by Ikroth »

Here's my entry into this challenge. It took me way too long to figure how to do this, it was tough fitting everything into 1K. I coded more features, but I had to remove them to get it under 1K.

Size: 1,021 bytes

Guidelines: All good.
Extra:
- Delta time
- Asteroids have different models
- Asteroids break apart

Controls:
Rotate left: A
Rotate right: D
Thrust: W
Shoot: K

Minified:

Code: Select all

L=love;M=math;R=M.random;u=M.cos;U=M.sin;G=L.graphics;K=L.keyboard.isDown;W,H=800,600;Q=pairs;I=table.insert;F=99;T=9;C=0;A=function(b,c,d,e)for f=1,e do a={x=c or R(W),y=d or R(H),X=R(-F,F),Y=R(-F,F),r=b}for g=0,6 do q=R(4)*b/4;I(a,u(g)*q)I(a,U(g)*q)end;C=C+1;I(a,a[1])I(a,a[2])I(E,a)end end;L.keypressed=function(h)if h=="k"then I(E,{x=S.x,y=S.y,X=u(O)*300,Y=U(O)*300,r=3,l=2,2,2,0,0})end end;L.draw=function()D=L.timer.getDelta()if C==0 or n then E={}S={x=W/2,y=H/2,X=0,Y=0,r=6,a=0,-9,-7,9,0,-9,7}I(E,S)A(45,_,_,T)C=T;n=_ end;O=S.a;S.a=K"a"and O-3*D or(K"d"and O+3*D or O)if K"w"then S.X=S.X+u(O)*F*D;S.Y=S.Y+U(O)*F*D end;s=F*F/(S.X^2+S.Y^2)s=s>1 and 1 or s^.5;S.X=S.X*s;S.Y=S.Y*s;for f,i in Q(E)do i.x=(i.x+i.X*D)%W;i.y=(i.y+i.Y*D)%H;G.translate(i.x,i.y)G.rotate(i.a or 0)G.line(i)G.origin()for j,k in Q(E)do if(k.x-i.x)^2+(k.y-i.y)^2<(i.r+k.r)^2 and#k>9 then if i.l then A(20,k.x,k.y,k.r>20 and R(2,4)or 0)C=C-1;E[f]=_;E[j]=_ end;if i.a then n=1 end end end;if i.l then i.l=i.l-D;if i.l<0 then E[f]=_ end end end end
Source:

Code: Select all

L=love
M=math
R=M.random
u=M.cos
U=M.sin
G=L.graphics
K=L.keyboard.isDown
W,H=800,600
Q=pairs
I=table.insert

F = 99 -- max force
T = 9 -- max asteroids
C = 0 -- asteroid count

A=function(z,x,y,c)
    for i=1, c do
        a = {
            x=x or R(W),
            y=y or R(H),
            X=R(-F,F),
            Y=R(-F,F),
            r=z,
        }
        for t=0, 6 do
            q = R(4)*z/4
            I(a, u(t)*q)
            I(a, U(t)*q)
        end
        C = C + 1
        I(a, a[1])
        I(a, a[2])
        I(E, a)
    end
end

L.keypressed=function(k)
    if k=="k" then
        I(E, {
            x=S.x,
            y=S.y,
            X=u(O)*300,
            Y=U(O)*300,
            r=3,
            l=2,
            2,2,0,0
        })
    end
end

L.draw=function()
    D = L.timer.getDelta()
    -- reset
    if C==0 or n then
        E = {}
        S = {
            x=W/2,
            y=H/2,
            X=0,
            Y=0,
            r=6,
            a=0,
            -9,-7,9,0,-9,7
        }
        I(E, S)
        A(45,_,_,T)
        C = T
        n = _
    end
    O = S.a
    S.a = K"a" and O - 3*D or (K"d" and O + 3*D or O)
    if K"w" then
        S.X = S.X + u(O)*F*D
        S.Y = S.Y + U(O)*F*D
    end
    -- clamp speed
    s = F * F / (S.X^2 + S.Y^2)
    s = s > 1 and 1 or s^.5
    S.X = S.X * s
    S.Y = S.Y * s
    for i, e in Q(E) do
        e.x = (e.x + e.X*D)%W
        e.y = (e.y + e.Y*D)%H

        G.translate(e.x, e.y)
        G.rotate(e.a or 0)
        G.line(e)
        G.origin()
        
        for j, f in Q(E) do
            if (f.x - e.x)^2 + (f.y - e.y)^2 < (e.r + f.r)^2 and #f>9 then
                -- bullet vs asteroid
                if e.l then
                    A(20, f.x, f.y, f.r > 20 and R(2,4) or 0)
                    C = C - 1
                    E[i] = _
                    E[j] = _
                end
                -- Ship vs asteroid
                if e.a then
                    n=1
                end
            end
        end

        if e.l then
            e.l = e.l - D
            if e.l < 0 then
                E[i] = _
            end
        end
    end
end
Attachments
1k-asteroids.love
(798 Bytes) Downloaded 161 times
Post Reply

Who is online

Users browsing this forum: No registered users and 99 guests