c=document.body.children[0];w=c.width=800;h=c.height=300;C=c.getContext("2d");C.t=C.fillText;C.lineWidth=3;M=Math;R=M.random;O='';e=[];t=[];l=1;W=C.strokeStyle='#fff';X=[];Y=[];for(K=i=Q=0;i<99;i++)X[i]=R()*w,Y[i]=R()*h,i<3&&(b=i*99+60,t[i]={X:400,Y:b,a:400,b:b});setInterval("J=++Q%40;R()<(K+60)/2e3&&e.push({x:0,y:R()*280+20,J:J?1:40,s:J?Q%7?Q%2:3:2});C.font='25px a';C[F='fillStyle']='#000';C.fillRect(0,0,w,h);C[F]=W;for(i in X)C.fillRect((X[i]+Q)%w,Y[i],1+i%2,2);for(i in t)with(t[i]){X+=X-a<-1?2:X-a>1?-2:0;Y+=Y-b<-1?2:Y-b>1?-2:0;C[F]=i^l?'#66f':'#e33';C.t('◉[',X,Y);for(j in e)with(e[j]){+i||(x+=s<3?2:3,C[F]='#ef1',C.t('⤘⇴▶✈'[s],x,y));x>w&&(O=' GAME OVER',e.splice(j,1))||M.abs(X-x)<28&&M.abs(Y-y)<28&&(C.beginPath(),C.moveTo(x+7,y-7),C.lineTo(X+7,Y-7),C.stroke(),--J||(e.splice(j,1),O||K++))}}C[F]=W;C.font='16px courier';C.t('Deep Space Defense [z,x,c=select ship m1=move] Score:'+K+O,6,h-9)",50);onclick=function(e){t[l].a=e.pageX-9;t[l].b=e.pageY+8};onkeydown=function(e){u=e.keyCode;l=u^90?u^67?1:2:0}
// .body.children[0] is shorter than .getElementById('c')
var canvas = document.body.children[0],
width = c.width = 800,
height = c.height = 300,
context = canvas.getContext("2d");
context.lineWidth = 3;
context.strokeStyle = "#fff";
var gameOver = "",
enemies = [],
ships = [],
selected = 1,
score = 0,
time = 0;
for (var i = 0; i < 3; i++) {
var y = i * 100 + 60;
// x,y are current coordinates, gx,gy are goal coordinates (when moving)
ships[i] = {x: width / 2, y: y, gx: width / 2, gy: y};
}
var starsX = [],
starsY = [];
for (var i = 0; i < 99; i++) {
starsX[i] = Math.random() * width;
starsY[i] = Math.random() * height;
}
function timeStep() {
time++;
// depending on the score, there is a chance a new enemy is spawned
if (Math.random() < (score + 60) / 2000) {
var bigEnemy = time % 40 == 0;
enemies.push({
x: 0,
y: Math.random() * 280 + 20,
// hit points
hp: bigEnemy ? 40 : 1,
// 0,1=grunt 2=shielded 3=fast
type: bigEnemy ? 2 : (time % 7 == 0) ? 3 : time % 2
});
}
// Clear the screen
context.fillStyle = "#000";
context.fillRect(0, 0, width, height);
// Draw the stars
context.fillStyle = "#fff";
// the modulo in the first argument (x) causes the scrolling.
// the modulo in the third argument (width) causes some stars to look brigher.
for(var i in starsX)
context.fillRect((starsX[i] + time) % width, starsY[i], 1 + i % 2, 2);
context.font = "25px arial";
// Go over the ships
for (var i in ships) {
var ship = ships[i], dx = ship.x - ship.gx, dy = ship.y - ship.gy;
// Move the ship
if (dx < -1) ship.x += 2;
else if (dx > 1) ship.x -= 2;
if (dy < -1) ship.y += 2;
else if (dy > 1) ship.y -= 2;
// Draw the ship
context.fillStyle = i == selected ? "#e33" : "#66f";
context.fillText("◉[", ship.x, ship.y);
// Go over the enemies
for (var j in enemies) {
var enemy = enemies[j];
// Move and draw (only once per turn)
if (i == 0) {
enemy.x += enemy.type == 3 ? 3 : 2;
context.fillStyle = "#ef1";
context.fillText("⤘⇴▶✈".charAt(enemy.type), enemy.x, enemy.y);
}
// Reached the other side
if (enemy.x > width) {
gameOver = " GAME OVER";
enemies.splice(j, 1);
}
// Close to this ship
else if (Math.abs(ship.x - enemy.x) < 28 &&
Math.abs(ship.y - enemy.y) < 28) {
context.beginPath();
context.moveTo(enemy.x + 7, enemy.y - 7);
context.lineTo(ship.x + 7, ship.y - 7);
context.stroke();
// When dead, remove enemy, update score
if (--enemy.hp == 0) {
enemies.splice(j, 1);
if (!gameOver) score++;
}
}
}
}
// Draw status text
context.fillStyle = "#fff";
context.font = "16px courier";
context.fillText("Deep Space Defense [z,x,c=select ship m1=move] Score:"
+ score + gameOver, 6, height - 9);
}
setInterval(timeStep, 50);
window.onclick = function(event) {
ships[selected].gx = event.pageX - 9;
ships[selected].gy = event.pageY + 8;
};
window.onkeydown = function(event) {
if (event.keyCode == 90) selected = 0;
else if (event.keyCode == 67) selected = 2;
else selected = 1;
};