Space Invadors destroyed this page! Take revenge on them!
Use Space to shoot and   to move!   

.center{text-align:center} #space-invaders { margin: 0 auto; display: block; background: white } ;(function() { "use strict"; // General var canvas, screen, gameSize, game; // Assets var invaderCanvas, invaderMultiplier, invaderSize = 20, initialOffsetInvader, invaderAttackRate, invaderSpeed, invaderSpawnDelay = 250; // Counter var i = 0, kills = 0, spawnDelayCounter = invaderSpawnDelay; var invaderDownTimer; // Text var blocks = [ [3, 4, 8, 9, 10, 15, 16], [2, 4, 7, 11, 14, 16], [1, 4, 7, 11, 13, 16], [1, 2, 3, 4, 5, 7, 11, 13, 14, 15, 16, 17], [4, 7, 11, 16], [4, 8, 9, 10, 16] ]; // Game Controller // --------------- var Game = function() { this.level = -1; this.lost = false; this.player = new Player(); this.invaders = []; this.invaderShots = []; if (invaderDownTimer === undefined) { invaderDownTimer = setInterval(function() { for (i = 0; i < game.invaders.length; i++) game.invaders[i].move(); }, 1000 - (this.level * 1.8)); }; } Game.prototype = { update: function() { // Next level if (game.invaders.length === 0) { spawnDelayCounter += 1; if (spawnDelayCounter < invaderSpawnDelay) return; this.level += 1; invaderAttackRate -= 0.002; invaderSpeed += 10; game.invaders = createInvaders(); spawnDelayCounter = 0; } if (!this.lost) { // Collision game.player.projectile.forEach(function(projectile) { game.invaders.forEach(function(invader) { if (collides(projectile, invader)) { invader.destroy(); projectile.active = false; } }); }); this.invaderShots.forEach(function(invaderShots) { if (collides(invaderShots, game.player)) { game.player.destroy(); } }); for (i = 0; i < game.invaders.length; i++) game.invaders[i].update(); } // Don't stop player & projectiles.. they look nice game.player.update(); for (i = 0; i < game.invaderShots.length; i++) game.invaderShots[i].update(); this.invaders = game.invaders.filter(function(invader) { return invader.active; }); }, draw: function() { if (this.lost) { screen.fillStyle = "rgba(0, 0, 0, 0.03)"; screen.fillRect(0, 0, gameSize.width, gameSize.height); screen.font = "55px Lucida Console"; screen.textAlign = "center"; screen.fillStyle = "white"; screen.fillText("You lost", gameSize.width / 2, gameSize.height / 2); screen.font = "20px Lucida Console"; screen.fillText("Points: " + kills, gameSize.width / 2, gameSize.height / 2 + 30); } else { screen.clearRect(0, 0, gameSize.width, gameSize.height); screen.font = "10px Lucida Console"; screen.textAlign = "right"; screen.fillText("Points: " + kills, gameSize.width, gameSize.height - 12); } screen.beginPath(); var i; this.player.draw(); if (!this.lost) for (i = 0; i < this.invaders.length; i++) this.invaders[i].draw(); for (i = 0; i < this.invaderShots.length; i++) this.invaderShots[i].draw(); screen.fill(); }, invadersBelow: function(invader) { return this.invaders.filter(function(b) { return Math.abs(invader.coordinates.x - b.coordinates.x) === 0 && b.coordinates.y > invader.coordinates.y; }).length > 0; } }; // Invaders // -------- var Invader = function(coordinates) { this.active = true; this.coordinates = coordinates; this.size = { width: invaderSize, height: invaderSize }; this.patrolX = 0; this.speedX = invaderSpeed; }; Invader.prototype = { update: function() { if (Math.random() > invaderAttackRate && !game.invadersBelow(this)) { var projectile = new Projectile({ x: this.coordinates.x + this.size.width / 2, y: this.coordinates.y + this.size.height - 5 }, { x: 0, y: 2 }); game.invaderShots.push(projectile); } }, draw: function() { if (this.active) screen.drawImage(invaderCanvas, this.coordinates.x, this.coordinates.y); }, move: function() { if (this.patrolX < 0 || this.patrolX > 100) { this.speedX = -this.speedX; this.patrolX += this.speedX; this.coordinates.y += this.size.height; if (this.coordinates.y + this.size.height * 2 > gameSize.height) game.lost = true; } else { this.coordinates.x += this.speedX; this.patrolX += this.speedX; } }, destroy: function() { this.active = false; kills += 1; } }; // Player // ------ var Player = function() { this.active = true; this.size = { width: 16, height: 8 }; this.shooterHeat = -3; this.coordinates = { x: gameSize.width / 2 - (this.size.width / 2) | 0, y: gameSize.height - this.size.height * 2 }; this.projectile = []; this.keyboarder = new KeyController(); }; Player.prototype = { update: function() { for (var i = 0; i < this.projectile.length; i++) this.projectile[i].update(); this.projectile = this.projectile.filter(function(projectile) { return projectile.active; }); if (!this.active) return; if (this.keyboarder.isDown(this.keyboarder.KEYS.LEFT) && this.coordinates.x > 0) this.coordinates.x -= 2; else if (this.keyboarder.isDown(this.keyboarder.KEYS.RIGHT) && this.coordinates.x < gameSize.width - this.size.width) this.coordinates.x += 2; if (this.keyboarder.isDown(this.keyboarder.KEYS.Space)) { this.shooterHeat += 1; if (this.shooterHeat < 0) { var projectile = new Projectile({ x: this.coordinates.x + this.size.width / 2 - 1, y: this.coordinates.y - 1 }, { x: 0, y: -7 }); this.projectile.push(projectile); } else if (this.shooterHeat > 12) this.shooterHeat = -3; } else { this.shooterHeat = -3; } }, draw: function() { if (this.active) { screen.rect(this.coordinates.x, this.coordinates.y, this.size.width, this.size.height); screen.rect(this.coordinates.x - 2, this.coordinates.y + 2, 20, 6); screen.rect(this.coordinates.x + 6, this.coordinates.y - 4, 4, 4); } for (var i = 0; i < this.projectile.length; i++) this.projectile[i].draw(); }, destroy: function() { this.active = false; game.lost = true; } }; // Projectile // ------ var Projectile = function(coordinates, velocity) { this.active = true; this.coordinates = coordinates; this.size = { width: 3, height: 3 }; this.velocity = velocity; }; Projectile.prototype = { update: function() { this.coordinates.x += this.velocity.x; this.coordinates.y += this.velocity.y; if (this.coordinates.y > gameSize.height || this.coordinates.y < 0) this.active = false; }, draw: function() { if (this.active) screen.rect(this.coordinates.x, this.coordinates.y, this.size.width, this.size.height); } }; // Keyboard input tracking // ----------------------- var KeyController = function() { this.KEYS = { LEFT: 37, RIGHT: 39, Space: 32 }; var keyCode = [37, 39, 32]; var keyState = {}; var counter; window.addEventListener('keydown', function(e) { for (counter = 0; counter < keyCode.length; counter++) if (keyCode[counter] == e.keyCode) { keyState[e.keyCode] = true; e.preventDefault(); } }); window.addEventListener('keyup', function(e) { for (counter = 0; counter < keyCode.length; counter++) if (keyCode[counter] == e.keyCode) { keyState[e.keyCode] = false; e.preventDefault(); } }); this.isDown = function(keyCode) { return keyState[keyCode] === true; }; }; // Other functions // --------------- function collides(a, b) { return a.coordinates.x < b.coordinates.x + b.size.width && a.coordinates.x + a.size.width > b.coordinates.x && a.coordinates.y < b.coordinates.y + b.size.height && a.coordinates.y + a.size.height > b.coordinates.y; } function getPixelRow(rowRaw) { var textRow = [], placer = 0, row = Math.floor(rowRaw / invaderMultiplier); if (row >= blocks.length) return []; for (var i = 0; i < blocks[row].length; i++) { var tmpContent = blocks[row][i] * invaderMultiplier; for (var j = 0; j < invaderMultiplier; j++) textRow[placer + j] = tmpContent + j; placer += invaderMultiplier; } return textRow; } // Write Text // ----------- function createInvaders() { var invaders = []; var i = blocks.length * invaderMultiplier; while (i--) { var j = getPixelRow(i); for (var k = 0; k < j.length; k++) { invaders.push(new Invader({ x: j[k] * invaderSize, y: i * invaderSize })); } } return invaders; } // Start game // ---------- window.addEventListener('load', function() { var invaderAsset = new Image; invaderAsset.onload = function() { invaderCanvas = document.createElement('canvas'); invaderCanvas.width = invaderSize; invaderCanvas.height = invaderSize; invaderCanvas.getContext("2d").drawImage(invaderAsset, 0, 0); // Game Creation canvas = document.getElementById("space-invaders"); screen = canvas.getContext('2d'); initGameStart(); loop(); }; invaderAsset.src = "//stillh.art/project/spaceInvaders/invader.gif"; }); window.addEventListener('resize', function() { initGameStart(); }); document.getElementById('restart').addEventListener('click', function() { initGameStart(); }); function initGameStart() { if (window.innerWidth > 1200) { screen.canvas.width = 1200; screen.canvas.height = 500; gameSize = { width: 1200, height: 500 }; invaderMultiplier = 3; initialOffsetInvader = 420; } else if (window.innerWidth > 800) { screen.canvas.width = 900; screen.canvas.height = 600; gameSize = { width: 900, height: 600 }; invaderMultiplier = 2; initialOffsetInvader = 280; } else { screen.canvas.width = 600; screen.canvas.height = 300; gameSize = { width: 600, height: 300 }; invaderMultiplier = 1; initialOffsetInvader = 140; } kills = 0; invaderAttackRate = 0.999; invaderSpeed = 20; spawnDelayCounter = invaderSpawnDelay; game = new Game(); } function loop() { game.update(); game.draw(); requestAnimationFrame(loop); } })();