Build pong html5 video game




 

You have dream that you are a html5 and javascript video game developer. Now, your dream can become real. This first post start a new series about Pong and how to build a video game with html5 and javascript. It’s seems easy. But to begin, it’s a good choice, mostly if you are rookie. French version.

 

To Internet Explorer users

Internet Explorer is not the better HTML5 navigator. For the best experience in html5 game development, Google Chrome is a good choice: it’s the faster and support HTML5 news.

 

The show

If you want to go faster (it’s in french):
– set game environment (field, rackets, ball and score) : here;
– ball animation : here;
– racket control with keyboard : here.

 

Before to begin

– know what is html;
– basic knowledge of javascript;
– reading posts Set game development and Canvas tutorial.

 

Pong project tree

Like any development, you must create tree directories for html5 video game components.

Let’s begin by creating game project directory named Pong. It will including all of the elements of html5 video game.

In Pong directory, do make:
js directory including javascript files and libraries;
img directory including images files (background, sprites…);
sound directory including song files;
music directory including music files;
css directory including css files.

Arborescence Projet

Html file of the game pong.html is building at the project root directory.

 

Basic code

The basic code includes:
– a game set function;
– a function called at the screen refresh (it’s the loop game);
– a javascript namespace called game.

Edit pong.html file, and add next code:

<script>
(function () {
  // start insulated code
  var requestAnimId;
 
  var set = function() {
    // set code
    requestAnimId = window.requestAnimationFrame(main); // first call of min function at the screen refresh
  }
 
  var main = function() {
    // game code 
    requestAnimId = window.requestAnimationFrame(main); // main recall at the next screen refresh
  }
 
  window.onload = set; // call set function on page loading

  // end insulated code
})();
</script>

I don’t explain this code. To see more, read post Set video game development.

For a good code structure, I advise javascript namespaces using.

Javascript namespace doesn’t exist like C# or Java. But you can use simple object instead of pure namespace. To see more, read post Les namespace javascript.

In your case, create a game namespace dedicated to video game, like this :

var game = {

};

Yes, it’s a json object.

 

Make Pong game environment

Components of game environment

The project is created. Now, you must implement the game environment including:
– the game field;
– the game score display;
– the ball;
– and the rackets.

Create this without animation. All of the components are statics.

An environnement splitted in 3 layers

3 html5 canvas:
– the first dedicated to the field: a black background with a net;
– the second dedicated to score display;
– the third and last dedicated to ball and rackets animation.

Why 3 html5 canvas instead of one ?
– optimization : with one html5 canvas, you must refresh all of the game elements like the rackets, ball, score and net at the screen refresh;
– conceptual : group the same nature element in a dedicated html5 canvas.

To see more on html5 canvas, read post Canvas tutorial.

For easy reading code, a good practice is to build a dedicated object called html5 layer that you can clone as you like from javascript prototype object.

The layer including html5 canvas is easy to use in the javascript video game context.

The Layer javascript prototype object

First, create a subnamespace named display in the game.display.js file. This javascript namespace includes all of th display functions.

The code:

game.display = {
}

Add layer object to javascript namespace:

game.display = {
  layer : {
  }
}

Now add the next properties:
– name by the name property;
html5 canvas by the canvas property;
– 2D context (from canvas) by the context2D property;
– plan position les propriétés by the posX et posY properties;
– dimensions by the width et heigth properties;
– background color by the backgroundColor property;
– layer position in the layers list by the zIndex property.

The code:

game.display = {
  layer : {
    name : "",
    canvas : "",
    context2D : "",
    posX : null,
    posY : null,
    width : "",
    height : "",
    backgroundColor : "",
    zIndex : ""
  }
}

Next, a javascript namespace included to html5 layer with all the parameters needed to initialize. This constructor creates html5 canvas from the in parameters.

Some details:
– drawing operations can’t not be called from html5 canvas, but from canvas 2D context;
getContext(‘2d’) function returns the canvas 2D context;
Layer object includes all of that (canvas and context2D properties);
createLayer function initialize all of that.

Like you can see, the constructor is a simple function that returns layer object.

