This is a small game I made for the old version of my blog. Unfortunately, my blog has had a bit of a makeover and I have not yet put the game in. You should easily be able to play the game as soon as it pops up though.

Note that I will not be linking to any repositories here, and I will instead paste the source code at the bottom of the page

image
image
$(document).ready(setTimeout(initGame, 3000));
function initGame() {

	// Setup Functions
	$(window).resize(setSize);
	$(window).scroll(setSize);


	function setSize() {
		width = $(window).width();
		height = $(window).height();

		scrollLeft = $(document).scrollLeft();
		scrollTop = $(document).scrollTop();
		scrollDiffX = scrollLeft - $(canvas).position().left;
		scrollDiffY = scrollTop - $(canvas).position().top;

        canvas.width = width;
        canvas.height = height;
		canvas.style.top = scrollTop + "px";
		canvas.style.left = scrollLeft + "px";

		player.x -= scrollDiffX;
		player.y -= scrollDiffY;

		starfield.stars.forEach(function(e) {
			e.x -= scrollDiffX;
			e.y -= scrollDiffY;
		});

		asteroidBelt.asteroids.forEach(function(e) {
			e.x -= scrollDiffX;
			e.y -= scrollDiffY;
		});

		player.lasers.forEach(function(e) {
			e.x -= scrollDiffX;
			e.y -= scrollDiffY;
		});

		if (width < 1280) {
			inPlay = false;
			gameEnabled = false;
		}
		else {
			if (!gameEnabled) {
				gameEnabled = true;
				inPlay = false;
				player = new Player(width - playerW, height - playerH, playerW, playerH);
				asteroidBelt = new AsteroidBelt();
				updateGame();
			}

		}
	}

	function createLayer () {
    	var canvas = document.createElement('canvas');
		canvas.style.position = "absolute";
		canvas.style.left = "0px";
		canvas.style.right = "0px";
		canvas.style.top = "0px";
		canvas.style.zIndex = "-200";


		var body = document.getElementsByTagName("body")[0];
		body.appendChild(canvas);

		return canvas;
	}


    // Setup
	var canvas = createLayer();
	var width = 0;
	var height = 0;
	var context = canvas.getContext('2d');

	var canvasDisp = 0;

	var mouseX = 0;
	var mouseY = 0;
	var mouseMoved = false;

	var scrollTop = 0;
	var scrollLeft = 0;
	var scrollDiffX = 0;
	var scrollDiffY = 0;

	var inPlay = false;
	var gameEnabled = true;

	var playerW = 50;
	var playerH = 100;
	var nukeCount = 0;
	var nukeCountReq = 10;


	var hud = new HUD();
	var starfield = new Starfield();
	var player = new Player(width - playerW, height - playerH, playerW, playerH);
	var asteroidBelt = new AsteroidBelt();
	setSize();

	$(document).mousemove(function() {
		mouseX = $(document).scrollLeft() + event.clientX - $('canvas').offset().left;
        mouseY = $(document).scrollTop() + event.clientY - $('canvas').offset().top;

		mouseMoved = true;
	})

	$(document).click(function() {
		if (gameEnabled) {
			if (!inPlay) {
				// If the game isn't being played and the player clicks on the rocket, start
				if (mouseX > player.x - player.width && mouseY > player.y - player.height)
					inPlay = true;
			}
			else {
				// When the game is in play and the player shoots
				player.shoot();
			}
		}
	})

	var zDown = false;
	var xDown = false;
	var nukeDown = false;

	$(document).keypress(function(e) {
		if (gameEnabled && inPlay)
			if (!zDown && e.keyCode == 122) {
				zDown = true;
				player.shoot();
			}
			else if (!xDown && e.keyCode == 120) {
				xDown = true;
				player.shoot();
			}
			else if (!xDown && e.keyCode == 99) {
				nukeDown = true;
				player.nuke();
			}
	})

	$(document).keyup(function(e) {
		if (e.keyCode == 90)
			zDown = false;
		else if (e.keyCode == 88)
			xDown = false;
		else if (e.keyCode == 67)
			nukeDown = false;
	})

    // Player class
    function Player(x, y, pWidth, pHeight) {
		hud.reset();
        this.x = x;
        this.y = y;

        this.width = pWidth;
        this.height = pHeight;
		this.radius = 50;
		this.angle = 0;
		this.velX = 0;
		this.velY = 0;

		this.slowMod = 3;
		this.resistance = 0.98;

		this.drawing = new Image();
		this.drawing.src = "/content/rocket_game/rocket.png";

		this.lasers = [];

		this.shoot = function() {
			this.lasers.push(new Laser(this.x, this.y, this.angle));
		}

		this.nuke = function() {
			if (nukeCount >= nukeCountReq) {
				nukeCount = 0;
				nukeCountReq *= 1.5;

				for (var i = 0; i < 360; i++) {
					var angle = (i / 180) * Math.PI;
					this.lasers.push(new Laser(this.x, this.y, angle));
				}
			}
		}

		this.update = function() {
			if (!inPlay) {
				this.x = width - this.width;
				this.y = height - this.height;

				if (mouseX > this.x - this.width && mouseY > this.y - this.height)
					this.angle = -0.5;
				else
					this.angle =0;
			}
			else {
				var angleTot;
				if (mouseX > this.x)
					angleTot = Math.atan((mouseY - this.y) / (mouseX - this.x)) - Math.PI / 2 + Math.PI;
				else
					angleTot = Math.atan((mouseY - this.y) / (mouseX - this.x)) - Math.PI / 2;

				// I made angleTot incase I wanted to do precalculations
				this.angle = angleTot;

				// Only accelerate if moving the mouse
				if (mouseMoved) {
					// Calculate the angle

					// Calculate the velocity
					var mod = Math.hypot(mouseY - this.y, mouseX - this.x) * this.slowMod;
					this.velX += (mouseX - this.x) / mod;
					this.velY += (mouseY - this.y) / mod;

					mouseMoved = false;
				}

				this.velX *= this.resistance;
				this.velY *= this.resistance;

				// Apply velocity
				this.x += this.velX;
				this.y += this.velY;

				// Check lasers
				this.lasers = this.lasers.filter(function (laser) {
					return (laser.x > -width/2 && laser.x < width + width/2 && laser.y > -height/2 && laser.y < height + height/2);
				});
			}
		}

        this.draw = function() {
			for (var i = 0; i < this.lasers.length; i++) {
				this.lasers[i].draw();
			}

			// Translate to the origin, rotate and draw, then translate back
			context.translate(this.x, this.y);
			context.rotate(this.angle);
            context.drawImage(this.drawing, - this.width / 2, - this.height / 2, this.width, this.height);
			context.rotate(-this.angle);
			context.translate(-this.x, -this.y);

        }
	}

	// Laser
	function Laser(x, y, angle) {
		this.x = x;
		this.y = y;

		this.angle = angle - Math.PI / 2;
		this.speed = 45;
		this.velX = Math.cos(this.angle) * this.speed;
		this.velY = Math.sin(this.angle) * this.speed;

		this.colour = getRandomColor();

		this.draw = function() {

			this.x += this.velX;
			this.y += this.velY;

			context.beginPath();
			context.lineWidth="3.5";
			context.strokeStyle= this.colour;
			context.moveTo(this.x,this.y);
			context.lineTo(this.x + this.velX * 2, this.y + this.velY * 2);

			context.stroke();
		}
	}

	// Asteroids
	function Asteroid(image) {

		this.width = Math.random() * 200 + 100;
		this.radius = 0.45 * this.width;

		this.angle = 0;
		this.angleIncreaseSpeed = ((Math.random() * 2) - 1) * 0.05;

		this.x = 0;
		do {
			this.x = Math.random() * width * 3 - width;
		} while (this.x >= 0 - this.width && this.x <= width);

		this.y = 0
		do {
			this.y = Math.random() * height * 3 - height;
		} while (this.y >= 0 - this.height && this.y <= height);

		this.velX = 0;
		this.velY = 0;

		this.randomModifier = Math.random() * 10 + 25;

		this.drawing = image;

		this.update = function() {
			var mod = Math.hypot(mouseY - this.y, mouseX - this.x) * this.randomModifier;
			this.velX += (player.x - this.x) / mod;
			this.velY += (player.y - this.y) / mod;

			this.x += this.velX;
			this.y += this.velY;
		}

		this.draw = function() {
			this.angle += this.angleIncreaseSpeed;

			context.translate(this.x, this.y);
			context.rotate(this.angle);

            context.drawImage(this.drawing, - this.width / 2, -this.width / 2, this.width, this.width);

			context.rotate(-this.angle);
			context.translate(-this.x, -this.y);
		}
	}

	function AsteroidBelt() {
		this.chanceToSpawn = 1;
		this.chanceIn = 200;

		this.drawing = new Image();
		this.drawing.src = "/content/rocket_game/asteroid.png";

		this.asteroids = [];

		this.update = function(score) {
			if (inPlay) {

				if (Math.floor(Math.random() * this.chanceIn <= this.chanceToSpawn + score / 5)) {
					this.asteroids.push(new Asteroid(this.drawing));
				}
				for (var i = 0; i < this.asteroids.length; i++)
					this.asteroids[i].update();
			}
		}

		this.draw = function() {
			for (var i = 0; i < this.asteroids.length; i++) {
				this.asteroids[i].draw();
			}
		}
	}

	// Stars
	function Star(velX, velY) {

		this.x = Math.random() * width * 2;
		this.y = 0;

		this.speed = Math.random() * 35 + 5;

		this.velX = velX * this.speed;
		this.velY = velY * this.speed;

		this.length = Math.random() * 50 + 10;

		this.color = "#000000";
		if (hud.score >= 30)
			this.color = getRandomColor();
		else {
			var randomNum = Math.floor(Math.random() * 5);
			if (randomNum <= 0)
				this.color = "#000000";
			else if (randomNum <= 1)
				this.color = "#333333";
			else if (randomNum <= 2)
				this.color = "#555555";
			else if (randomNum <= 3)
				this.color = "#888888";
			else if (randomNum <= 4)
				this.color = "#AAAAAA";
		}

		this.draw = function() {
			this.x += this.velX;
			this.y += this.velY;

			context.beginPath();
			context.lineWidth="2";
			context.strokeStyle= this.color;
			context.moveTo(this.x,this.y);
			context.lineTo(this.x - this.velX * this.length, this.y - this.velY * this.length);

			context.stroke();
		}
	}

	function Starfield() {
		this.chanceToSpawn = 1;
		this.velX = -1;
		this.velY = 1;

		this.stars = [];

		this.update = function() {
			if (inPlay) {
				if (Math.floor(Math.random() * 6 <= this.chanceToSpawn)) {
					this.stars.push(new Star(this.velX, this.velY));
				}
			}

			this.stars = this.stars.filter(function (star) {
				return (star.x > -width * 3 && star.y < height * 3);
			});
		}

		this.draw = function() {
			if (inPlay)
				for (var i = 0; i < this.stars.length; i++) {
					this.stars[i].draw();
				}
		}
	}

	function HUD() {
		this.score = 0;
		this.highScore = 0;
		this.fontSize = 80;
		this.fontSizeMax = 250;

		this.inc = function() {
			this.score += 1;
			nukeCount += 1;

			if (this.score > this.highScore)
				this.highScore = this.score
		}

		this.reset = function() {
			this.score = 0;
			nukeCount = 0;
			nukeCountReq = 10;
		}

		this.draw = function() {
			if (gameEnabled && inPlay) {
				var totalFont = this.fontSize + this.score * 2;
				if (totalFont > this.fontSizeMax)
					totalFont = this.fontSizeMax;

				var text = "";
				var colour = "#000000";

				if (this.score == 0)
					text = "";
				else if (this.score < 5) {
					text = "Hey ;)";
				}
				else if (this.score < 10)
					text = "Nice.";
				else if (this.score < 15)
					text = "Wow :D";
				else if (this.score < 15)
					text = "Lit!";
				else if (this.score < 25)
					text = "You're pretty good!";
				else if (this.score < 30)
					text = "Keep it up!";
				else if (this.score < 100) {
					text = "RAINBOW!";
					colour = getRandomColor();
				}
				else {
					text = "GODLIKE!";
					colour = getRandomColor();
				}

				context.fillStyle = colour;

				context.textAlign = "left";
				context.font = "bold " + totalFont + "px Roboto, Helvetica Neue, Helvetica, Arial, sans-serif";
				context.fillText(this.score, 40, totalFont - 15);

				var middle = context.measureText(this.score).width / 2 + 40;
				var vPos = totalFont + 10;

				context.font = "bold 20px Roboto, Helvetica Neue, Helvetica, Arial, sans-serif";
				if (nukeCount >= nukeCountReq) {
					context.fillStyle = "#FF0000";
					context.fillText("NUKE ready", middle - context.measureText("NUKE ready").width / 2, vPos);
				}
				else {
					context.fillText("NUKE in: " + Math.ceil(nukeCountReq - nukeCount), middle - context.measureText("NUKE in: " + Math.ceil(nukeCountReq - nukeCount)).width / 2, vPos);
				}

				vPos += 20;


				context.fillStyle = colour;
				context.fillText(text, middle - context.measureText(text).width / 2, vPos);

				context.font = "20px Roboto, Helvetica Neue, Helvetica, Arial, sans-serif";

				context.fillText("Mouse:", 20, height - 60);
				context.fillText("Move", 90, height - 60);

				context.fillText("Z+X:", 20, height - 40);
				context.fillText("Shoot", 90, height - 40);

				context.fillText("C:", 20, height - 20);
				context.fillText("Nuke (when available)", 90, height - 20);


				context.textAlign = "right";

				context.fillText("Made by Ashley Smith", width - 20, height - 20);
				context.font = "bold 20px Roboto, Helvetica Neue, Helvetica, Arial, sans-serif";
				context.fillText("Highscore: " + this.highScore, width - 20, height - 40);
			}
		}
	}

	window.requestAnimationFrame(updateGame);
	function updateGame() {
		if (gameEnabled) {
			// Check asteroids
			asteroidBelt.asteroids = asteroidBelt.asteroids.filter(function (asteroid) {
				var success = true;
				var laserHit = false;
				var laserNum = -1;
				for (var i = 0; i < player.lasers.length; i++) {
					if (Math.abs(Math.hypot(((asteroid.x) - player.lasers[i].x),((asteroid.y) - player.lasers[i].y))) < asteroid.radius) {
						laserNum = i;
						laserHit = true;
					}
				}
				if (laserHit) {
					player.lasers.splice(laserNum, 1);
					hud.inc();
					success = false;
				}

				if (success)
					if (Math.abs(Math.hypot(((asteroid.x) - (player.x - player.width / 2)),((asteroid.y) - (player.y - player.height / 2)))) < asteroid.radius + player.radius) {
						hud.reset();
						success = false;
					}
				return success;
			});

			// Update objects
			starfield.update();
			asteroidBelt.update(hud.score);

			player.update();

			// Draw everything and refresh
			draw();
			window.requestAnimationFrame(updateGame);
		}
	}

	function draw() {
		// Clear the window before drawing
		context.clearRect(0, 0, width, height);

		// Draw objects
		starfield.draw();
		player.draw();
		asteroidBelt.draw();
		hud.draw();
	}

	function getRandomColor() {
		var letters = '0123456789ABCDEF';
		var color = '#';
		for (var i = 0; i < 6; i++ ) {
			color += letters[Math.floor(Math.random() * 16)];
		}
    return color;
	}
};