HTML5 Game Tutorial: Battle Pong
This is a simple HTML5 version of the classic game of pong. Play against the computer for as many levels as you can. The computer gets faster and more competitive the higher the level gets. The game can easily be customized to grow/shrink the paddles and the computer’s difficulty if you’re looking for a challenge after you’ve finished putting the tutorial together. You’ll need a current version of a browser (Chrome, Firefox) that supports HTML5 in order to complete this tutorial. Enjoy!
Download the Code or Fork on Plunker or Try the Working Version
Create the HTML File
The beauty of html5 is that you can program it using javascript. This makes your html file small and super simple. All we need to do is create a canvas for the game and then include the javascript file:
< script type="text/javascript" src="battlePong.js">
Create the Javascript File
/** * File: BattlePong.js * Purpose: HTML5 pong game * Author: Design1Online.com, LLC* Created: 6/7/2016 **/ //global game variables var game = { debug: true, canvas: null, canvasContext: null, frameRate: 1000, framesPerSecond: 30, fonts: { header: '30px Arial', regular: '15px Arial' }, colors: { net: 'gray', background: 'black', header: 'red', text: 'white' }, screens: { winner: false, startGame: true, levelUp: false, continue: false }, ball: { x: 50, y: 50, speedX: 10, speedY: 4, threshold: 35, radius: 10, color: 'blue' }, level: 1, pointsPerLevel: 3, player: { score: 0, lives: 5, paddle: { y: 250, thickness: 10, height: 100, color: 'green' } }, computer: { score: 0, paddle: { y: 250, thickness: 10, height: 100, speed: 6, color: 'red' } } }; /** * Start the game when the window loads **/ window.onload = function() { //init the canvas game.canvas = document.getElementById('battlePong'); //adjust canvas to window size game.canvas.width = window.innerWidth - game.computer.paddle.thickness; game.canvas.height = window.innerHeight; //create the context game.canvasContext = game.canvas.getContext('2d'); //add event listeners game.canvas.addEventListener('mousedown', mouseClickHandler); game.canvas.addEventListener('mousemove', mouseMoveHandler); //start buffering the screen setInterval(function() { buffer(); }, game.frameRate / game.framesPerSecond); }; /** * Figure out the player's mouse position **/ function mouseMoveHandler(e) { var mousePos = mousePosition(e); game.player.paddle.y = mousePos.y - (game.player.paddle.height / 2); } /** * Return the x,y coordinates of the mouse in * relation to the screen **/ function mousePosition(e) { var rect = game.canvas.getBoundingClientRect(); var root = document.documentElement; return { x: e.clientX - rect.left - root.scrollLeft, y: e.clientY - rect.top - root.scrollTop }; } /** * Handle mouse clicks **/ function mouseClickHandler(e) { if (game.debug) { console.log('mouseClickHandler()'); } if (game.screens.startGame) { if (game.debug) { console.log('Removing start screen'); } game.screens.startGame = false; } else if (game.screens.continue) { if (game.debug) { console.log('Removing start screen'); } game.screens.continue = false; } else if (game.screens.levelUp) { if (game.debug) { console.log('Removing level up screen'); } game.screens.levelUp = false; } else if (game.screens.winner) { resetGame(); if (game.debug) { console.log('Removing winner screen, showing start screen'); } game.player.score = 0; game.computer.score = 0; game.screens.winner = false; game.screens.startGame = true; } } /** * Start the game **/ function startGame() { if (game.debug) { console.log('Starting game...'); } if (game.player.lives <= 0) { game.screens.winner = true; } game.ball.speedX = -game.ball.speedX; game.ball.x = game.canvas.width / 2; game.ball.y = game.canvas.height / 2; } /** * Move the ball and the computer mouse paddle **/ function move() { var deltaY = 0; //move computer paddle var center = game.computer.paddle.y + (game.computer.paddle.height / 2); if (center < game.ball.y - game.ball.threshold) { game.computer.paddle.y = game.computer.paddle.y + game.computer.paddle.speed; } else if (center > game.ball.y + game.ball.threshold) { game.computer.paddle.y = game.computer.paddle.y - game.computer.paddle.speed; } //move ball game.ball.x = game.ball.x + game.ball.speedX; game.ball.y = game.ball.y + game.ball.speedY; //check for paddle collisions hitCollision(); if (game.ball.y < 0) { if (game.debug) { console.log('Inverting ball Y speed 1'); } game.ball.speedY = -game.ball.speedY; } if (game.ball.y > game.canvas.height) { if (game.debug) { console.log('Inverting ball Y speed 2'); } game.ball.speedY = -game.ball.speedY; } } /** * Check for ball/paddle collisions **/ function hitCollision() { //player paddle check if (game.ball.x <= 0) { if (game.debug) { console.log('player paddle collision check'); console.log('ball', game.ball); console.log('player paddle', game.player.paddle); console.log( 'hit or miss', game.ball.y > game.player.paddle.y, game.ball.y < (game.player.paddle.y + game.player.paddle.height + game.ball.radius) ); } if (game.ball.y > (game.player.paddle.y) && game.ball.y < (game.player.paddle.y + game.player.paddle.height + game.ball.radius) ) { game.ball.speedX = -game.ball.speedX; deltaY = game.ball.y - (game.player.paddle.y + game.player.paddle.height / 2); game.ball.speedY = deltaY * 0.35; } else { game.computer.score++; game.player.lives--; game.screens.continue = true; startGame(); } } //computer paddle check if (game.ball.x >= game.canvas.width) { if (game.debug) { console.log('player paddle collision check'); console.log('ball', game.ball); console.log('player paddle', game.computer.paddle); console.log( 'hit or miss', game.ball.y > game.computer.paddle.y, game.ball.y < (game.computer.paddle.y + game.computer.paddle.height + game.ball.height) ); } if (game.ball.y > (game.computer.paddle.y) && game.ball.y < (game.computer.paddle.y + game.computer.paddle.height + game.ball.radius) ) { game.ball.speedX = -game.ball.speedX; deltaY = game.ball.y - (game.computer.paddle.y + game.computer.paddle.height / 2); game.ball.speedY = deltaY * 0.35; } else { game.player.score++; //increase score //level up if (game.player.score > 0 && game.player.score % game.pointsPerLevel === 0) { game.player.lives++; //get another life game.level++; //level up game.computer.paddle.speed += 1.3; //increase computer paddle speed game.screens.levelUp = true; } else { game.screens.continue = true; } startGame(); } } } /** * Draw the game board **/ function drawBoard() { //draw the net for (var i = 0; i < game.canvas.height; i += 10) { drawRectangle(game.canvas.width / 2 - 1, i, 2, 1, game.colors.net); } //draw the score text var offset = 100; //set the header text var header = "BattlePong!"; game.canvasContext.fillStyle = game.colors.header; game.canvasContext.font = game.fonts.header; game.canvasContext.fillText(header, offset, 30); //set the colors and font style game.canvasContext.fillStyle = game.colors.net; game.canvasContext.font = game.fonts.regular; //set the score text var score = "Score: " + game.player.score; game.canvasContext.font = game.fonts.text; var scoreSize = game.canvasContext.measureText(score); game.canvasContext.fillText(score, offset + 5, 50); //set the lives text var lives = "Lives: " + game.player.lives; var livesSize = game.canvasContext.measureText(lives); game.canvasContext.fillText(lives, offset + scoreSize.width + 25, 50); //set the copyright text var copyright = "Games by design1online.com, LLC"; var copyrightSize = game.canvasContext.measureText(copyright); game.canvasContext.fillText(copyright, game.canvas.width - copyrightSize.width - offset/4, game.canvas.height - offset/4); //player paddle drawRectangle( 0, game.player.paddle.y, game.player.paddle.thickness, game.player.paddle.height, game.player.paddle.color ); //computer paddle drawRectangle( game.canvas.width - game.computer.paddle.thickness, game.computer.paddle.y, game.computer.paddle.thickness, game.computer.paddle.height, game.computer.paddle.color ); //ball drawBall(game.ball.x, game.ball.y, game.ball.radius, game.ball.color); } /** * Draw the ball **/ function drawBall(centerX, centerY, radius, color) { game.canvasContext.fillStyle = color; game.canvasContext.beginPath(); game.canvasContext.arc(centerX, centerY, radius, 0, Math.PI * 2, true); game.canvasContext.fill(); } /** * Draw paddle **/ function drawRectangle(leftX, topY, width, height, color) { game.canvasContext.fillStyle = color; game.canvasContext.fillRect(leftX, topY, width, height); } /** * Reset for a new game **/ function resetGame() { if (game.debug) { console.log('Resetting game...'); } game.level = 1; game.computer.paddle.speed = 6; game.player.score = 0; game.computer.score = 0; game.player.lives = 5; } /** * Draw the winner screen **/ function screenWinner() { var center = game.canvas.width / 2; var height = game.canvas.height / 2; var header = "Game Over!"; var score = "Score: " + game.player.score; //set the header text game.canvasContext.fillStyle = game.colors.header; game.canvasContext.font = game.fonts.header; var headerSize = game.canvasContext.measureText(header); game.canvasContext.fillText(header, center - headerSize.width/2, height); //set the score text game.canvasContext.fillStyle = game.colors.text; game.canvasContext.font = game.fonts.regular; var scoreSize = game.canvasContext.measureText(score); game.canvasContext.fillText(score, center - scoreSize.width/2, height + 25); } /** * Draw the continue screen **/ function screenContinue() { var center = game.canvas.width / 2; var height = game.canvas.height / 2; //set the header text var header = "Missed Ball!"; game.canvasContext.fillStyle = game.colors.header; game.canvasContext.font = game.fonts.header; var headerSize = game.canvasContext.measureText(header); game.canvasContext.fillText(header, center - headerSize.width/2, height); //set the info text var info = "Click anywhere to start the next ball"; game.canvasContext.fillStyle = game.colors.text; game.canvasContext.font = game.fonts.regular; var infoSize = game.canvasContext.measureText(info); game.canvasContext.fillText(info, center - infoSize.width/2, height + 25); } /** * Draw the level up screen **/ function screenLevelUp() { var center = game.canvas.width / 2; var height = game.canvas.height / 2; //set header var header = "Level " + game.level; game.canvasContext.fillStyle = game.colors.header; game.canvasContext.font = game.fonts.header; var headerSize = game.canvasContext.measureText(header); game.canvasContext.fillText(header, center - headerSize.width/2, height); //set the regular text color and font game.canvasContext.fillStyle = game.colors.text; game.canvasContext.font = game.fonts.regular; //set the level text var info = "Click anywhere to start the next ball"; var infoSize = game.canvasContext.measureText(info); game.canvasContext.fillText(info, center - infoSize.width/2, height + 25); } /** * Draw the start screen **/ function screenStartGame() { var center = game.canvas.width / 2; var height = game.canvas.height / 2; //set the header text var header = "BattlePong!"; game.canvasContext.fillStyle = game.colors.header; game.canvasContext.font = game.fonts.header; var headerSize = game.canvasContext.measureText(header); game.canvasContext.fillText(header, center - headerSize.width/2, height); //set the info text var info = "Click anywhere to start playing"; game.canvasContext.fillStyle = game.colors.text; game.canvasContext.font = game.fonts.regular; var infoSize = game.canvasContext.measureText(info); game.canvasContext.fillText(info, center - infoSize.width/2, height + 25); } /** * Buffer the screen **/ function buffer() { //black out the screen drawRectangle(0, 0, game.canvas.width, game.canvas.height, game.colors.background); //draw one if the screens if they're active if (game.screens.winner) { screenWinner(); return; } else if (game.screens.continue) { screenContinue(); return; } else if (game.screens.levelUp) { screenLevelUp(); return; } else if (game.screens.startGame) { screenStartGame(); return; } //playing the game move(); drawBoard(); }
Test Your File
Open your html file in a browser. Make sure that your javascript file is located in the same place. Voila! Now you can tweak and refine it to your hearts content.