Sunday, October 17, 2010

Animating the Canvas part 8: Splitting Image

Right now the library is good at drawing solid blocks. To be useful, however, better image support is needed. The one class that would make this library sufficient for the creation of games, which is the goal of this after all, would be an image layer that had support for image strips and image grids. Better yet, an image atlas since image strips and image grids are a subset of an image atlas. This is actually very simple to do.

An image atlas, for those who are not familiar with the term, is simply just a large image that contains smaller images. The idea here is that instead of dealing with a large number of image files, you instead only need to load one image and show portions of that image. This speeds up loading as you only need to request a single file instead of having to request multiple files from the server. It is also commonly used with 3D rendering but that is beyond the scope of this series.

What makes this class so easy to create is simply the fact that it inherits most of its functionality from the Layer class. JavaScript does not currently have support for subclasses so I make use of the inheritProperties function that was created earlier. As it is likely that the image layer will be used to display an entire image, the constructor simply contains the image to use. The portion of the image used is set to the entire image, though this can be changed any time allowing this class to be used as an image atlas.

BGLayers.ImageLayer = function(id, image)
{
    this.supr = new BGLayers.Layer(id, image.width, image.height);
    BGLayers.inheritProperties(this, this.supr);
   
    this.clip = new BGLayers.Rectangle(0,0, image.width, image.height);
    this.image = image;
}

To set the particular portion of the image that should be displayed, the setClip function sets the new portion of the image to be shown. This can be used for animation by simply having a strip or grid of frames and altering the portion being shown every frame.

BGLayers.ImageLayer.prototype.setClip = function(rect)
{
    this.clip.x = rect.x;
    this.clip.y = rect.y;
    this.clip.width = rect.width;
    this.clip.height = rect.height;
    this.addDirty(null);
}

The hard part comes with the drawing as the portion of the image within the clipping bounds. This has to be calculated. This is done in a similar way to the calculation of the real layer position but using the clipping portion of the image. In theory it is possible to just set the canvas clipping region and draw the whole image, but I have had some issues with clipping so figure it is safest to avoid clipping whenever possible. Besides, relying on clipping makes the assumption that the canvas implementation is actually efficiently written where as manually drawing just the clip guarantees that the minimum amount of drawing is being done.

BGLayers.ImageLayer.prototype.drawSelf = function(ctx, bounds)
{
    if (this.findRealPosition().intersects(bounds) == false)
        return;
    var rect = this.realPosition.getIntersection(bounds);
    var scaleX = this.clip.width / this.realPosition.width;
    var scaleY = this.clip.height / this.realPosition.height;
    var boundClip = new BGLayers.Rectangle(
                this.clip.x + (rect.x - this.realPosition.x) * scaleX,
                this.clip.y + (rect.y - this.realPosition.y) * scaleY,
                rect.width * scaleX,
                rect.height * scaleY);
    ctx.drawImage(this.image, boundClip.x, boundClip.y, boundClip.width, boundClip.height,
                rect.x, rect.y, rect.width, rect.height);
}

And that is all that is needed. Creating a new layer is that simple. The atlas functionality of this class should be adequate for most uses so already this library is useful. Still, while doing some debugging on my Tarot project, stepping through the drawing of things did help me notice a lot of inefficiencies in how the library works so I am planning on having an optimization pass. I also want to do a bit of fine tuning to the library to make it clearer what variables are private, even though JavaScript does not support private variables. I may be renaming some things and adding some functionality so there is no need to access private variables. If something is clearly private and somebody modifies it anyway breaking their program it is their problem.

Sunday, October 10, 2010

Animating the Canvas part 7: Dirty Knives

I forgot to mention last week that the source code for parts 6 though 8 is located at http://www.blazinggames.com/other/openLibrary/html5Libs. It is time to start dealing with overlap. This will all be handled by the addDirty function which adds a dirty rectangle to the list of dirty rectangles. As before, this function adds dirty rectangles to the root layer. This time, however, an additional three steps have been added to this process.

