JavaScript Pong
Written by Mike James   
Friday, 24 December 2010
Article Index
JavaScript Pong
Ball and bats
Timer for animation
Enhancements

Who needs HTML5 - it should come as no surprise that you don't need to wait for HTML5 to write games. All you need is Dynamic HTML, i.e. HTML4 and JavaScript. This project builds a fun demo in the form of classic Pong - if you don't have the time to code it yourself you can just play with it.

Banner

 

Inspired by the account of how Nolan Bushnell created Pong this project implements a classic looking version of the classic game using nothing but JavaScript and some object-oriented ideas that come under the general label of Spartan Ajax.

 

If you would like to see the program in action before finding out how it all works then click here. You also need to know that the A and Z keys move the left bat and the K and M keys move the right bat and the game is over when either side gets to nine.

 

finished

 

The whole idea of Spartan Ajax is to get rid of HTML, or any markup language, and return the act of programming to the creation of procedural or imperative code. Its basic methodology is very simple – use the DOM as if it was JavaScript's own object system and make as little distinction between a JavaScript object and a DOM object as possible.

 

Of course this leaves open the possibility of many different coding styles and much of the following example could be written in many different ways – in particular there is no reason not to use an established JavaScript library such as JQuery or DOJO and in most cases this would be the best way to go. However for an example, working without the help of a class library has the advantage of simplicity and directness.

 

In general we can’t get rid of 100% of the HTML and apart from a purists approach there really is no need too. Markup is fine doing the job it was originally intended for i.e. to format static objects. In this case the only HTML we need is:

<!DOCTYPE html PUBLIC 
"-//W3C//DTD XHTML 1.0
Transitional//EN"
"http://www.w3.org/TR/
xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns=
"http://www.w3.org/1999/xhtml">
<head>
<title>Pong</title>
<script type="text/javascript"
src="/pong.js">
</script>
</head>
<body>
</body>
</html>

This simply loads the JavaScript file which then does all the work. From this point on we can forget HTML and concentrate on the code – this is the advantage of Spartan Ajax.

Run

The program starts off declaring a few global variables – just the height and width of the playing area:

var h=200;
var w=400;

Next we wait until all of the JavaScript has been loaded and everything is ready to go before calling the function which starts everything off. We could create an application object at this point and an associated run method but it's easy just to create a run function:

run = function() {

The first task of the run is to create a Court object – basically just a large black block. In fact creating blocks of colour is one of the very fundamental things we keep on doing so it's worth defining an object to do the job:

CBlock = function(position, size, c) {
var DOMObj =
document.createElement("div");
DOMObj.style.position = "absolute";
DOMObj.style.width = size.w + 'px';
DOMObj.style.height = size.h + 'px';
DOMObj.style.top = position.y + 'px';
DOMObj.style.left = position.x + 'px';
DOMObj.style.backgroundColor = c;
return DOMObj;
}

This is the archetypal Spartan Ajax object. It creates a DOM object – a div in this case – sets its properties and then returns a reference to the new object. Notice the use of associative arrays to pass the position as position.x and position.y and size as size.h and size.w.

Now that we have the CBlock object the CCourt object is easy to construct:

CCourt = function(size) {
var DOMObj =
new CBlock({x:10,y:10},size, "black");
return DOMObj;
}

All we have to do is create a black block with its top left-hand corner at 10,10 and of the specified height and width.

Returning to the Run function we can now create the instance of the CCourt object and continue with the construction of the game:

run = function() {
Court = new CCourt({h:h,w:w});
document.body.appendChild(Court);

The result is, as promised, just a black rectangle:

fig1

To make the Court display we have to add it to the DOM using appendChild – notice however that we can carry on using Court as if it was a standard JavaScript object.

 

To make the Court look a little more like something you could play on let’s add a net. This makes use of the CBlock object to draw a vertical dashed line down the middle of the court:

CNet = function(position, 
size, nodash) {
DOMObj = new CBlock(position,
size, "black");
DOMObj.p = position;
DOMObj.s = size;
for (i = 0; i < nodash; i++) {
dash = new CBlock(
{x: 0, y:i * 2 * DOMObj.s.h /
(2 * nodash)}, {h:size.h/
(2*nodash),w: size.w}, "white");
DOMObj.appendChild(dash);
}
return DOMObj;
};

There are a few new techniques used. The first CBlock object is used as a container for the dashed line in the sense that all of the other CBlocks are added to it as child DOM objects. This has the advantage that you can position, and generally work with, the new CNet object as a if it was a single object rather than a collection of dashes. It also allows you to use co-ordinates that are relative to the container.

Also notice the use of associative arrays for the position and size parameters and the way that these are stored in two new properties added to the DOM object – yes you can do this. The for loop simply creates a number of dash objects and adds them to the container.

Now that we have the CNet object we can create a suitable instance in the Run function which now reads:

run = function() {
Court = new CCourt({h:h,w:w});
document.body.appendChild(Court);

Net = new CNet(
{x: w / 2, y: 0},
 {h: h,w: 3},
 20);
Court.appendChild(Net);

Notice the way that the new Net object is added to the Court object as a DOM child object. Now we have a black rectangle to act as the court and a dotted line displayed.

fig2

Banner

<ASIN:0470452021>

<ASIN:0596517742>

<ASIN:0470344725>



Last Updated ( Sunday, 10 July 2022 )