<!DOCTYPE HTML>
<html lang="en">
<head>
<title>HTML5 Canvas Game Tutorial</title>
<meta charset="utf-8">
</head>
<body onload="init()" style="margin:0px; overflow:hidden;">
<canvas id="canvas"></canvas>
<script>
//Declare Global Variables
var can = document.getElementById("canvas");
var ctx = can.getContext("2d");
var cw = can.width = window.innerWidth;
var ch = can.height = window.innerHeight;
//Create a 2D array to spell out words and shoot at
var title = [
[0,0,0,0,0,0,1,0,0,1,0,2,2,2,2,2,0,3,0,0,0,3,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,1,0,0,1,0,0,0,2,0,0,0,3,3,0,3,3,0,4,0,0,0,0,0,5,0,0,0,6,6,0,0,7,0,0,0,0,0,0,8,8,0,0,9,9,9,0,0,0],
[0,0,0,0,0,0,1,0,0,1,0,0,0,2,0,0,0,3,0,3,0,3,0,4,0,0,0,0,5,0,5,0,6,0,6,0,0,7,7,7,7,7,0,8,0,0,8,0,9,0,0,0,0,0],
[0,0,0,0,0,0,1,1,1,1,0,0,0,2,0,0,0,3,0,0,0,3,0,4,0,0,0,0,5,0,5,0,6,0,6,0,0,7,0,7,0,7,0,8,8,8,0,0,0,9,9,0,0,0],
[0,0,0,0,0,0,1,0,0,1,0,0,0,2,0,0,0,3,0,0,0,3,0,4,0,0,0,0,0,5,5,0,6,0,6,0,0,7,0,7,0,7,0,8,0,0,0,0,0,0,9,0,0,0],
[0,0,0,0,0,0,1,0,0,1,0,0,0,2,0,0,0,3,0,0,0,3,0,4,0,0,0,0,0,0,5,0,0,6,0,6,0,7,0,7,0,7,0,0,8,8,0,0,9,9,9,0,0,0],
[0,0,0,0,0,0,1,0,0,1,0,0,0,2,0,0,0,3,0,0,0,3,0,4,4,4,4,0,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]];
//Colors array determines the colors used
var colors = ["#FF0000","#00FF00","#0000FF","#FFFF00", "#FF00FF", "#00FFFF"];
var bullets = [];
var mouse = {x:cw/2,y:0};
function init() {
animate();
draw();
//This next line copies the title array so it displays twice
for(var i=0, len=title.length; i<len; i++) title.push(title[i].slice());
}
//The animate function gets called every frame and calls draw() and processBullets()
function animate() {
window.requestAnimationFrame(animate);
draw();
if (bullets.length > 0) processBullets();
}
//This function determines if a bullet hit a square, It needs to determine
//the width and height of the squares. Then the for-loop starts to process
//each bullet. The bullet is first moved -y (towards the top). Then x and y
//are calculated which determines where the bullet is in the 2D array (title)
//Next, a check is done that will remove the bullet if it went above the screen
//Finally, the location in title is checked, if it isn't zero then its a hit
//When a bullet hits it makes the spot in the 2D array zero and removes the bullet
//Lastly, the bullet is drawn as a white circle
function processBullets() {
var rWidth=cw/title[0].length;
var rHeight=(ch-30)/title.length;
for (var i=0, len=bullets.length; i<len; i++) {
bullets[i].y -= 5;
var y = Math.floor(bullets[i].y/rHeight);
var x = Math.floor(bullets[i].x/rWidth);
if (y < 0) {bullets.splice(i,1); i -= 1;}
else if (title[y][x] != 0) {
title[y][x] = 0;
bullets.splice(i,1);
i -= 1;
}
ctx.beginPath();
ctx.fillStyle="white";
ctx.arc(bullets[i].x,bullets[i].y,4,0,Math.PI*2);
ctx.fill();
}
}
//Draw is responsible for drawing the 2D array (title) on the screen
//It clears the screen and then finds the width and height for each block
//Then 2 for-loops go through the array and draw each rectangle
//The reason why there are so many commands is because a highlight line
//and a shadow line are drawn on each box so they stand out
//Lastly, drawShip is called
function draw() {
ctx.fillStyle = "black";
ctx.fillRect(0,0,cw,ch);
var rWidth=cw/title[0].length;
var rHeight=(ch-30)/title.length;
ctx.lineWidth="4";
for (var i=0, ilen=title[0].length; i<ilen; i++) {
for (var j=0, jlen=title.length; j<jlen; j++) {
if (title[j][i] == 0) continue;
ctx.fillStyle=colors[title[j][i]%6];
ctx.fillRect(i*rWidth, j*rHeight, rWidth-4, rHeight-4);
//Highlight Lines (Right and Top sides);
ctx.beginPath();
ctx.strokeStyle="rgba(255,255,255,.5)";
ctx.moveTo(i*rWidth+2, j*rHeight+rHeight-4);
ctx.lineTo(i*rWidth+2, j*rHeight+2);
ctx.lineTo(i*rWidth+rWidth-4, j*rHeight+2);
ctx.stroke();
//Shadow Lines (Left and Bottom sides)
ctx.beginPath();
ctx.strokeStyle="rgba(0,0,0,.5)";
ctx.moveTo(i*rWidth+rWidth-6, j*rHeight+4);
ctx.lineTo(i*rWidth+rWidth-6, j*rHeight+rHeight-6);
ctx.lineTo(i*rWidth+4, j*rHeight+rHeight-6);
ctx.stroke();
}
}
drawShip();
}
//drawShip simply draws the ship at the bottom. It is just made
//from a bunch of jagged lines with its x position matched to mouse
function drawShip() {
ctx.strokeStyle="white";
ctx.lineWidth="2";
ctx.beginPath();
ctx.moveTo(mouse.x-30,ch);
ctx.lineTo(mouse.x+30,ch);
ctx.lineTo(mouse.x+25,ch-20);
ctx.lineTo(mouse.x+20,ch-5);
ctx.lineTo(mouse.x+10,ch-10);
ctx.lineTo(mouse.x,ch-30);
ctx.lineTo(mouse.x-10,ch-10);
ctx.lineTo(mouse.x-20,ch-5);
ctx.lineTo(mouse.x-25,ch-20);
ctx.lineTo(mouse.x-30,ch);
ctx.stroke();
}
//This event listener updates the mouse object with the latest mouse position
window.addEventListener("mousemove", function(e) {mouse={x:e.clientX,y:e.clientY}});
//This event listener fires a bullet by adding the bullet object to the bullets array
window.addEventListener("click", function(e) {bullets.push({x:mouse.x,y:ch-30})});
</script>
</body>
</html>