06 Drift
No gun, just momentum. Coast around a wraparound screen collecting sparks, but every spark you grab births another rock.
Controls A/D or arrows rotate, W/Up/Space thrust. Touch: hold to steer toward your finger and thrust
1000 / 1024 bytes · 24 to spare
The 1000 bytes that ship
for(_='t[Ze.j),q()zRz,~,16V=>{U=(Lh.K))J*S(J-`Text(_n[0][^&&key,Sz-.5=.99*(jtype,o,f,iL)=>"#ff(u[3let c.fill,"Rect(Kcos(i180320c.strokeKhypot(]|u[Ksin(0, ;for(tZ0],Z1]Style==*joffset/a.clientWidth,=onpointerlocalStoragjdrift1kt,e,l,n,r,s,y,d,p,k,T,h=Math,S=Krandom,u=[],m=+|| R(k=`e,(T=`l)<70~g(~n.push([k,T]J,x{e=16 l=9 o=f=i=r=s=y= n=[]=7;t--;)gz;^2]=^3]=0};xz,s=1,ondown=onupmovedownup=eUu[jCode]=<"u",dXpYt=jbuttons,/n$/.test()sy>30xz},setInterval(zUif(y++"#0b0b1066 32 q!s){i+=t?.15*Katan2(p-l,d-e)-i):.08*(968])-765]J;n=.09*88732]|t);oo+)*nqff+i)*nqeLe+o+)%32 lLl+f+)%}n.map((tLo?7:3JUL+Z2]+)%LZ1]+Z3]+)%18 o?4f6d":d23f-i-i,2*i,2*iq!s-e-l)<i+3(o?(s=1,y= =m=Kmax(m,rJ:(r++,~=k=T,g(J)}q9f3f",c.beginPathz of[ 2.5,-2.5,0])c.lineTo(e+8*+tql+8*i+tJ;z"#e9e7df",s_"DRIFT · TAP TO START"V 64)_r+" HI "+mV 20)}V)';G=/[-^-`J-LUV~zqjZ]/.exec(_);)with(_.split(G))_=join(shift());eval(_)Readable source
// DRIFT: coast, collect sparks, dodge rocks. Each spark births a rock.
let M = Math, R = M.random, K = [], H, X, Y, U, V, A, rocks, score, dead, t, tx, ty, p, q,
best = +localStorage.drift1k || 0;
// pick a point at least 70px from the ship
let far = () => M.hypot((p = R() * 320) - X, (q = R() * 180) - Y) < 70 && far();
// rocks[0] is the spark (still); the rest are drifting rocks
let rock = () => (far(), rocks.push([p, q, R() - .5, R() - .5]));
let start = () => {
X = 160; Y = 90; U = V = A = score = dead = t = 0;
rocks = [];
for (let i = 7; i--;) rock();
rocks[0][2] = rocks[0][3] = 0; // first one is the (still) spark
};
start(); dead = 1;
// one handler for keys and pointers
onkeydown = onkeyup = onpointermove = onpointerdown = onpointerup = e => {
K[e.keyCode] = e.type < 'keyu';
tx = e.offsetX * 320 / a.clientWidth; ty = e.offsetY * 320 / a.clientWidth;
H = e.buttons;
/n$/.test(e.type) && dead && t > 30 && start(); // keydown / pointerdown
};
setInterval(() => {
t++;
c.fillStyle = '#0b0b1066';
c.fillRect(0, 0, 320, 180);
if (!dead) {
if (H) A += M.sin(M.atan2(ty - Y, tx - X) - A) * .15;
else A += ((K[39] | K[68]) - (K[37] | K[65])) * .08;
// thrust + drag
let th = (K[38] | K[87] | K[32] | H) * .09;
U = (U + M.cos(A) * th) * .99;
V = (V + M.sin(A) * th) * .99;
X = (X + U + 320) % 320;
Y = (Y + V + 180) % 180;
}
// r = rock, i = index (0 is the spark), s = half-size. Not a map() default param: map passes the array 3rd
rocks.map((r, i, _, s = i ? 7 : 3) => {
r[0] = (r[0] + r[2] + 320) % 320;
r[1] = (r[1] + r[3] + 180) % 180;
c.fillStyle = i ? '#ff4f6d' : '#ffd23f';
c.fillRect(r[0] - s, r[1] - s, s * 2, s * 2);
if (!dead && M.hypot(r[0] - X, r[1] - Y) < s + 3)
if (i) {
dead = 1; t = 0;
localStorage.drift1k = best = M.max(best, score);
} else score++, far(), r[0] = p, r[1] = q, rock();
});
// ship: vector triangle
c.strokeStyle = '#ff9f3f';
c.beginPath();
for (let d of [0, 2.5, -2.5, 0]) c.lineTo(X + M.cos(A + d) * 8, Y + M.sin(A + d) * 8);
c.stroke();
c.fillStyle = '#e9e7df';
if (dead) c.fillText('DRIFT · TAP TO START', 160, 64);
c.fillText(score + ' HI ' + best, 160, 20);
}, 16);