The first step is simply to go through the existing list and make sure that the rectangle to be added isn't already in the list. By in the list, we are checking to see if there is a rectangle in the dirty rectangle list that covers the rectangle being added. If there is, our work is done and we can return from the function. This code is simply a traversal of the dirty rectangle list with a call to a rectangle function called containsRect.

ContainsRect is a simple function that simply checks to see if a passed rectangle is contained within the rectangle. This is simply done by seeing if the top left corner is in the bounds of the rectangle. If it is then a check is made to see if the bottom right corner is in the rectangle. If it is, then the rectangle is contained.

If the first step does not eliminate the dirty rectangle, then a second pass through the dirty rectangle list is made. This time, we are seeing if the new dirty rectangle covers some of the rectangles in the list. If it does, those rectangles can be removed from the list. This is why having the ability to remove nodes from the dirty rectangle list is important.

The third part is a really large chunk of code which is a bit too big to dump here so if my explanation is not good enough please review the code. This pass is where we make sure that the dirty rectangle doesn't overlap other rectangles in the list of dirty rectangles. If there is an overlap, the rectangle gets split. The check to find an overlap is simply a traversal of the dirty rectangle list with the traversal being stopped if an overlap is detected.

        var overlap = null;
        nextDirty = this.dirtyList.nxt;
        while (nextDirty != null) {
            var bounds = nextDirty.rect;
            if (dirty.rect.intersects(bounds)) {
                overlap = bounds;
                nextDirty = null;
            } else
                nextDirty = nextDirty.nxt;
        }

If there is an overlap, the goal then becomes to divide the dirty rectangle. First, we see if there is overlap on the left side. If there is, we create a new rectangle that contains the left portion of the dirty rectangle up to the start of the overlap. This rectangle gets sent to the addDirty function so that it gets processed as there may be other overlaps that cause it to be split up further.

The dirty rectangle is then resized to have the dimensions without the sliced portion. At this point we check to see if there is a right overlap. If there is the rectangle is again sliced and addDirty is called for processing the right portion of the rectangle.

The same procedure is done for the top and bottom portions of the rectangle. However, with the bottom portion we do not need to adjust the size of the dirty rectangle because it will be contained by the overlap and can be discarded.

We now have the functioning dirty rectangle system I originally planned. Next week I will actually implement a custom image layer class. After that, I will either conclude this series and start work on a game or will optimise the code. I will decide next week.

Sunday, October 3, 2010

Animating the Canvas part 6: Linking Dirty Rectangles

While the code we have created so far is usable, the big problem with it is that there is a lot of redrawing as dirty rectangles may overlap each other. If you are dealing with only a small number of objects then this may not be a big deal. Still, my original plan was to subdivide dirty rectangles to eliminate overlap. As I started preparing to write the code to deal with this it became clear that arrays were not the ideal mechanism for dealing with this problem. Instead, I needed a linked list. My JavaScript reference has no mention of any type of linked list class in the standard library so I am going to create my own simple doubly linked list class. This is dirty-rectangle specific class right now though I see no reason why this couldn't be modified and extended to create a general purpose class if such a thing was desired.

Linked lists are a useful concept. They simply are a list of objects with each object in the list pointing to the next object in the list. The advantage this offers is that there is no size limits, it is easy to transverse from start to end, and objects can be easily inserted in the middle of the list. Removing an item from the list isn't difficult but does require knowledge of the previous item. Arrays contain splice and slice functions to do this, but these are problematic and probably extremely inefficient. I say probably because it would depend on how the arrays were implemented.

A linked list would probably suffice for my needs, but as one of the key things I need to do is remove objects from the middle of the list, a doubly linked list would be much more convenient. This is the same as a linked list but instead of just pointing to the next object in the list, they also point to the previous object. This means that no knowledge of other items in the list are needed to remove an item.

