A small JS clone of the infamous GORILLAS.BAS game (1991) that came distributed with QBasic. Move mouse for angle, hold button down for velocity.
_='$ñ=b.appendChild(document.createEment("span")t=ñ,tt.posiabsolutet.whiteSpacepret.top=a,ñrndceil(random()*a)K,f-e,-f_()rc.fillSty=_Sty#"+γ[a]oσc.fill()Q,fU[(f?"car":"fill")+"Rect"]-1,b-1,d+2)N=(SPQ(999,999L=2,j=1;È>L;)W=37)+37,H=max(120)+(6)<3?130:1510J[j++]={x:L,y:δ-H,w:Wr(3)Q(L,δ-H,W,He=L+3,L+=W+2;L-5>e;e+=10)i=H-3;i>=0;i-=15)r(5-!(4)-1)Q(e,δ-i,3,6);i=0;2>i;i++)L=J[(j-2)*i+(i?-2:2)+1~G[i]={x:L.x+L.w/2,y:L.y-30g(i,3)g,bvar ca~d=c.x=c.y;Q(d-15-3,28,31r(6o(d,6Q(d-7+83,9a=d;d+4>=a;a+=.1)K534,98K-65158,þ/4K-5+(134,54K+(274,þ/4);Q(d-3,5,1) move=(bdxX@Left-px||.1,dyY@Top-py,z=round(atan(dy/dx)/σ*(P?l:-l)z+=0>z?l:0md down=(Vmd=md||T( a(V++,md=T,20)}) upmd=+car(mdS||=z/k*þ,Ö=cos)*(P?-V:VË=sin)*V,g(P,2-Pxp=px,yp=py-2tS=3,T((g(3g(1,3S=1200VP=+!P)};var z,V,bgbackgroundColor";ÄbeginPathPÚ=Math,þ=PI,σ=2*þ,T=set,k=18l=36Üstyd=b,d.color#fffd=a,dd`dnull,a`δ=35aÈ=64Ò=È/2,J=[~G=[~Z=[0~uglobalCompositeOperanImageDataγ=["f00"639"f61"ccc"777"ff1"fff"~SB=$("10px"M=$("320px"M.ft280pxN( f(switch(Scase 1:t^c["put"+n](β,X-4,Y-4X=xp+Ö*t,Y=yp+Ë*-t+4.9*t*t,È>X^X>3^δ>Y?L,Y).data[2]:Sβ-4,Y-4,8,8r(5o(X,Y,3t+=.1,L^(R=7,S=2,s=-1,L>250^(s=+!(Ò>XXs].x,Ys].y,R=50ex=Xy=Y,É=R,Í=R/12r=R+.5);break;case 2:r(0c[u]destina-out,É+Íc[u]source-overrer-=Í,0>er^(Ss>=0^(S=5,Z[+!s]++,I a(g(+!s,I%2+1T(I++<4?a:N,800)}()))}pxP].x,pyP].y,B!S^z?"Ang: "+z+"\\n"+(V?"Velocity: "+V:""):"B.ft=(P?500:20)+"pxMZ[0]+">Score<"+Z[1~requestAnimaFrame(f)}();func),0,=U.arc,",,ereturn b.onmouse*þ/Ú.="){},[Ü]tionfor(rnd(=c["get"+n](X(a=.innerHTML=,b,d&b?14:49,[bg]bluele=G[+2=b.client@-a.offsetUc[Ä](c^&&_c.stroke`.height=zÃ~],,1Timeout.width=o(exy';for(Y in $='~z`_^U@ ')with(_.split($[Y]))_=join(pop());eval(_)
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
$ = function( p ) {
ñ = b.appendChild( document.createElement( "span" ) );
t = ñ[ Ü ];
t[ bg ] = "blue";
t.position = "absolute";
t.whiteSpace = "pre";
t.top = p;
return ñ;
}
rnd = function( A, B, C, D, E ) {
return Ú.ceil( Ú.random() * A );
}
// arc
K = function( A, B, C, D, E ) {
c[ Ä ]();
c.arc( A, B, C, -D, -E, 1 );
c.stroke();
}
// color
r = function( A, B, C, D, E ) {
c.fillStyle = c.strokeStyle = "#" + γ[ A ];
}
// circle
o = function(A, B, C, D, E ) {
c[ Ä ]();
c.arc( A, B, C, 0, σ );
c.fill();
}
// rectangle
Q = function( A, B, C, D, E ) {
c[ Ä ]();
c[ (E ? "clear" : "fill") + "Rect" ]( A - 1, B - 1, C + 2, D + 2 );
}
N = function( A, B, C, D, E ) {
// init state
S = 0;
// init player number
P = 0;
// clear canvas
Q( 0, 0, 999, 999, 1 );
// draw city
L = 2;
j = 1;
while( L < È ) {
// Set width of building
W = rnd( 37 ) + 37;
// Set height of building
H = Ú.max( rnd( 120 ) + ( rnd( 6 ) < 3 ? 130 : 15 ), 10 );
// Set the coordinates of the building into the array
J[ j++ ] = {
x: L,
y: δ - H,
w: W
};
r( rnd(3) );
Q( L, δ - H, W, H );
// drawin' windows
for ( e = L + 3, L += W + 2; e < L - 5; e += 10 ) {
for( i = H - 3; i >= 0; i -= 15 ) {
r( 5 - !( rnd(4) - 1 ) );
Q( e, δ - i, 3, 6 );
}
}
}
// place gorillas
for ( i = 0; i < 2; i++ ) {
// determine building for gorilla
L = J[ ( j - 2 ) * i + ( i ? - 2 : 2 ) + 1 ];
// register
G[ i ] = {
x: L.x + L.w / 2,
y: L.y - 30
};
// draw
g( i, 3 );
}
}
// drawGorilla
g = function( A, B, C, D, E ) {
var p = G[ A ],
x = p.x,
y = p.y;
// clear previous gorilla
Q( x - 15, y - 3, 28, 30, 1 );
r( 6 ); // white
// draw head
o( x, y + 2, 6 );
// body
Q( x - 7, y + 8, 13, 9 );
for( A = x; A <= x+4; A += .1 ) {
// legs
K( A, y + 25, 10, 3*þ/4, 9*þ/8 );
K( A - 6, y + 25, 10, 15*þ/8, þ/4 );
// arms
K( A - 5, y + (B & 1 ? 14 : 4), 9, 3*þ/4, 5*þ/4 ); // left
K( A, y + (B & 2 ? 14 : 4), 9, 7*þ/4, þ/4 ); // right
}
// draw eyes/brow
Q( x - 3, y + 2, 5, 0, 1 );
}
b.onmousemove = function( A, B, C, D, E ) {
dx =( A.clientX - a.offsetLeft - px) || .1;
dy = A.clientY - a.offsetTop - py;
à = Ú.round( Ú.atan( dy / dx ) / σ * ( P ? l : -l ) );
à += à < 0 ? l : 0;
}
md=0;
b.onmousedown = function( A, B, C, D, E ) {
V = 0;
md = md || T( function Ä( A, B, C, D, E ) {
V++;
md = T( Ä, 20 );
});
}
b.onmouseup = function( A, B, C, D, E ) {
md = +clearTimeout( md );
if ( !S ) {
// plotShot
A = Ã / k * þ;
Ö = Ú.cos( A ) * ( P ? -V : V );
Ë = Ú.sin( A ) * V;
g( P, 2 - P );
xp = px;
yp = py - 20;
t = 0,
S = 3;
T(function( A, B, C, D, E ) {
g( 0, 3 );
g( 1, 3 );
S = 1; // SHOT
}, 200);
// \plotshot
V = 0; // reset velocity
P = +!P; // pass turn
}
}
var Ã,
V,
bg = "backgroundColor";
Ä = "beginPath";
P = 0,
Ú = Math,
þ = Ú.PI,
σ = 2*þ,
T = setTimeout;
k = 180,
l = 360;
Ü = "style";
d = b[ Ü ];
d.color = "#fff";
d = a[ Ü ];
d[ bg ] = "blue";
d.height = d.width = null;
a.height = δ = 350;
a.width = È = 640;
Ò = È / 2;
J = [];
G = [];
Z = [ 0, 0 ];
u = "globalCompositeOperation";
n = "ImageData";
// colors
γ = [
"f00", // red
"639", // purple
"f61", // orange
"ccc", // light grey
"777", // grey
"ff1", // yellow
"fff" // white
];
S = 0;
B = $( "10px" ); // status info
M = $( "320px" ); // score info
M[ Ü ].left = "280px"
N(); // init
/*
SHOT = 1,
EXPLODE = 2,
SHOOTING = 3,
VICTORY = 5
*/
(function F() {
switch( S ) {
case 1: // SHOT
// updateShot
t && c["put"+n]( β, X - 4, Y - 4 );
X = xp + (Ö * t),
Y = yp + Ë * -t + 4.9 * t * t;
( X < È && X > 3 && Y < δ ) // check if on screen
? ( L = c["get"+n]( X, Y, 1, 1 ).data[ 2 ] ) // determine impact
: ( S = 0 ); // off screen
// store pre-banana data, so we can restore later
β = c["get"+n]( X - 4, Y - 4, 8, 8 );
// draw banana
r( 5 );
o( X, Y, 3 );
t += .1;
if ( L ) {
// only white pixels have G > 250 with current colors
R = 7;
S = 2;
s = -1;
if ( L > 250 ) {
s = +!(X < Ò);
X = G[ s ].x;
Y = G[ s ].y;
R = 50; // bigger boom!
}
ex = X;
ey = Y;
É = R,
Í = R / 12,
er = R+.5;
}
break;
case 2: // EXPLODE
// updateExplosion();
r( 0 );
c[ u ] = "destination-out";
o( ex, ey, É + Í );
c[ u ] = "source-over";
o( ex, ey, er );
er -= Í;
if ( er < 0 ) {
S = 0;
if ( s >= 0 ) {
S = 5; // VICTORY
Z[ +!s ]++;
I = 0;
(function B() {
g( +!s, I % 2 + 1 );
return T( I++ < 4 ? B : N, 800 );
}());
}
}
}
px = G[ P ].x;
py = G[ P ].y;
// update input status
B.innerHTML =
( !S && Ã ) ?
( "Angle: " + Ã + "\n" + ( V ? "Velocity: " + V : "") ) :
"";
B[ Ü ].left = ( P ? 500 : 20 ) + "px";
// update score
M.innerHTML = Z[ 0 ] + ">Score<" + Z[ 1 ];
requestAnimationFrame( F );
}());