GameJS: A 2d game development framework in JavaScript

October 9th, 2008 by Tommy Maintz

A little while ago I decided to learn something about game development. Being a die-hard web developer, coding games was something completely new, so I started looking for a good language to learn game development in. Obviously C++ is the most popular language for creating commercial high-end games, but the OpenGL and DirectX API’s were both really hard to understand, especially in an unfamiliar language.

I then came across a book about developing games with Microsoft’s XNA Game Framework using either C# or VB. I quickly learned the C# syntax, which I found out is easy to learn for an (OO) JavaScript developer, and within hours I already had textures flying over my screen controlled by my keyboard and the basics of a simple game.

I then started thinking about how cool it would be to create games just as easily in JavaScript and decided to port the XNA Framework over to JavaScript using Canvas as the rendering device. I quickly had a lot of fun doing so, and learned much about the internals of game development by reverse-engineering the XNA API to JavaScript.

I decided to name the framework GameJS, since I got alot of inspiration from the ExtJS source code. I have always been a fan of ExtJS and the way it is structured.

Performance

The result is pretty cool. I wrote a Tetris clone as a test case while developing the framework.

Obviously JavaScript and Canvas isn’t the best combination to write browser games with. Flash will be the best platform for this for a long time. But this was all about fun, experimenting with new HTML features and learning game development. In Tetris a high FPS isn’t really important, but with a filled game field, which already is 10 x 18 textures every frame, I still managed to get 25fps in FF and Chrome. This means that if you would use the framework to write games like Pacman and Super Mario, you would probably get 50+ fps on a decent computer, since they both probably have less then half the amount of textures at the same time on the screen.

The use of Canvas

The framework relies heavily on HTML’s Canvas tag. This means that the framework currently only works in the latest Safari, Chrome, FF and Opera versions. Techincally it could work in IE using IECanvas I guess, but the performance would be so bad that I'm not even going to try it. I won’t go into too much technical canvas details in this post, since I plan to create a proper documentation for the framework, and a detailed step-by-step guide on how to create a game with it. The conclusion is that Canvas is awesome, and opens a lot of possibilities. If there will be a decision on the 3D context API, I think it will be fairly straightforward to implement this into the framework, making hardware accelerated 3D games in the browser a real possibility.

Some classes to look at

I didn’t compress and concatenate the source files, so you guys can easily browse through them. A few classes I suggest you look at if you are interested are:

GameJS.framework.Game - This is the main game class you extend when creating the game. It has the following methods which you have to override: initialize, loadContent, update and draw. This is all very similar to the XNA framework. Tetris.js is an example of how to extend this class.

GameJS.content.ContentManager - This class handles the asynchronous loading of resources saving you some headaches. The following code loads a new texture which can be drawn in the games draw() method:

loadContent: function() {
    // set the screen rect
    this.screenRect = new Rectangle(
        0, 0,
        this.screenWidth,
        this.screenHeight
    );
 
    // Create the background texture. The third argument argument
    // makes this texture is not redrawn every frame (gives
    // performance boost since the background doesn't change)
    this.backgroundTexture = new Texture(
        this.graphics,
        this.content.load('Textures/BackgroundTexture.png'),
        false
    );

GameJS.graphics.GraphicsDevice - This file sets up the main canvas. It also manages the Z-buffering, and has a method that creates a new resource context which individual textures can use. You can easily change its properties. A simple example:

constructor: function() {
    var ds = this.graphics.deviceSettings;
 
    ds.screenWidth = this.screenWidth;
    ds.screenHeight = this.screenHeight;
    ds.target = document.getElementById('tetris-container');
    ds.fullScreen = false;
    ds.applyChanges();

GameJS.graphics.SpriteBatch - This class acts as a wrapper around the canvas element. It has a draw method which allows you to draw a texture to the graphicsDevice. You can pass it a destination and source rectangle. Code example:

draw: function(gameTime) {
    // clear the device
    this.graphics.graphicsDevice.clear();
 
    var spriteBatch = new GameJS.graphics.SpriteBatch(this.graphics);
    spriteBatch.begin();
 
    // Draw the background
    spriteBatch.draw(this.backgroundTexture, this.screenRect);
 
    // Draw the gamefield.
    spriteBatch.draw(this.gameFieldTexture, this.gameFieldRect);

GameJS.input.Keyboard and GameJS.input.KeyboardState - These classes take handle the keyboard input. Since JavaScript is an event based language and a game cycle is something continues, the framework takes care of storing the pressed keys. This looks something like the following:

update: function(gameTime) {
    // Get the current input state.
    var keyboardState = this.keyboard.getState();
    if(this.isGamePaused) {
        if (keyboardState.isKeyPressed(Keys.ENTER)) {
            this.isGamePaused = false;
        }
    }

Obviously the framework contains a lot of other features. If you are interested, I suggest you browse the source files to learn more about the internals, or wait till I can find the time to create a proper documentation and guide.

Final notes

As you can see the framework doesn’t support sound yet. This would be easy to do if you use Flash as the audio player. But since the whole idea behind this framework is to use only HTML and Javascript, I think I will wait with implementing sound until some more browsers properly implement HTML 5’s Audio object.

Another thing that I need to work on is the drawing of strings to the canvas. Canvas doesn’t support the drawString method yet, and the performance of the alternative I currently use (strokeText.js) is quite bad.

Download

You can download the source code for Tetris (which includes the GameJS library itself) here. All the code will be released under the LGPL license.

3rd party libraries used