The creation of an element in the linked list is simple enough. It is, after all, just references to three objects. In the case of our dirty rectangle class, this is the rectangle that is dirty, the previous node and the next node. The nodes are set to null initially with null being used to determine the beginning and end of the list.

BGLayers.DirtyRect = function(rect)
{
    this.rect = new BGLayers.Rectangle(rect);
    this.prev = null;
    this.nxt = null;
}

Having a node is fine but by itself it is not that useful. To be useful, the node has to be added to a list. Adding to a list only requires a node to the list in which the item is being added to. A node can only belong to one list at a time so it will remove itself from any existing list. The node from the list that this node is being added to will be considered the previous element in the list. As the previous item in the list may already have a next item, the first step then is to take the previous node next element and make it the added nodes next element. The node being added to the list then becomes the next node for the previous node. Likewise, the previous node is the added nodes previous entry. At this point everything is correct with this node, but the next node is not pointing to the added node so if the next node is not null, its previous entry will have to be changed to the added node.

BGLayers.DirtyRect.prototype.addSelf = function(parent)
{
    if ( (this.prev != null) || (this.nxt != null) )
        this.removeSelf();
    this.prev = parent;
    this.nxt = parent.nxt;
    if (this.nxt != null)
        this.nxt.prev = this;
    parent.nxt = this;
}

Removing a node is actually very easy. If the previous node is not null, it's next node becomes the removed nodes next entry. Likewise, if the next node is not null then it's previous entry becomes the removed nodes previous entry. Finally, the previous and next entries for the removed node are set to null so that it is clear that this node is not part of a list.

BGLayers.DirtyRect.prototype.removeSelf = function()
{
    if (this.prev != null) {
        this.prev.nxt = this.nxt;
    }
    if (this.nxt != null)
        this.nxt.prev = this.prev;
    this.prev = null;
    this.nxt = null;   
}

Some implementations of linked lists will have a separate class for manipulating nodes which also controls the root node. If you were going to expand on my linked list code this would be a good idea. For BGLayers, I am simply creating a root node which is not an active part of the list. This is not the best solution but it is very easy to do and doesn't require more classes be written. I might do this for a future version of this library as I am starting to think it is the proper thing to do.

Traversing the list is very simple. My implementation of renderDirty is a good demonstration of doing this. It simply grabs the first real node from the root node and then uses a while loop to continue through the list while the next element is not null. If the list is empty, the root nodes next will be null causing the while loop to exit  immediately. Of course, the loop processes the dirty rectangles by calling render, and then removes the node from the list so the list will be empty at the end of this function.

BGLayers.Layer.prototype.renderDirty = function(ctx)
{
    var nextDirty = this.dirtyList.nxt;
    while (nextDirty != null) {
        var bounds = nextDirty.rect;
        this.render(ctx, bounds);
        var curDirty = nextDirty;
        nextDirty = curDirty.nxt;
        curDirty.removeSelf();
    }
}

Now that we have the dirty rectangle doubly linked list class functioning, next time we will get to the fun part of splitting rectangles.

Sunday, September 26, 2010

A Break for Bugs

I am going to delay the planned installment of Animating the Canvas this week. While I have made a lot of progress on the code and thought that I had the rest of this series finished, when using the code within my Tarot project, some bugs were uncovered. While I could continue the series anyway, as the planned topic for today would not have been related to the issue at hand, I have decided instead to take a brief break and discus testing.

Testing and debugging are an important part of programming. The testing requirements largely depend on the project. Being old-school, I tend to use my brain to do the bulk of my debugging. I try and think like the computer to figure out where the problem is and then isolate and solve the problem. I find this approach much faster than the second level of debugging, namely using a debugger. Firefox, thankfully, has an incredible debugger called firebug. Apple has pretty much cloned this tool for Safari. Still, as someone who uses multiple operating systems, I like the fact that Firefox is everywhere so tend to use that browser for my preliminary testing. Single stepping through a program can be very time-consuming but for some bugs it is a necessity.

