TRPG in Javascript 1

[sandbox-demo url=”” width=”770″ height=”420″ class=”demo-iframe” github=”″]

This is the first post in a series exploring the development of a Turn-based, Tactical Role-Playing Game (TRPG) in the vein of Fire Emblem or Disgaea — Think chess with different pieces and Anime thrown in and you’ll have a pretty good idea. If you want the full run-down on what I’m doing, check out the Project Introduction.

With the first experiment, I stuck with the basics and simply set up a basic EaselJS stage and rendered out a sample of the game board background and grid. You can click the “Download JS” link above and try this yourself.

Let’s run down the code:

var canvas,             
    stage ,
    queue ,
    gridSquare = 25 ;

Here I’m setting up a few basic variables to store references to the canvas and stage elements, as well as the loading queue. I define the default size of tile in the gridSquare variable as 25 pixels.

As I talked about in the introduction, I’ve elected to not use jQuery for performance reasons, so I’m using window.onload rather than $(function(){}).

First, I populate my global variable,  initializing the CreateJS Stage object so that it’s drawing to my main canvas. You can think of the Stage object as a display list or a container of elements you want to render to the canvas.

canvas = document.getElementById( "game" ); // populate the global canvas var
stage = new createjs.Stage( canvas );       // populate the global canvas var
createjs.Ticker.setFPS( 24 );               // set frame rate to 24 FPS
createjs.Ticker.addListener( stage );       // set an event handler to update the stage

The Ticker is an object that is roughly equivalent to a setInterval or requestAnimationFrame loop. In this instance, the Ticker object calls stage.update() 24 times a second (or 24FPS).

The next part of the onload event was new to me, as the last time I worked with EaselJS there was no automated way of handling loading. PreloadJS and the LoadQueue class handle that now:

var manifest = [
    { src:"" , id:"gameboard" }
queue = new createjs.LoadQueue( false );
queue.addEventListener( "complete" , handleComplete );
queue.loadManifest( manifest );

Here, I’m creating a manifest of elements I want to load. For now it only holds a cropped version of the background using the id of “gameboard” which I’ll use later. I created a new instance of the LoadQueue, passing in false to tell the loader to use tags over XHR requests when possible. Why I’d need do this, I don’t know — it was simply a part of the docs and is something I’ll investigate.

I set a “complete” event handler that will fire when all elements in the manifest have been loaded and then tell the queue to begin loading.

function handleComplete()  {
    var img = queue.getResult( "gameboard" ) ,
        bitmap = new createjs.Bitmap( img );
    bitmap.x = bitmap.y = 0;
    stage.addChild( bitmap );
    drawGrid() ;

The handleComplete function is where I do all of the initialization of the game board visuals, demonstrating how drawing and animation work in CreateJS.

The Stage object is a reference to the Adobe Flash stage and serves as a keeper of stuff you want to render, like the game board. So for our little stub of a game, I grab the image data from the queue ( using that “gameboard” id set earlier ) and then creating a CreateJS Bitmap object. After setting the Bitmap’s position to ( 0, 0 ) , I  add it to the stage for rendering.

This is the heart of how EaselJS works: Add an element to the stage, then alter it’s properties. These changes are then drawn to the canvas when stage.update() is called transparently by the Ticker object once every frame (or tick), keeping your animation smooth.

Finally, I call drawGrid() a simple function that renders the grid lines on the page.

function drawGrid(){
    var grid = new createjs.Shape() ; createjs.Graphics.getRGB( 255, 255, 255 ) ) ;
    for( var i = gridSquare - 1 ; i < canvas.width ; i += gridSquare ){ i  , 0 , 1 , canvas.height );
    for( i = gridSquare - 1 ; i < canvas.height ; i += gridSquare ){ 0  , i , canvas.width , 1 );
    grid.alpha = 0.4 ;
    stage.addChild( grid ) ;

If you’ve done any pixel drawing in another language, this should be very familiar to you. Briefly, I create a new Shape object and in the first loop draw my vertical lines starting at gridSquare – 1 ( that’s 24px, in this instance),  and then one line every gridSquare pixels (25px). The next loop does the same thing, only horizontally. Then I set the transparency of the grid to 40% (0.4) so that the lines are simply a ghost on the game board. Add the shape to the stage, and the ticker will handle the rendering.

So at this point I have a fairly good base for building the game. I do see some things that will need to be improved.

  • First and foremost, I need to build in some methods for giving me performance metrics. It doesn’t have to be anything comprehensive, just something that says “this many milliseconds has expired.” I have to have some way to evaluate the performance of each feature as I add it to the game.
  • Next, I need to build this so it’s canvas dimension agnostic. If you’re viewing this on a smaller screen, you’ll notice that the canvas overlaps the right menu or continues right off screen. Some of this is to be expected, especially if you’re looking at this on a cell phone. But there should be an easy way of dealing with this.
  • The game board I’m using here is cropped to the size of the canvas. I’ve got a massive game board to move around on, need to build this so that the canvas serves as a view port and you can scroll.
  • It’s early yet, but I need to allow for touch events, rather than just keyboard and mouse. I’ll consider multi-touch at a MUCH later date.
  • My tools prevented me from using Backbone in this initial build so I couldn’t evaluate whether it was appropriate for a canvas/EaselJS project. I enjoy how it can be used to make my code easier to work with as well as it’s collection & data classes. Still, there’s nothing in it that I can’t live without.
  • The preloading manifest likely needs to be broken out into a separate method — it’ll get a lot more use in future versions of this experiment.

I must also mention that the background image is a cropped section from the work of Cartographer’s Guild member Pasis. The work is used with only implied (non-commercial, attribution) permission from the original post, so this may come down if Pasis isn’t okay with my use of his work. We’ll find out if/when I get in touch with him.

Next: Part 2 – OOP and the Gameboard & Cursor


Leave a Reply

Your email address will not be published. Required fields are marked *