createLayer : function(name, width, height, zIndex, backgroundColor, x, y) {
  var layer = Object.create(this.layer);

  layer.canvas = window.document.createElement("canvas");

  layer.canvas.id = name;

  if ( backgroundColor != undefined )
    layer.canvas.style.background = backgroundColor;

    layer.zIndex = zIndex
    layer.canvas.style.zIndex = zIndex;

    layer.width = width
    layer.canvas.width = width;

    layer.height = height
    layer.canvas.height = height;

    if ( x != undefined )
      layer.posX = x;

    if ( y != undefined )
      layer.posY = y;

    layer.context2D = layer.canvas.getContext('2d');

    return layer;
},

To make easy the layout or match some video game html5 elements like score, screen game or others, attach these to a container is a good idea. It will be easy to move container instead of every components one to one.

I advise you to add to display javascript namespace container property:

game.display = {
  container : "",
	
  layer : {
    name : "",
    canvas : "",
    context2D : "",
    posX : null,
    posY : null,
    width : "",
    height : "",
    backgroundColor : "",
    zIndex : ""
  },

  createLayer : function(name, width, height, htmlContainer , zIndex, backgroundColor, x, y) {
    var layer = Object.create(this.layer);

    layer.canvas = window.document.createElement("canvas");

    layer.canvas.id = name;

    if ( backgroundColor != undefined )
      layer.canvas.style.background = backgroundColor;

    layer.zIndex = zIndex
    layer.canvas.style.zIndex = zIndex;

    layer.width = width
    layer.canvas.width = width;

    layer.height = height
    layer.canvas.height = height;

    if ( x != undefined )
      layer.posX = x;

    if ( y != undefined )
      layer.posY = y;

    layer.canvas.style.position = "absolute";
    if ( x != undefined )
      layer.canvas.style.left = x;

    if ( y != undefined )
      layer.canvas.style.top = y;

    if ( htmlContainer != undefined ) {
      htmlContainer.appendChild(layer.canvas);
    } else {
      document.body.appendChild(layer.canvas);
    }

    layer.context2D = layer.canvas.getContext('2d');

    return layer;
  }
}

In code below, note the constructor has a new parameter htmlContainer. With the next code, html5 canvas is including to the container:

game.display = {
    ......
    if ( htmlContainer != undefined ) {
      htmlContainer.appendChild(layer.canvas);
    } else {
      document.body.appendChild(layer.canvas);
    }
    ......
}

If htmlContainer is not defined, html5 canvas is including to html root document document.body.

First layer : the field

From Layer object defined, you can create dedicated layer to the field with black background and a vertical line is drawing in the middle, like this:

The field parameters are:
– the field size, for example 800 by 600 pixels;
– net width, for example 6 pixels;
– field color, black for this game;
– net color, white for this game.

Add 5 properties at the begin of the game namespace:

var game = {
  groundWidth : 700,
  groundHeight : 400,
  groundColor: "#000000",
  netWidth : 6,
  netColor: "#FFFFFF"
};

La création du terrain fait partie de l’initialisation du jeu et ne sera exécuté qu’une seule fois, pourquoi ne pas créer une fonction dédiée à l’initialisation ?

var game = {
  groundWidth : 700,
  groundHeight : 400,
  groundColor: "#000000",
  netWidth : 6,
  netColor: "#FFFFFF",

  init : function() {
  }

};

Now, add a Layer object for the field from init function of namespace game.

var game = {
  groundWidth : 700,
  groundHeight : 400,
  groundColor: "#000000",
  netWidth : 6,
  netColor : "#FFFFFF",

  groundLayer : null,

  init : function() {
    this.groundLayer = game.display.createLayer("terrain", this.groundWidth, this.groundHeight, undefined, 0, "#000000", 0, 0); 
  }

};

As is, you have a black layer. It remains to add the white net by drawing white rectangle.

You just add rectangle draw function drawRectangleInLayer in namespace javascript display :

game.display = {
  container : "",
	
  layer : {
    .....
  },

  createLayer : function(name, width, height, htmlContainer , zIndex, backgroundColor, x, y) {
    .....
  },

  drawRectangleInLayer : function(targetLayer, width, heigth, color, x, y) {
    targetLayer.context2D.fillStyle = color;
    targetLayer.context2D.fillRect (x, y, width, heigth);
  }
}

Some details: the fillRect function (called from context2D) draws colored rectangle. The color is selected with fillStyle function.

The code:

var game = {
  groundWidth : 700,
  groundHeight : 400,
  groundColor: "#000000",
  netWidth : 6,
  netColor: "#FFFFFF",

  groundLayer : null,

  init : function() {
    this.groundLayer = game.display.createLayer("terrain", this.groundWidth, this.groundHeight, undefined, 0, "#000000", 0, 0); 
    game.display.drawRectangleInLayer(this.groundLayer, this.netWidth, this.groundHeight, this.netColor, this.groundWidth/2 - this.netWidth/2, 0);
  }

};

To finish, make it all in root file pong.html.

<html>
 <body>
 </body>
<script src="game.js"></script>
<script src="game.display.js"></script>
<script>
(function () {
  // start insulated code
  var requestAnimId;
 
  var main = function() {
    // le code de l'initialisation
    game.init();
    requestAnimId = window.requestAnimationFrame(main); // premier appel de main au rafraîchissement de la page
  }
 
  var main = function() {
    // le code du jeu
    requestAnimId = window.requestAnimationFrame(main); // rappel de main au prochain rafraîchissement de la page
  }
 
  window.onload = main; // appel de la fonction initialisation au chargement de la page
 
  // end insulated code
})();
</script> 
</html>

To see running code, click on Pong

That’s all for the field. It remains to draw score and rackets in episode 2 to follow here.

If you like this post, share.
If you some errors (like english) or you are happy, comment.

 
The code:
game.html

<html>
 <body>
 </body>
<script src="game.js"></script>
<script src="game.display.js"></script>
<script>
(function () {
  // début du code isolé
  var requestAnimId;
 
  var initialisation = function() {
    // le code de l'initialisation
    game.init();
    requestAnimId = window.requestAnimationFrame(main); // premier appel de main au rafraîchissement de la page
  }
 
  var main = function() {
    // le code du jeu
    requestAnimId = window.requestAnimationFrame(main); // rappel de main au prochain rafraîchissement de la page
  }
 
  window.onload = initialisation; // appel de la fonction initialisation au chargement de la page
 
  // fin du code isolé
})();
</script> 
</html>

game.js

var game = {
  groundWidth : 700,
  groundHeight : 400,
  groundColor: "#000000",
  netWidth : 6,
  netColor: "#FFFFFF",

  groundLayer : null,

  init : function() {
    this.groundLayer = game.display.createLayer("terrain", this.groundWidth, this.groundHeight, undefined, 0, "#000000", 0, 0); 
    game.display.drawRectangleInLayer(this.groundLayer, this.netWidth, this.groundHeight, this.netColor, this.groundWidth/2 - this.netWidth/2, 0);
  }
};

game.display.js

game.display = {
  container : "",
 
  layer : {
    name : "",
    canvas : "",
    context2D : "",
    posX : null,
    posY : null,
    width : "",
    height : "",
    backgroundColor : "",
    zIndex : ""
  },
 
  createLayer : function(name, width, height, htmlContainer , zIndex, backgroundColor, x, y) {
    var layer = Object.create(this.layer);
 
    layer.canvas = window.document.createElement("canvas");
 
    layer.canvas.id = name;
 
    if ( backgroundColor != undefined )
      layer.canvas.style.background = backgroundColor;
 
    layer.zIndex = zIndex
    layer.canvas.style.zIndex = zIndex;
 
    layer.width = width
    layer.canvas.width = width;
 
    layer.height = height
    layer.canvas.height = height;
 
    if ( x != undefined )
      layer.posX = x;
 
    if ( y != undefined )
      layer.posY = y;
 
    layer.canvas.style.position = "absolute";

    if ( x != undefined )
      layer.canvas.style.left = x;

    if ( y != undefined )
      layer.canvas.style.top = y;

    if ( htmlContainer != undefined ) {
      htmlContainer.appendChild(layer.canvas);
    } else {
      document.body.appendChild(layer.canvas);
    }

    layer.context2D = layer.canvas.getContext('2d');
 
    return layer;
  },
 
  drawRectangleInLayer : function(targetLayer, width, heigth, color, x, y) {
    targetLayer.context2D.fillStyle = color;
    targetLayer.context2D.fillRect (x, y, width, heigth);
  }
}

 

Posté dans html5, pongTaggé canvas, HTML5 canvas, html5 video game, javascript video game  |  Laisser un commentaire

Répondre

*