The big trend now is something called unit testing. It is an approach that is really good and is something that I should be doing more of but as most my projects are small I don't. The idea here is that you write your tests before you write your code. The tests are usually written using some type of testing framework in mind. Because the tests are all automated, you simply need to run the tests before checking in code. The advantage to using this technique is that you know when you are done as all of your tests are successful. For game development, this is only a partial solution. You can test the subsystems that make up the game, but are still going to need human testing for a lot of the testing.

While unit testing is not the silver bullet a lot of people think, the automated tests do help you make progress if you have written them. If you have not and are debugging things, unit tests can still prove useful. Once you have isolated a bug, or started writing testing code to help find the bug, you will have automated tests that make sure you do not re-introduce the bug in the future. While I am sure there are countless JavaScript testing frameworks available, creating one is very simple. Here is the one I wrote after discovering my issues with the BGLayers library I am writing:

function addTestResult(group, desc, result)
{
    var testTable = document.getElementById('testTable');
    var rRow = testTable.insertRow(1);
    var resText;
    if ( result)
        resText = 'Test Passed';
    else
        resText = 'Test Failed';
    rRow.innerHTML = ''+group+''+desc+''+resText+'';
}

Yes, I could have searched out a much better one online, but was simply too lazy to. My own "framework" only took a few minutes to write. I am sure that as I continue to focus more on writing JavaScript, especially as I start larger projects,  finding a better library for unit testing will make sense. For now, my simple test function is adequate for my needs.

Sunday, September 19, 2010

Animating the Canvas part 5: Layers of Paint

Last week we covered the positioning of layers and how to get the real position of the layer. This week we are actually going to draw. To make this class very easy to extend, the drawing of the layer is broken into two separate functions. The drawSelf function simply draws the contents of the layer. No care is given to any children the layer may have. By doing this, we can isolate the drawing of the layer (if any) from dealing with children. This function takes a bounds parameter which indicates which portion of the layer needs to be drawn. The function first looks to see if the bounds that are being drawn are actually part of this layer. This is done by adding a new function to the Rectangle class:  intersects(rect). This is a very simple function that tests if two rectangles intersect with each other. Still, a lot of people seem to find the test confusing so lets go over it in detail:

First we want to make sure that the passed rectangle  is not left of the class rectangle. This is done by taking the class rectangles' x2 coordinate and comparing it to the passed rectangles' x coordinate. If x is greater than x2 is then obviously there can be no overlap so the condition will fail.
    if ( (this.x < (rect.x + rect.width)) &&

Next, we know that the passed rectangle is not to left of the class rectangle so we are now seeing if it is to the right of the rectangle. This can be done by seeing if the class rectangles' x2 coordinate is greater than the passed rectangles' x coordinate.
            ( (this.x + this.width) > rect.x) &&

At this point we know that there is potentially intersection along the x axis so we now need to examine the y axis. This is essentially the same as above except we are checking for top and bottom instead of left and right.

            (this.y < (rect.y + rect.height)) &&
            ( (this.y + this.height) > rect.y) )
        return true;
    else
        return false;

If there is some overlap, we want to get that overlap so a getIntersection function is added to the rectangle to perform this task. It is simply the interior most bounds so no detailed explanation should be necessary.

Once we know what portion needs to be drawn, we simply draws a rectangle in the colour that is contained in the backgroundColor property. Overridden classes may need to do more work to figure out what needs to be drawn and to insure that things are drawn within the clip, you may actually need to formalize the bounds by using canvas clipping operations. It may be a good idea to set a clipping region no matter what as the browser probably has very efficient clipping support so there should be very little overhead.

The other function used for drawing is the render function. This is a very simple function that simply calls the drawSelf function passing the bounds it was passed and then calls the render function for all of the children that belong to this layer.

