"Panzer Dragoon 1k" is a 2D remake of Panzer Dragoon. GOAL: Use your Dragoon to prevent enemies from escaping.
_='t=g=D=U=X=Y=Q=8o^Cp^CImovexJX+99,yJY,tEL()},IupU=!g}ec)c[++(~E"")]=c[e];Lwith(c){setTimeout(L-18*x/X=.98*X+Y_3+`%9EgE6,32]1>t%Qzo[]^*,40+3e3*/(Q=30>Q?200:.98*Q-*(1`/1e4+K3e3,"#1"`%7`%5]HglobalAlpha=.8/(1+DG8cd",gzGe44"c(B6*D*,6*D*Ze=Ge44",i=f=X;14>i;i++)f-=+(i/20+.6)*-14,,3==i,44+90);D=x/io){e=o[iC t>~z7]),f^x,yC(F=FEt)zHB,$0<sq,U2(-XK2($-YK24F=0])Zf=,(-=f[5C~=t+5,_9,<f[0];D_@max(.6-/<18o[iC<0zg=gEt)}Bx,ysq2,2H gsq18OU=0}};fillNstrokeN@random()P*P+V*V<W*W,bgqarc(_3C$_4C,9()flc(f,9-i*14+Ya.widthrt(-t/14srR(-9,-9Oe[ Gffb",),(x-XK3=function(e){20-(t-FK2*@cos(-i/2`/12)0,,180];for(delete &&(f[2](y-YK28-2*ix(gEt(p[]^X,Y, in p[j],a.height$1]@Math.B taqC],E||F5]G"#Hsv(IonmouseJ=e.pageK)/NStyle=Orse(P0]-)V1]-$)W2]+)Z)jp)^=[_+=`+tqa(z(~6]fl';for(Y in $='~zq`_^ZWVPONKJIHGFECB@$ ')with(_.split($[Y]))_=join(pop());eval(_)
Xz0ndD1nPUQ9VT1YPVk9EVE9OBFvXkNwXkNJbW92ZQ54SlgrOTkseUpZLHRFTCgpfSxJdXAOVT0hZ30UZR1jKWNbEysYKyh+RSIiKV09Y1tlXTtMDndpdGgoYyl7c2V0VGltZW91dChMEi0xOCp4LwYLWD0uOTgqWCsMWV8ZMxErYCU5RWdFHDYsDBkzETJdCzE+dCVRem9bAl1eHyoCLDQwKzNlMyoCLyhRPTMwPlE/MjAwOi45OCpRCy0GKigxYC8xZTQrAkszZTMsERERIiMxImAlN2AlNV0LSGdsb2JhbEFscGhhPS44LygxK0QLRzhjZCIsZ3pHZTQ0In9jKBERHwtCNipEKgIsNipEKgJaZT0eBBRHZTQ0IixpPRFmPVg7MTQ+aTtpKyspZi09GisoaS8yMCsuNikqDAUtMTQsGiwaCzM9PWkWBSw0NCsMOTAQKTtEPXgvBhRpHW8pe2U9b1tpQwl0Pn56AQg3XSkELGZeeCx5EkMoRj1GRQN0KXpIQhMsJAswPA8Wc3EPLA8HVRYcMhEoEy1YSzIRKCQtWUsyETQRRj0wXSlaZj0eLAMoGC09Zls1Q349dCs1LBNfOSwVHgsGPGZbMF0WFR47RF9AbWF4KBEuNi0TLwYLGDwxOBYVb1tpQxM8MHpnPWdFdCl9QngseQtzcTIsMhsHSAlnFnNxMTgSG09VPTB9fTsBZmlsbE5zdHJva2VOAkByYW5kb20oKQNQKlArVipWPFcqVxYELGJncQthcmMoE18IM0MkXwg0QxgsETl/KCkFZmxjKGYsORAtaSoZMTQrWQZhLndpZHRoBwtydCgtdC8xNAtzclIoLTksLTkSEk8IZVsJR2ZmYiIsCyksDCh4LVhLMxEOPWZ1bmN0aW9uKGUpew8yMC0odC1GSzIQKkBjb3MoLWkvMmAvMTIpETAsEiwxOBMIMF0UO2ZvcigVZGVsZXRlIBYmJhcoZlsYCDJdGSh5LVlLGjI4LTIqaRt/eChnRXQSEhwocFsCXV5YLFksHSBpbiAecFtqXR8GLGEuaGVpZ2h0JAgxXUBNYXRoLkIJdGFxQ10sRXx8Rgg1XUcBIiNIc3YoC0lvbm1vdXNlSj1lLnBhZ2VLKS9OU3R5bGU9Twtyc2UoC1AXMF0tEylWFzFdLSQpVxcyXSsYKVopFGodcClePVtfKz1gK3RxYSh6Fih+CDZdfwtmbCc7Zm9yKFkgaW4gJD0nf356cWBfXlpXVlBPTktKSUhHRkVDQkAkHx4dHBsaGRgXFhUUExIREA8ODAsJCAcGBQQDAgEnKXdpdGgoXy5zcGxpdCgkW1ldKSlfPWpvaW4ocG9wKCkpO2V2YWwoXyk=
/**
* "Panzer Dragoon 1k" by @greweb
* an entry for JS1K 2014 "Here Be Dragons"
*
* Blog Post: http://greweb.me/2014/03/panzer-dragoon-1k
*/
// window object is polluted like hell with one letter variables ;-)
// i, j, e, f : are temporary variables
// Game States
t = // Game frame current time.
g = // GameOver Time || 0 if no GameOver
D = // "Danger" variable: more it is high, more there is danger (means a lot of opponent are reaching the left part)
U = // mouseup flag. It represents a missile shoot request.
//x = y = // x,y: mouse position <- we don't need their declaration because the game can't be started without them
X = Y = // X,Y: player position
0;
// Q : the mob pop factor. More it is low, more there is opponent popping.
// Q ~ depends on t but in a non trivial way. it ~ follows a sawtooth curve. See the algorithm in the opponent creation code.
Q = 80; // We start a bit lower than the reset value.
// Here we create 2 collections, but those are used as objects not array! Each element of these is a vector
o = []; // an opponent: [ 0: x, 1: y, 2: health, 3: vx, 4: vy, 5: locked, 6: hitTime ]
p = []; // a particule: [ 0: x, 1: y, 2: size, 3: vx, 4: vy, 5: damage ]
// Game Input
//ontouchmove = // mobile support. I wish I had more bytes!
onmousemove = function (e) {
x = e.pageX+99; // We don't directly use the mouse coordinate but we translate/scale the cursor to avoid behind able to shoot behind. It is like a constraint of the dragoon.
y = e.pageY;
t || L(); // the mouse moved, we can start the game once.
//return e.touches ? ontouchmove(e.touches[0]) : !1;
}
//ontouchend =
onmouseup = function (e) {
U = !g; // We can only shoot if game is not over
}
// Programmatically alias Context2d functions. (WARNING some functions are overrided with different behavior on different browsers)
for (e in c) c[e[0]+e[2]+(e[6]||"")] = c[e];
// L is the render loop
L = function (e) { with (c) { // with(c){} allows to we make all functions of "c" available in the scope
// Call the next frame.
setTimeout(L, 18 - 18 * x / a.width); // The framerate increases when you are targetting far in order to improve the gameplay.
// Move player in a smooth way
X = .98 * X + (x-X)/30;
Y += (y-Y)/30;
// Fire bullet
++t % 9 || // Increment the ticker here! but don't trigger a bullet each frame!
g || // Don't trigger a bullet if game is over
// Trigger one fire by adding to p
(p[Math.random()] = [ // It is the f**king way to add an element! to be used with delete and for-in loops.
X,
Y,
6,
(x-X) / 30,
(y-Y) / 30,
2
]);
t % Q < 1 && // May happen for a few times t until t%Q isn't < 1, it makes opponents coming by waves
// Creates an opponent
(o[Math.random()] = [
// Following values are important part of game difficulty
a.width, // X
a.height * Math.random(), // Y
// Health
40+3e3*Math.random()/
(
Q = Q < 30 ? 200 : .98 * Q // Update Q <- decrease, and move back to initial value for each new level
),
-a.width*(1+t/1e4+Math.random())/3e3, // VX
0, // VY
0, // hold
0,
"#1"+t%7+t%5 // Random color
]);
// Save the state to be restored later
sv();
// Draw background
globalAlpha = .8/(1+D); // The cheap way of doing Motion Blur
fillStyle = strokeStyle = "#8cd";
if (g) fillStyle = strokeStyle = "#e44";
flc(0,0,a.width,a.height);
// Next color for drawing bullets.
fillStyle = strokeStyle = "#ffb";
// Shake the whole screen proportionally to D
taa(6*D*Math.random(), 6*D*Math.random());
// Bullets Update & Draw
for(j in p) { e = p[j]; // Foreach Bullet e
// Drawing a circle
bga();
arc(
// Update bullet position
e[0] += e[3],
e[1] += e[4],
e[2],
0, 9); // OMG trick to goes from 0 to 2π
fl();
}
// Player Update & Draw
fillStyle = strokeStyle = "#e44";
// Drawing the Dragoon
for(i=0,f=X; i<14; i++) {
f -= 28 - 2*i + (i/20+.6)*(x-X)/30;
flc(
f,
Math.cos(-i/2+t/12)*9 - i*(y-Y)/14 + Y - 14,
28 - 2*i,// + 9*!i,
28 - 2*i// + 9*!i
);
if (i == 3) flc(
f,
Math.cos(-i/2+t/12)*9 - i*(y-Y)/14 + Y,
44+(x-X)/30,
Math.cos(-i/2+t/12)*90
);
}
D = x / a.width; // Danger is recomputed in the following Opponents loop
// Opponents Update & Draw
for(i in o) { e = o[i]; // Foreach Opponent e
fillStyle = strokeStyle = "#ffb";
if (t > e[6]) {
fillStyle = strokeStyle = e[7];
}
// Drawing a circle (it is the same chunk of code previously used!)
bga();
arc(
// Update opponent position
e[0] += e[3],
e[1] += e[4],
e[2],
0, 9);
fl();
f = [x, y, 18]; // Cursor "tuple", used for factorizing the distance formula
// Cursor Targetting
if (
// Opponent is targetted if he was not yet and the cursor is near the opponent. e[5] becomes the time of the targetting
e[5] = e[5] ||
// cursor hits opponent
(f[0]-e[0])*(f[0]-e[0])+(f[1]-e[1])*(f[1]-e[1]) < (f[2]+e[2])*(f[2]+e[2]) &&
t
) {
// Drawing a scaling/rotating cursor for the targetting effect
sv();
fillStyle = strokeStyle = "#ffb";
taa(e[0], e[1]);
if (0 < 20-(t-e[5])/2) {
// From the targetting time, we scale down to make the targetting effect
sa(
20-(t-e[5])/2,
20-(t-e[5])/2
);
}
rt(-t/14);
srR(-9,-9,18,18);
rse();
// Missile Bullet
U && // If hold off and opponent targetted, trigger a missile to that opponent
(p[Math.random()] = [
X,
Y,
20,
(e[0]-X)/20,
(e[1]-Y)/20,
40,
e[5] = 0 // Also reset the "locked" state here.
]);
}
for(j in p) { f = p[j]; // Foreach Bullet f - N.B. it seems impossible to reconciliate to the previous for(i in p) loop here because there is better bytes save implied.
if ( // bullet hits opponent
(f[0]-e[0])*(f[0]-e[0])+(f[1]-e[1])*(f[1]-e[1]) < (f[2]+e[2])*(f[2]+e[2])
// ^ Intentionally, we have the exact same code that that previously!
) {
e[2] -= f[5]; // Apply bullet force from bullet size
e[6] = t+5; // Flash effect
e[0] += 9; // backwards effect on shot
delete p[j]; // And here is the way we remove an element!
}
// Out of Bound to prevent memory leaks!!!
if (a.width < f[0])
delete p[j];
}
// Accumulate Danger with the left opponent distance
D += Math.max(0, .6-e[0]/a.width);
// Destroy Opponent if his life is enough small
if (e[2]<18)
delete o[i];
// Game Over reached with an opponent reaches the left side
if (e[0]<0)
g = g || t;
}
// Draw the Cursor with its score text
fillStyle = strokeStyle = "#ffb";
taa(x, y);
sa(2, 2);
flx(g||t,18,18);
rt(-t/14);
srR(-9,-9,18,18);
rse();
// Draw the top-left Score
sv();
fillStyle = strokeStyle = "#ffb";
if (g) sa(18, 18); // Scale it up if game is over
flx(g||t,18,18);
rse();
U = 0; // reset the mouseup flag
}}