Pong - The Game Runner
Sat, May 14, 2011- Introduction
- The Game Runner
- Bouncing Balls
- The Game Loop
- Collision Detection
- Computer AI
Game Runner Loop
The GameRunner is very generic. It provides some javascript pre-requisites (see below) and a rudimentary game loop:
- Initialize the runner
- Construct canvas front and back buffers
- Construct a game instance
- Start a 60fps loop
On each iteration of the loop:
- call
game.update()
- providing dt timer interval since last frame - call
game.draw()
- providing back buffer canvas context for drawing on - flip back and front buffers
- update frame rate statistics
And thats really all it does. You can find the demo here
Javascript Pre-Requisites
I want to build a framework that does not require any 3rd party libraries. Since these
games are going to be based on the HTML <canvas>
and only supported in modern browsers
there is no real need for including a full library like jQuery or prototype.js.
However, there are a few pre-requisites we are going to need:
- Canvas
- Function.bind
- Object.create
- Object.extend
- addEventListener
- DOMContentLoaded
- Image Loader
Canvas
We are building a game using the HTML5 <canvas>
element, so duh! we’re going to need an
HTML5 <canvas>
element! This is supported in all modern browsers, so should be no problem.
Older versions of IE usually require a 3rd party library (excanvas.js), but since IE9 has a native canvas I am going to simply drop support for older versions of IE.
Function.bind
This method is standard in ECMAScript 5. It is one of the most important methods in
javascript development and is used to ensure that instance methods used as callbacks
(e.g. event handlers) have the correct this
set. Its also used to curry arguments
when compositing methods.
This method is provided by most modern browsers, but is easy enough to provide for older browsers, a sample implementation is provided by mozilla
if (!Function.prototype.bind) {
Function.prototype.bind = function(obj) {
var slice = [].slice,
args = slice.call(arguments, 1),
self = this,
nop = function () {},
bound = function () {
return self.apply(this instanceof nop ? this : (obj || {}), args.concat(slice.call(arguments)));
};
nop.prototype = self.prototype;
bound.prototype = new nop();
return bound;
};
}
Object.create
Another ECMAScript5 standard encapsulates the construction of an object with a specific prototype.
Many attempts have been made to mimic OO class construction patterns in javascript, but in many cases it can be simpler to avoid these entirely and embrace javascripts prototypical nature.
Again, modern browsers will provide this method, but its easy enough to implement it ourselves when necessary:
if (!Object.create) {
Object.create = function(base) {
function F() {};
F.prototype = base;
return new F();
}
}
What’s missing from Object.create is the ability to pass arguments to some kind of constructor function. I like to add a wrapper Object.construct that provides this additional behavior on top of the standard Object.create
if (!Object.construct) {
Object.construct = function(base) {
var instance = Object.create(base);
if (instance.initialize)
instance.initialize.apply(instance, [].slice.call(arguments, 1));
return instance;
}
}
Object.extend
Not a standard, but typically provided by libraries such as jQuery or prototype. The ability to copy all of the properties of one object to another can be very useful on occasions.
if (!Object.extend) {
Object.extend = function(destination, source) {
for (var property in source) {
if (source.hasOwnProperty(property))
destination[property] = source[property];
}
return destination;
};
}
addEventListener
Of course, we need to be able to respond to DOM events. There are a number of established methods for supporting
older browsers, but since we are only supporting modern browsers with the <canvas>
we can be fairly sure that
these browsers support the standard addEventListener (yes, even IE supports it in IE9)
DOMContentLoaded
Knowing when the page is ready to load is also a solved problem with 3rd party libraries such as jQuery and prototype.js, but again, since we are only supporting modern browsers we can be fairly sure that these browsers support the DOMContentLoaded event (yup. IE9 supports this)
Image Loader
One issue <canvas>
based games will run into is that they cannot use images until those images are loaded. To ensure we
dont try to use an image until it has completed loading we need a helper method that will load multiple images and
make a callback when the last image has completed loading.
loadImages: function(sources, callback) { /* load multiple images and callback when ALL have finished loading */
var images = {};
var count = sources ? sources.length : 0;
if (count == 0) {
callback(images);
}
else {
for(var n = 0 ; n < sources.length ; n++) {
var source = sources[n];
var image = document.createElement('img');
images[source] = image;
Game.addEvent(image, 'load', function() { if (--count == 0) callback(images); });
image.src = source;
}
}
},
More…
- Introduction
- The Game Runner
- Bouncing Balls
- The Game Loop
- Collision Detection
- Computer AI
You can find the final game here and the code is here