There is one additional function for painting the display. The renderDirty function is a convenience function that simply calls render for each rectangle in the list of dirty rectangles.  This function will be discussed in a later part as while have a functional system right now, the dirty rectangle management needs to be overhauled to eliminate overlap. We will be starting on this work in the next part.

Sunday, September 12, 2010

Animating the Canvas part 4: Laying out Layers

As I am partially writing these classes for use with November's Tarot release, I am a lot further in the code than I would be if I was just working on this code Sunday afternoons (which is the plan for this blog from now on). I have been packaging up the source as it has reached logical development points but it will be a while before this series of articles catches up with the work. The source code is located at http://www.blazinggames.com/other/openLibrary/html5Libs.

With primitives started it is now time to get to the real code and start implementing the layers class. This class will be a base class for all of the other elements that get added to the canvas. The problem with this is that JavaScript does not currently support superclasses or inheritance. This is something that may come to a future version of JavaScript (ECMAScript version 6 unless it gets delayed like it did when such features were in ECMAScript version 4) but for now we have to manually perform the inheritance. While some browsers support a technique known as prototype chaining by exposing the __proto__ property, this is not always the case so manually copying the properties must be done for browser compatibility. A simple function can handle this making creating subclasses much easier, though at a bit of cost in efficiency and memory.

BGLayers.inheritProperties = function(child, supr)
{
    for (var property in supr) { 
        if (typeof child[property] == "undefined") 
            child[property] = supr[property]; 
    } 
}

The layers are loosely based on the layer classes that I created for Dozen Days of Words Episode 12: Morse Code but with the addition of dirty rectangle support and switching from absolute positions to relative positioning. Relative positioning adds a lot more flexibility for animation as any given layer only has to worry about it's position relative to it's parent. For this reason, a layer can be created with a width and a height which can, with the exception of the root (stage) layer, be any size as scaling will be done when the component is rendered onto the canvas.

The logical and real positions of the layer is dependent on the parent. This means that there should only be a single parent for a layer, though layers can have multiple children.  This means that when you add a child to a layer, that child is being assigned a new parent. If it already has a parent that parent is told that the child is being removed and the new parent becomes the parent. The addChild, removeChild, and setParent functions handle all this work. Note that these functions take advantage of the addDirty function to let the old and new parents know which part of the display has changed.

The addDirty function handles our dirty rectangle list, but at the moment is far from complete as I was more concerned with getting the code functional. Currently the addDirty function simply adds the dirty rectangle, expressed in real canvas coordinates, to the root layer. The root layer is simply the layer which does not have a parent. To find the layer, the parent is called until there is no parent. Right now no effort is being made to cull the list to eliminate overdrawing. This feature will be added in the future.

While for internal work the real size and location of the layer is not that important, for marking dirty rectangles and rendering them knowing the real location becomes vital. This is where the findRealPosition function comes into play. As this is such an important function, lets go over it in detail.

First, to speed things up, we don't want to constantly re-calculate this so we have a flag that lets us know if the real position is known and if so, we return the already calculated position. This means that when the logical position or parent layer position changes the flag has to be set to false so when the final code is put together the logical position information may be marked protected (sadly, there is no such thing as protected variables in JavaScript yet, so we have to go on the honour system).

    if (this.realPositionKnown)
        return this.realPosition;

If this is the root layer then it's logical position and size are the real thing. If it is not, then we need to get the real thing by getting the parent's real position by calling this function on the parent. If the parent is not the root layer it will call it's parent and so on until the real position can be determined.

    var parentPos = this.logicalPosition;
    var w = this.logicalSize.width;
    var h = this.logicalSize.height;
    if (this.parent != null) {
        parentPos = this.parent.findRealPosition();
        w = this.parent.logicalSize.width;
        h = this.parent.logicalSize.height;
    }

