Build pong html5 video game – part III

Third part to make videogame with html5 javascript. Today, the ball will move and bounce on the field walls.

So fast…

You want to go fast :
– player animation with keyboard : ici.

Before reading this post

Read the first post at the first episode of this tutorial.
Read the second post at the second episode of this tutorial.

Le principe

To move the ball, you must change data position on the canvas :

For horizontal move from right to left, only x data position decrements.
For horizontal move from left to right, only x data position increments.
For vertical move from top to bottom, only y data position increments.
For vertical move from bottom to top, only y data position decrements.

To move the ball, you must increment or decrement on the both axis.

Le code

The ball object defined in previous post includes 2 properties to set position on html5 canvas : posX et posY :

[javascript]
var game = {
…..
ball : {
width : 10,
height : 10,
color : « #FFFFFF »,
posX : 200,
posY : 200
},

init : function() {
…..
[/javascript]

Value variation of this properties posX and posY make ball animation.

Who says movement, says speed.

So, for that, we add a new property to set speed.

[javascript]
var game = {
…..
ball : {
width : 10,
height : 10,
color : « #FFFFFF »,
posX : 200,
posY : 200,
speed : 1
},

init : function() {
…..
[/javascript]

The speed value is an increment value in pixels applied to ball to all display refresh.

Bigger is the value, bigger is the speed.

But, when you make test with high value, you see bad game display.

With the value 1, ball moves to bottom and right screen.

You need add a new method or function tom ove the ball in the javascript ball object.

This function changes the ball position with 2 new properties directionX and directionY.

The properties directionX and directionY use 2 values to set the movement on axis X and Y.

To move to right on the screen on X axis, directionX value is 1.
To move to left on the screen on X axis, directionX value is -1.
To move to bottom the screen on Y axis, directionY value is 1.
To move to top on the screen on Y axis, directionY value is -1.

[javascript]
var game = {

ball : {

move : function() {
this.posX += this.directionX * this.speed;
this.posY += this.directionY * this.speed;
},
}

}
[/javascript]

However, it’s not enough because you must refresh the display when the ball changes position. Simple, you just recall existing displayBall function.

[javascript]
displayBall : function() {
game.display.drawRectangleInLayer(this.playersBallLayer, this.ball.width, this.ball.height, this.ball.color, this.ball.posX, this.ball.posY);
},
[/javascript]

For easy reading code, inside namespace javascript game.js, another called moveBall calls this functions :

[javascript]
var game = {

moveBall : function() {
this.ball.move();
this.displayBall();
},

}
[/javascript]

If you keep this function with any changes, the ball moves to bottom and right of the screen game and disappears. The ball must bound on the wall.

Make bounces is easy :
– when the ball is on the right of the screen (if his value exceeds the screen game width), we reverse his direction (directionX value must be reverse);
– for the left of the screen, it’s same (if his value is less than 0);
– when the ball is on the bottom of the screen (if his value exceeds the screen game height), we reverse his direction (directionY value must be reverse);
– for the top of the screen, it’s same (if his value is less than 0).

Finally, bounce code is attached to ball objet :
[javascript]
var game = {

ball : {

bounce : function() {
if ( this.posX > game.groundWidth || this.posX < 0 )
this.directionX = -this.directionX;
if ( this.posY > game.groundHeight || this.posY < 0 )
this.directionY = -this.directionY;
},
}

}
[/javascript]

And you call from moveBall function :
[javascript]
var game = {

moveBall : function() {
this.ball.move();
this.ball.bounce();
this.displayBall();
},

[/javascript]

And you call moveBall function from the main function :
[javascript]

var main = function() {
// le code du jeu
game.moveBall();
requestAnimId = window.requestAnimationFrame(main); // rappel de main au prochain rafraîchissement de la page
}

[/javascript]

If you run javascript program now, you can see a trail after the ball.

Why trail ? Because screen game is not refresh. You must erase all contents in the ball layer, and display all items. And so on.

You add a new method to erase all items in the layer (inside layer object) :
[javascript]

layer : {
name : «  »,
canvas : «  »,
context2D : «  »,
posX : null,
posY : null,
width : «  »,
height : «  »,
backgroundColor : «  »,
zIndex : «  »,

clear : function() {
this.context2D.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
},

[/javascript]

And you add a erase layer function in the game namespace :
[javascript]
var game = {

clearLayer : function(targetLayer) {
targetLayer.clear();
}

[/javascript]

To finish, you call erase functio from game namespace in the main loop :
[javascript]
var main = function() {
// le code du jeu
game.clearLayer(game.playersBallLayer);
game.moveBall();
requestAnimId = window.requestAnimationFrame(main); // rappel de main au prochain rafraichissement de la page
}
[/javascript]

THe ball moves but players are erase :

Players and ball are displayed in the same layer, so clearLayer function must erase also players.
And you must display also players, with the displayPlayers function from game namespace :
[javascript]
var main = function() {
// le code du jeu
game.clearLayer(game.playersBallLayer);
game.displayPlayers();
game.moveBall();
requestAnimId = window.requestAnimationFrame(main); // rappel de main au prochain rafraichissement de la page
}
[/javascript]

To see live code, click onr Pong

In the next step, we animate players, see on ici.

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

Le source javascript complet :
game.html
[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 principale au rafraichissement de la page
}

var main = function() {
// le code du jeu
game.clearLayer(game.playersBallLayer);
game.displayPlayers();
game.moveBall();
requestAnimId = window.requestAnimationFrame(main); // rappel de main au prochain rafraichissement de la page
}

window.onload = initialisation; // appel de la fonction initialisation au chargement de la page

// fin du code isolé
})();
</script>
</html>
[/html]

game.js
[javascript]
var game = {

groundWidth : 700,
groundHeight : 400,
netWidth : 6,
groundColor : « #000000 »,
netColor : « #FFFFFF »,

groundLayer : null,
scoreLayer : null,
playersBallLayer : null,

scorePosPlayer1 : 300,
scorePosPlayer2 : 365,

ball : {
width : 10,
height : 10,
color : « #FFD700 »,
posX : 200,
posY : 200,
directionX : 1,
directionY : 1,
speed : 1,

move : function() {
this.posX += this.directionX * this.speed;
this.posY += this.directionY * this.speed;
},

bounce : function() {
if ( this.posX > game.groundWidth || this.posX < 0 )
this.directionX = -this.directionX;
if ( this.posY > game.groundHeight || this.posY < 0 )
this.directionY = -this.directionY;

}
},

playerOne : {
width : 10,
height : 50,
color : « #FFFFFF »,
posX : 30,
posY : 200
},

playerTwo : {
width : 10,
height : 50,
color : « #FFFFFF »,
posX : 650,
posY : 200
},

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);

this.scoreLayer = game.display.createLayer(« score », this.groundWidth, this.groundHeight, undefined, 1, undefined, 0, 0);
game.display.drawTextInLayer(this.scoreLayer , « SCORE », « 10px Arial », « #FF0000 », 10, 10);

this.playersBallLayer = game.display.createLayer(« joueursetballe », this.groundWidth, this.groundHeight, undefined, 2, undefined, 0, 0);
game.display.drawTextInLayer(this.playersBallLayer, « JOUEURSETBALLE », « 10px Arial », « #FF0000 », 100, 100);

this.displayScore(0,0);
this.displayBall(200,200);
this.displayPlayers();
},

displayScore : function(scorePlayer1, scorePlayer2) {
game.display.drawTextInLayer(this.scoreLayer, scorePlayer1, « 60px Arial », « #FFFFFF », this.scorePosPlayer1, 55);
game.display.drawTextInLayer(this.scoreLayer, scorePlayer2, « 60px Arial », « #FFFFFF », this.scorePosPlayer2, 55);
},

displayBall : function() {
game.display.drawRectangleInLayer(this.playersBallLayer, this.ball.width, this.ball.height, this.ball.color, this.ball.posX, this.ball.posY);
},

moveBall : function() {
this.ball.move();
this.ball.bounce();
this.displayBall();
},

displayPlayers : function() {
game.display.drawRectangleInLayer(this.playersBallLayer, this.playerOne.width, this.playerOne.height, this.playerOne.color, this.playerOne.posX, this.playerOne.posY);
game.display.drawRectangleInLayer(this.playersBallLayer, this.playerTwo.width, this.playerTwo.height, this.playerTwo.color, this.playerTwo.posX, this.playerTwo.posY);
},

clearLayer : function(targetLayer) {
targetLayer.clear();
}

};
[/javascript]

game.display.js
[javascript]
game.display = {
container : «  »,

layer : {
name : «  »,
canvas : «  »,
context2D : «  »,
posX : null,
posY : null,
width : «  »,
height : «  »,
backgroundColor : «  »,
zIndex : «  »,

clear : function() {
this.context2D.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
},

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.backgroundColor = 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);
},

drawTextInLayer : function(targetLayer, text, font, color, x, y) {
targetLayer.context2D.font = font;
targetLayer.context2D.fillStyle = color;
targetLayer.context2D.fillText(text, x, y);
}

}
[/javascript]

Posté dans html5Tagged canvas, canvas html5, html5 videogame  |  1 commentaire

Une réponse à "Build pong html5 video game – part III"

Répondre