Knowing the real position of the parent then gives us the information we need to find our real position. This is done by determining how big we are logically compared to how big of an area we are in our parent's eyes. This results in scaling factors.

    var scaleX = parentPos.width / w;
    var scaleY = parentPos.height / h;

With the scaling factors known, we can simply calculate the position by multiplying the logical coordinates by the scale and adding the parent's position.

    this.realPosition.x = parentPos.x + this.logicalPosition.x * scaleX;
    this.realPosition.y = parentPos.y + this.logicalPosition.y * scaleY;
    this.realPosition.width = this.logicalPosition.width * scaleX;
    this.realPosition.height = this.logicalPosition.height * scaleY;
    this.realPositionKnown = true;
    return this.realPosition;

Now we know where to draw things, the next step is to actually implement the rendering  of things which we will do next week.

Sunday, September 5, 2010

Animating the Canvas Part 3: Getting Primitive

Before I get to the actual article, I will briefly point out that Dozen Days of Words episode 12: Morse Code has been posted on the site and while I never had the time to get dirty rectangles implemented in it, it does use a primitive layers system. In fact, if you are running it on Internet Explorer using excanvas you can visibly see how dirty rectangles could dramatically improve things. This is not noticeable on browsers that support the canvas tag.

As is often the case, before we can get to the good stuff, we need to build the foundation. As this project is going to require a bunch of classes and JavaScript, at least current implementations of it, is not really designed for such a thing we need to think about the best way of handling classes. Everything in JavaScript is thrown into a global namespace which can lead to problems. Looking at how other JavaScript libraries have handled the problem, I am going to follow the same route and put all my classes into a single object which is essentially equivalent to packages in Java or ActionScript.

This is actually very easy to do and to my surprise, it poses no problems for using the prototype variable in class creation. The one disadvantage to this technique is that you are putting the entire library into the package. Two ways around this is to break the library up into separate files that can be individually included, or to use a utility like Google's closure compiler. Setting up the package is simple:

var BGLayers = new Object();

With the "package" set up, it is time to get some of the primitives out of the way. The obvious most primitive graphic objects are the point and dimension. Both of these classes are essentially just structures but they are handy to have.

BGLayers.Point = function(x,y)
{
    this.x = x;
    this.y = y;
}

BGLayers.Dimension = function(w,h)
{
    this.width = w;
    this.height = h
}

The next class is a bit more complicated but is important as it is really the heart of this engine. No, not the layers class (we will start on that next week) but the lowly Rectangle. The question is how to handle the construction of the rectangle as I would like support for a valid empty rectangle, a clone constructor that takes a Rectangle as the sole parameter and copies it, and a Rectangle that lets you specify the four parameters.

Java and ActionScript support multiple constructors and functions by basing which function gets called on the parameters used. JavaScript doesn't do this yet. So how does one have multiple constructors for something like the Rectangle class? This is where I get to play around a bit with JavaScript. Researching this subject I discovered that functions have a arguments variable that holds the parameters. While arguments is not technically an Array object, it does have a length and can be accessed like an array. By using the length, the three different constructors can be combined into a single constructor function as follows:

BGLayers.Rectangle = function(x, y, w, h)
{
    if (arguments.length == 1) { // clone rectangle
        this.x = x.x;
        this.y = x.y;
        this.width = x.width;
        this.height = x.height;
    } else if (arguments.length == 4) { // parametrized rectangle
        this.x = x;
        this.y = y;
        this.width = w;
        this.height = h;
    } else { // default to empty rectangle
        this.x = 0;
        this.y = 0;
        this.width = 0;
        this.height = 0;
    }
}

I have noticed that I am starting to get a bit code-heavy. I want to focus more on the concepts and less on raw code, so I am thinking that for future posts I will link to the source file and just focus on the most relevant code while having an overview of the additional code. This has the added advantage of get through a lot more material and there is a lot of material that I want to cover here. As the Layers class is rather huge, I suspect that it will require more than one post to cover everything in it. Once we get that out of the way we can get to the animation part.