Wednesday, February 25, 2015

2xSE: Hardware accelerated realtime pixel art upscaling

Image upscaling is nothing new. Popular algorithms such as 2xSAI and Super Eagle have been around for a decade or more but most of these algorithms run on the CPU. I wanted to write one that targeted the GPU to take advantage of hardware acceleration. Now that webGL is available, it seemed fitting write this shader in GLSL. The results thus far have been fairly encouraging. Click here to see the demo running on top of the open source JSNES emulator.

Note: use the period key on the number pad to toggle SE filtering on/off in fullscreen mode to see the difference.

Also, this goes without saying but 2xSE requires a video card with some hardware acceleration for decent performance. Software emulation of pixel shaders is not so good.


2xSE (Scaling & Extrapolation)

The algorithm works by accepting an input texture and producing an output texture that is exactly twice the size of the input. This means that for every source textel we will be producing 4 output textels. The pixel shader reads a maximum of 10 input textels for every output textel. The textels forming the diagonal line perpendicular to the pixel being written are compared. If they are the same color that color is written otherwise the color of the local textel is written.
input pattern         output
   Y  X  Y            [X][Y]
   X [Y] Y            [Y][Y]
   Y  Y  Y
         Y  <-- This extra textel has a special purpose. Keep reading...
This is enough except for In cases where the input textels form an X pattern where each stroke is a different color. This situation causes rendering artifacts so the solution is to break the tie and determine which line should get the enhancement. I chose to implement a simple luminance calculation to be the tie breaker choosing darker colors over lighter colors. This was not an arbitrary decision since most pixel sprites use a dark usually black outline and sprites should always take precedence over background images.

Fast GLSL luminance function:
float LUM(vec3 color){ 
 return (color.x+ color.x+ color.z+ color.y +color.y+ color.y) * 0.166;
}
The "special textel" is used only for calculating the SW output value. I use this textel as a tie breaker to flip the logic on the luminance calculation which causes the algorithm to favor lighter colors over the darker color only in this one specific case. I found that while this does reduce many artifacts it also creates some in certain cases so it was a trade off but overall I think the output looks better with this. At some point I may take it out of the shader or create an option to toggle this feature on and off.

Sunday, February 8, 2015

Osmosis: A short game in Phaser.js


This was one of my earlier phaser experiments. You start the game as a molecule and the goal is to become more massive by absorbing smaller particles. This game is based on the well known Osmos with a twist. Its a gravity simulation game where the game world expands with the player. You win the game when you become a black hole.

Spheres that are more massive absorb spheres that are less massive. Spheres that appear red are more massive than you and should be avoided. Spheres that appear blue are less massive and safe to absorb. Use the mouse or touchscreen to propel matter from your sphere but be aware that locomotion comes at a price. You sphere will slowly lose mass as it is ejected. In other words, the blue sphere that you were moving towards may not be blue by the time you get to it!

The source code is about 500 lines of code. Feel free to fork it on github.

Monday, December 29, 2014

Hardware accelerated general purpose computation in javascript. (gpgpu)

General-purpose computing on graphics processing units (GPGPU, rarely GPGP or GP²U) is the utilization of a graphics processing unit (GPU), which typically handles computation only for computer graphics, to perform computation in applications traditionally handled by the central processing unit (CPU). The use of multiple graphics cards in one computer, or large numbers of graphics chips, further parallelizes the already parallel nature of graphics processing. In addition, even a single GPU-CPU framework provides advantages that multiple CPU's on their own do not offer due to specialization in each chip.
source: wikipedia
So why would you want to do this in javascript? Well for one its awesome! The fact that you can now run code directly on the GPU via WebGL shaders makes general purpose computation on accelerated hardware now possible. Secondly, unlike javascript, shaders are compiled and are optimized for parallel operations. SO I thought, why wait for WebCL when i could just do it myself with WebGL shaders? I used three.js to take care of most of the WebGL grunt work which majorly simplified the setup code. I ended up with a small function that accepts a shader, an array of input data, and a callback function. It looks like this.
 gpgpu(shader, dataset, function (gpuout) { 
    /* do somthing with gpuout array */
});
So generally speaking, the way this works is a texture is created from an array of input data. This texture is loaded into the video card. A fragment shader renders onto a plane using the texture as input data. This plane is then rendered to a buffer which is then dumped back into a javascript array. If the whole process sounds inefficient its because it is. Luckily the speed increase of running computations on accelerated hardware usually makes up for the performance hit moving all the data back and forth. I have found that this approach tends to work best for computationally expensive functions and larger datasets. although the gpgpu function can accept a dataset as small as 16 floats.
Once I wrote a javascript function and its GLSL shader equivalent, I was able to run a test to compare the speed of native javascript vs. the same function written as a WebGL shader. Amazing! in some cases the WebGL shader was as much as 100x faster that its javascript counterpart. Finally I thought it would be cool to only have to write the code once so i wrote a very simple javascript -> GLSL cross compiler. I ended up with something that looks like this.
gpgpu(
    glsl(function(val){ 
        return Math.sqrt(val);
    }), 
    dataset, 
    function (gpuout) { 
    /* do somthing with gpuout array */
});
Leave a comment and let me know what you think and feel free to check out the live demo. There is a code editor window where you can modify the javascript/shader and see the execution times of the CPU vs the GPU. :)



Wednesday, December 17, 2014

Getting Old-School with Voxels in Phaser


Yay so what is a voxel anyway? A voxel represents a value on a rectangular grid in 3-dimensional space. Voxel is a combination of "volume" and "pixel" where pixel is a combination of "picture" and "element". As with pixels in a bitmap, voxels themselves do not typically have their position (their coordinates) explicitly encoded along with their values. Instead, the position of a voxel is inferred based upon its position relative to other voxels (i.e., its position in the data structure that makes up a single volumetric image). In contrast to pixels and voxels, points and polygons are often explicitly represented by the coordinates of their vertices.

So for those of you who have played Minecraft let me just say that Minecraft may or may not qualify as a voxel engine. It's sort of a gray area. Although minecraft stores and manipulates level data using a voxel data set, the rendering is entirely polygon based. Traditional voxel rendering does not make use of polygons but rather, voxels.

Voxel engines were much more commonly used in the past prior to modern 3D hardware acceleration however recently they have come back into style thanks in large part to popular games such as Minecraft so I decided to try my hand at some voxel rendering in Phaser.

My terrain voxel renderer prototype features rotation, pitch, linear interpolation (x-axis) for voxels and color. Currently the prototype works and can be viewed here. feel free to take my code and improve it. I am still working on speed optimizations. If you have some ideas to improve performance let me know. I would be interested in hearing your thoughts.

var heightmap;
var texture;
var scanline;
var graphicsRow;
var angle = 0;

var game = new Phaser.Game(800, 600, Phaser.WEBGL, 'voxel',
{
    preload: function () {
        game.time.advancedTiming = true;
        game.load.image('heightmap', 'assets/heightmap.jpg');
        game.load.image('texture', 'assets/terrain.jpg');
    },
    create: function () {

        heightmap = getBitmapData('heightmap', 'heightmap');
        texture = getBitmapData('texture', 'rgba');
        //graphics = game.add.graphics(game.width / 2, game.height / 2);

        // use a new graphics object for each row
        // for some reason when there are too many primitives in a graphics object the renderer chokes.
        // by creating a seperate graphics object for each row we ensure this does not happen.
        graphicsRow = [];
        for (var y = 0; y < texture.length; y++) {
            graphicsRow.push(game.add.graphics(game.width / 2, game.height / 2));
        }
    },
    update: function () {
        angle += 0.01;

        var height = texture.length;
        var width = texture[0].length;
        var halfHeight = height / 2;
        var halfWidth = width / 2;
        var centerx = -halfWidth;
        var centery = 0; // -halfHeight;
        var xScale = 4;
        var pitch = 2;

        // y-buffer        
        scanline = [];
        for (var x = 0; x < width * xScale; x++) {
            scanline.push(65535);
        }


        for (var y = height - 1; y > -1; y--) {

            var graphics = graphicsRow[y];
            graphics.clear();
            var ax;
            var ay;

            for (var x = 0; x < width; x++) {

                // calculate rotation
                var pax = ax;
                var pay = ay;
                var xoff = x - halfWidth;
                var yoff = y - halfHeight;
                var a = Math.atan2(yoff, xoff);
                a = Phaser.Math.wrapAngle(a + angle, true);
                var d = Math.sqrt(xoff * xoff + yoff * yoff);
                ay = Math.round((Math.sin(a) * d) + halfHeight);
                ax = Math.round((Math.cos(a) * d) + halfWidth);

                if (ax < 0 || ax >= width || ay < 0 || ay >= height || !pax || !pay || pax < 0 || pax >= width || pay < 0 || pay >= height) {
                    continue;
                }
                var lineHeight = heightmap[pay][pax];
                var color = texture[pay][pax];
                var nextLineHeight = heightmap[ay][ax];
                var nextColor = texture[ay][ax];
                if (!lineHeight) {
                    if (!nextLineHeight) continue;
                    lineHeight = nextLineHeight;
                }
                if (!color) {
                    if (!nextColor) continue;
                    color = nextColor;
                }

                var heights = subdivide(lineHeight, nextLineHeight, xScale);
                var colors = subdivideColor(color, nextColor, xScale);

                for (var s = 0; s < xScale; s++) {

                    lineHeight = heights[s];
                    color = colors[s];

                    var xs = (x * xScale) + s;
                    var cx = (x + centerx) * xScale + s;
                    var cy = (y * pitch) + centery;

                    var miny = cy - lineHeight;
                    if (scanline[xs] > miny) {

                        graphics.lineStyle(1, color, 1);
                        if (scanline[xs] > cy) {
                            graphics.moveTo(cx, cy);
                        } else {
                            graphics.moveTo(cx, scanline[xs]);
                        }
                        graphics.lineTo(cx, miny);
                        scanline[xs] = miny;
                    }
                }

            }
        }

    },
    render: function () {
        game.debug.text(game.time.fps || '--', 2, 14, "#00ff00");
    }
});

// steps must be >= 2
function subdivide(v1, v2, steps) {
    var diff = v2 - v1;
    var step = diff / steps;
    var values = [];
    for (var x = 0; x < steps; x++) {
        values.push( v1+ step*x );
    }
    return values;
}

function subdivideColor(c1, c2, steps) {
    var r = subdivide(c1.r, c2.r, steps);
    var g = subdivide(c1.g, c2.g, steps);
    var b = subdivide(c1.b, c2.b, steps);
    var values = [];
    for (var x = 0; x < steps; x++) {
        values.push(hex(r[x], g[x], b[x], 255));
    }
    return values;
}

function hex(r, g, b, a) {

    return a << 24 | r << 16 | g << 8 | b;

}

// function: getBitmapData
// scans an image and returns a 2-dimentional array of pixel data
//
// arguments:
//      imageName - the image key to the phaser image
//      format - the desired return format
//          possible values: 'rgba','hex','heightmap'  (default: 'hex')
//
function getBitmapData(imageName, format) {

    if (!imageName) throw 'imageName argument required';
    if (!format) format = 'hex';
    
    var image = game.cache.getImage(imageName);
    if (!image) throw 'invalid imageName. Verify imageName in your preload function!';    
    var bmd = game.make.bitmapData(image.width, image.height);

    bmd.draw(image, 0, 0);
    bmd.update();

    var data = [];
    if (format === 'rgba') {
        for (var y = 0; y < image.height; y++) {
            var row = [];
            for (var x = 0; x < image.width; x++) {
                var hex = bmd.getPixel32(x, y);

                var pixel = {
                    r: (hex) & 0xFF, // get the r
                    g: (hex >> 8) & 0xFF, // get the g
                    b: (hex >> 16) & 0xFF, // get the b
                    a: (hex >> 24) & 0xFF    // get the alpha                    
                };
                row.push(pixel);
            }
            data.push(row);
        }
    }
    else if (format === 'hex') {
        for (var y = 0; y < image.height; y++) {
            var row = [];
            for (var x = 0; x < image.width; x++) {
                var hex = bmd.getPixel32(x, y);
                row.push(hex);
            }
            data.push(row);
        }
    }
    else if (format === 'heightmap') {
        for (var y = 0; y < image.height; y++) {
            var row = [];
            for (var x = 0; x < image.width; x++) {
                var hex = bmd.getPixel32(x, y);

                var p = {
                    r: (hex) & 0xFF, // get the r
                    g: (hex >> 8) & 0xFF, // get the g
                    b: (hex >> 16) & 0xFF // get the b                    
                };
                row.push((p.r + p.b + p.g)/3); // average of rgb
            }
            data.push(row);
        }        
    }
    return data;
};

So this works but it is very slow. I get about 3-6 FPS on my laptop. Why is it so slow? The primary problem is that we are sending each voxel to webGL as a line segment (using phaser graphics primitives). Granted Phaser is using webGL to send the lines to the GPU with hardware acceleration but all of these line segments are independent webGL operations. Every call to webGL adds overhead and we are making ALOT of calls. The offending code:
    // we call this deep inside the render loop and it makes WebGL sad.
    graphics.lineStyle(1, color, 1);
    if (scanline[xs] > cy) {
        graphics.moveTo(cx, cy);
    } else {
        graphics.moveTo(cx, scanline[xs]);
    }
    graphics.lineTo(cx, miny);

The Solution? Instead of 480,000 operations per frame, lets just do 1 operation per frame. Better yet, lets move the render logic off of the CPU all together! Lets write a pixel shader to make the GPU do all the work for us. This will kill 2 birds with one stone because now we need only a few calls to WebGL and since the operation is running on the GPU we dont have to wait for the data to trickle down the bus for each frame. We can just send the data once and let it live in video RAM where the pixel shader will use it to render the terrain to a textured quad.

... Part 2: Coming Soon!

Thursday, December 11, 2014

Easy Local Storage persistence layer in angular.js

Angular.js is a MVC framework for client side javascript that gives HTML superpowers. I have only introduced a few developers to angular but so far every one of them has been blown away by how easy and incredibly useful it is for building dynamic and highly responsive web apps.

Object oriented programming in angular.js with ds.oop

One of the features I like most about angular (aside from the 2-way data binding) is that it allows you to write modular self-contained code and use dependency injection which is invaluable in large projects which would otherwise quickly become heaps of unmaintainable spaghetti code. Using dependency injection in angular, we can define a controller or service with exactly what it needs to operate clearly defined in the function parameters so that any developer looking at it later immediately knows what it touches (That is, what code it needs to run or have access to). To make use of some other oop ideas such as inheritance lets see how to implement ds.oop with angular.js. ds.oop is a lightweight object oriented framework to simplify class creation and inheritance in javascript. As you will see, it allows you to write classes in a way that feels like a class.

This short tutorial will demonstrate an easy way to persist data in HTML5 local storage using reusable code via inheritance with ds.oop in angular.js. These 2 frameworks are open-source and work quite well togeather.

Required Frameworks: To start, this is a regular angular factory that can be injected into other factories and controllers as a dependency. This is a fast function to generate a Guid using a lookup table. We will use this any time we need to create a random Identifier for something.

.factory('Guid', function () {
    var lut = []; for (var i = 0; i < 256; i++) { lut[i] = (i < 16 ? '0' : '') + (i).toString(16); }
    return function () {
        var d0 = Math.random() * 0xffffffff | 0;
        var d1 = Math.random() * 0xffffffff | 0;
        var d2 = Math.random() * 0xffffffff | 0;
        var d3 = Math.random() * 0xffffffff | 0;
        return lut[d0 & 0xff] + lut[d0 >> 8 & 0xff] + lut[d0 >> 16 & 0xff] + lut[d0 >> 24 & 0xff] + '-' +
            lut[d1 & 0xff] + lut[d1 >> 8 & 0xff] + '-' + lut[d1 >> 16 & 0x0f | 0x40] + lut[d1 >> 24 & 0xff] + '-' +
            lut[d2 & 0x3f | 0x80] + lut[d2 >> 8 & 0xff] + '-' + lut[d2 >> 16 & 0xff] + lut[d2 >> 24 & 0xff] +
            lut[d3 & 0xff] + lut[d3 >> 8 & 0xff] + lut[d3 >> 16 & 0xff] + lut[d3 >> 24 & 0xff];
    };
})

Don't worry if that looks a little intimidating. Its been heavily optimized. The important part to see here is that an angular factory is just a function that returns something. In this case we are returning a function to generate a Guid. Now we can inject this factory into controllers, directives, or even other factories. Actually, thats exacly what we are going to do. Here is the simple localStorage base class I made. This provides some simple methods to save and load the object state into localStorage. At this point you might be wondering what local storage is exactly. With local storage, web applications can store data locally within the user's browser using key/value pairs. Unlike cookies, the storage limit is far larger (at least 5MB) and information is never transferred to the server.

// Base class for persistence
.factory('LocalStorage', ['Guid', function (Guid) {
    return ds.make.class({
        init: function (id) {
            this.id = (id || Guid()).toString();
        },
        load: function () {
            var state = localStorage[this.id];
            if (state) ds.data.copy(JSON.parse(state), this, [this.id], false);
        },
        save: function () {
            localStorage[this.id] = JSON.stringify(this);
        }
    });
} ])

So as you can see this is a very simple class. Our Guid factory is injected at the top. Three methods. Init() will accept an optional id or generate one using the injected Guid factory. Save() will serialize *this and save it to local storage. and Load will deserialize the data from local storage and the load it into *this. You could use this class as it is but there is nothing interesting in this class to save so to make this useful we need to inherit it...

// FormModel inherits LocalStorage class for save/load methods
.factory('FormModel', ['LocalStorage', function (LocalStorage) {
    return ds.make.class({
        inherits: LocalStorage,
        constructor: function (id) {
            this.init(id);
        },

        reset: function () {
            this.firstName= 
            this.lastName= 
            this.age='';
        }
    });
} ])

Ok so here is another simple class but in this one we have inherited our LocalStorage class and can now make use of its methods. This class is called FormModel because it is going to hold all of the data for our particular form and to use this and tie everything together we must create a angular controller and view. Here is the super mega awesome controller

.controller('MyCtrl', ['$scope', 'FormModel', function ($scope, FormModel) {

    // create an instance of FormModel and give it the id: 'test001'
    $scope.model = new FormModel('test001'); 

} ]);

And here is the view. Angular is calling our save/load methods directly through our FormModel class and handling updates between the DOM and our model automatically via 2-way data binding. Yeah, did i mention angular.js is awesome?

    <body ng-controller="MyCtrl">
        
        <div>
            model.id:
            <input type="text" ng-model="model.id" ng-disabled="true" />
        </div>
        <div>
            First Name:   
            <input type="text" ng-model="model.firstName" />
        </div>
        <div>
            Last Name:
            <input type="text" ng-model="model.lastName" />
        </div>
        <div>
            Age (years):
            <input type="text" ng-model="model.age" />
        </div>
        
        <button ng-click="model.save()">Save</button>    
        <button ng-click="model.load()">Load</button>
        <button ng-click="model.reset()">Reset</button>
    </body>

So there it is. Now who needs a database? :)
By combining ds.oop with angular we are able to take advantage of dependency injection which simplifies code maintenance and development. We accomplish this by encapsulating our class in an angular factories. By using ds.oop we can define a base class that can be used to persist any other class to local storage by simply inheriting it. This base class could also be extended to use any other storage mechanism quite easily. Session Storage, cookies, even a server side database or cache using ajax if one so desires.

I hope you have enjoyed this short tutorial. Go forth and write code.

Wednesday, November 26, 2014

Binary Search vs. array.indexOf()

So I needed a binary search and decided to write a short tutorial on it. This binary search class uses ds.oop a small oop javascript framework which can be downloaded or cloned from github.

    ds.make.class({
        type: 'ArrayUtils.BinarySearch',
        constructor: function() {
        }
    });
Ok so this class is going to do a binary search of an array for us. If you don't know what a binary search is its just a much faster way of searching than simply starting at the beginning of a list and running through a for loop and testing each element to see if it matches. Instead of binary search starts in the middle and depending of if the value is more or less it jumps to the middle of the first half or the last half of the list. It continues to do this until it finds the matching item or until it can no longer divide up the list.
Visual representation of a binary decision tree.
So we know we need an array to search through so lets add an array property and initialize it with the constructor.

    ds.make.class({
        type: 'ArrayUtils.BinarySearch',
        properties: {
            array: []
        },
        constructor: function (array) {
            array.sort();
            this.array = array;
        }
    });

Ok great. Now we can pass in an array through the constructor and it will live in our class instance. Also we have sorted the array so the elements should be in alpha-numeric order. Now in order to do the binary search we will need to do some string comparisons so lets make a static class for all the string functions we will write.

    ds.make.static.class({
        type: 'string',
        compare: function (a, b) {
            if (a.toString() < b.toString()) return -1;
            if (a.toString() > b.toString()) return 1;
            return 0;
        }
    });

So now we can call `string.compare(a,b)` from anywhere and get a result. I could have just included this in the BinarySearch class, but we may want to use it again somewhere else in our project so its better if its in a separate class for string utility functions.

Ok so now we just need to add the search method.

    search: function (search) {
        var array = this.array;
        var length = array.length;
        var index = Math.floor(array.length * 0.5);

        while (length > 1) {
            var cmp = string.compare(search, array[index]);
            if (cmp == 0) return index;
            length = Math.ceil(length * 0.5);
            var half = Math.ceil(length * 0.5);
            index = index + (half * cmp);
        }
    }

So first this creates some local variables. We need to use `this.array` to access array now since it is a public property of the class. The index we use to search starts in the middle of the array. Then in the while loop we do a comparison between the search and the item at the current index. The result will be -1,0, or 1 (less than, equal, or greater than respectively). Then if its a match we return the index otherwise the index jumps to the middle of the first half or second half of the list and repeats the process.

Finally, lets test out the class and see if it works.
    var a = new ArrayUtils.BinarySearch(['Orange', 'Kiwi', 'Lime', 'Apple', 'Grape', 'Banana']);
    var index = a.search('Lime');
    alert('index: ' + index + '   item: ' + a.array[index]);

Ok. It seems like its works. We create the class instance and pass an array into it. Then we call the search method to return the index. Lets do a better test and also see how the speed compares to array.indexOf().

    // now lets test it
    var a = new ArrayUtils.BinarySearch(array);

    // accuracy test
    for (var i = 0; i < array.length; i++) {
        var item = array[i];
        var index = array.indexOf(item);
        var bindex = a.search(item);
        if (array[index] != array[bindex]) 
            throw 'The binary search result was incorrect!  i: ' +i +'  item: '+item+'  index: '
            +index + '>' +array[index]+'  bindex: '+bindex +'>' +array[bindex];
    }

    // speed test
    var iterations = 1000000;
    var old_time = (new Date()).getTime();
    for (var i = 0; i < iterations; i++) {
        var item = array[Math.floor(Math.random() * array.length)];
        var index = array.indexOf(item);
    }
    var new_time = (new Date()).getTime();
    var seconds_passed_indexOf = (new_time - old_time)/1000;

    old_time = (new Date()).getTime();
    for (var i = 0; i < iterations; i++) {
        var item = array[Math.floor(Math.random() * array.length)];
        var index = a.search(item);
    }
    new_time = (new Date()).getTime();
    var seconds_passed_binary_search = (new_time - old_time)/1000;

    alert(iterations + ' iterations\nindexOf:\t\t' + seconds_passed_indexOf 
            + '\nbinary search:\t\t' + seconds_passed_binary_search)

And here are the results. I ran the test with an array of 7000 random strings. As you can see, our BinarySearch class is waaaaayyy faster.

    1000000 iterations
    indexOf:  15.387 seconds
    binary search: 0.207 seconds

To see this class in action check out the tutorial folder. Thanks for reading!

Sunday, November 23, 2014

Singletons in ds.oop and Phaser State Management

State management is one of the things that separates a demo from a complete game. Phaser has a great state manager that helps to get states up and running quickly. While writing a game state manager is a good academic exercise for any game developer but since phaser already has one I'll just use it instead of writing my own.

So lets just get right into the code. We will be using the ds.oop framework to create a static class to encapsulate the phaser game and state management system. This class allows us to setup the state switching in one place which makes it easier to read and makes it easy to load states from a json file or later if we want.

// Singleton Class
ds.make.static.class({
    type: 'Game.State',
    constructor: function () {
        this.width = 800;
        this.height = 600;
        this.game = new Phaser.Game(this.width, this.height, Phaser.WEBGL, 'cartest');
        this.states = [];

        this.add(Game.Boot);
        this.add(Game.Loader, false);
        this.add(Game.World);
        this.start();
    },
    add: function (stateClass, clearWorld, clearCache) {
        this.game.state.add(stateClass.prototype.type, stateClass);
        this.states.push({
            state: stateClass.prototype.type,
            clearWorld: clearWorld,
            clearCache: clearCache
        });
    },
    start: function () {
        this.stateIndex = -1;
        this.next();
    },
    next: function () {
        var p = this.states[++this.stateIndex];
        this.game.state.start(p.state, p.clearWorld, p.clearCache);
    }
});

So this is the entry point for our phaser game. The constructor creates the phaser game object and adds all the game states. The add method will cache the parameters for the game.state.start method until we are ready to switch the state. The state order is completely linear in this example but it would be trivial create a branching structure that switches states conditionally if needed.

Here is the first state class. I created this jut as an example to show how the state switching works now. As you can see there is no need to keep track of which state is next. The order is already set in the Game.State class. All we are doing is calling the next() method to signal the state change.

ds.make.class({
    type: 'Game.Boot',
    create: function () {
        Game.State.next();
    }
});

The first task for our state manager is to display some graphic like a loading bar while the user waits for the game assets to load. The loading screen is a standard way to manage loading assets in a game. Here i'm just updating some text with the percentage loaded. Later we will load some loading screen assets and display an animated loading screen with a progress bar but for now this should give you the general idea.

ds.make.class({
    type: 'Game.Loader',
    preload: function() {
        var style = { font: "12px Lucida Console", fill: "#ffff44", align: "left" };
        this.text = this.game.add.text(5, 5, 'Loading...', style);
        this.text.fixedToCamera = true;
        // Load all the assets here
    },
    loadUpdate: function () {
        this.text.setText('Loading: ' + this.game.load.progress + '%');
    },
    create: function () {
        Game.State.next();
    }
});

Part 2 of this tutorial coming soon...

Tuesday, November 18, 2014

Combining Phaser and Three.js to make 2.5D games.

I wanted to incorporate 3D elements into a phaser game and since phaser does not support 3D I started looking at Three.js. Phaser and Three are both great game libraries on their own but individually neither one of them did everything that I wanted so I thought, why not combine them?

To see the demo in action click here.
here is the demo source code

Maybe I should take a step back for a moment. For those of you who don't know, Phaser is a great javascript game library for writing HTML5 games. It is based on PIXI.js as supports seamless canvas and webGL rendering of 2D games as well as tweening, tilemaps, sprites, collision detection, and physics. Three.js is another great javascript game library but unlike Phaser which only supports 2D, Three.js is designed to abstract away the complexities of working with 3D rendering in webGL.

The last library that I should mention is ds.oop. This is not a game library at all. It is a very lightweight abstraction layer for creating highly reusable classes in javascript. ds.oop streamlines object oriented programming in javascript by hiding all of the ugliness of inheritance and class creation in javascript and leaving you with a simple easy to maintain class object. Most importantly it just works. I highly recommend it for any javascript project.

Required Libraries:

There are likely many ways to combine phaser and three in a project but for my purposes, I wanted to use phaser primarily and just use three for incorporating some 3D elements into the game so I decided to keep the typical phaser game structure. I'm using the normal phaser rendering pipeline. Initially I thought about rendering everything from phaser onto a textured plane in three but I decided to do it the other way around and just render some elements in three and then grab the bitmap data and render it in phaser like any other sprite. This turned out to be easier than I thought.

The Phaser.Three class

This class allows you to create a layer in your phaser game that consists of a scene rendered by three.js. The class is fairly minimal. The init method starts an instance of THREE.WebGLRenderer with the same dimensions as the currently running phaser game. Then it creates a sprite from the off screen canvas to use as an layer. The sprite is attached to the phaser camera. Finally this method setup up the three.js scene and camera based on the current aspect ratio.
ds.make.class({
    type: "Phaser.Three",
    constructor: function () {
        throw 'Do no instantiate this class. Inherit it and call the init method from your constructor!';
    },
    init: function (game) {
        this.game = game;

        // renderer
        this.renderer = new THREE.WebGLRenderer({ alpha: true });
        this.renderer.setSize(game.width, game.height);

        // setup canvas to be used as a sprite texture
        this.canvas = this.renderer.domElement; 
        this.context = this.canvas.getContext('2d');
        this.baseTexture = new PIXI.BaseTexture(this.canvas);
        this.texture = new PIXI.Texture(this.baseTexture);
        this.textureFrame = new Phaser.Frame(0, 0, 0, this.game.width, this.game.height, 'debug', game.rnd.uuid());
        this.sprite = this.game.add.sprite(0, 0, this.texture, this.textureFrame);
        this.sprite.fixedToCamera = true;

        // camera
        var fov = 45;
        var camera = new THREE.PerspectiveCamera(fov, game.width / game.height, 1, 10000);
        var dist = game.height / 2 / Math.tan(Math.PI * fov / 360);
        camera.position.z = dist;
        //camera.position.y = 200;
        camera.lookAt(new THREE.Vector3(0, 0, 0));
        this.camera = camera;
        this.maxHeight = dist;

        // scene
        var scene = new THREE.Scene();
        this.scene = scene;

        var ambientlight = new THREE.AmbientLight(0xF0F0F0); // soft white light
        scene.add(ambientlight);
    },
    update: function () {

        this.scene.position.x = -this.game.camera.position.x * 2;
        this.scene.position.y = -this.game.camera.position.y * 2;

        // render
        this.renderer.render(this.scene, this.camera);

        PIXI.updateWebGLTexture(this.baseTexture, this.game.renderer.gl);
    }
});

So this is the base class that takes care of setting up the camera for you. The update function in this class will lock the three camera to the phaser camera position so when you move game.camera to a new position the scene will also render that position.

Using this class in easy. Just inherit it and start adding some meshes or whatever you need to render in Three.js
ds.make.class({
    type: 'Game.Layer3D',
    inherits: Phaser.Three,
    constructor: function (game) {
        this.init(game);

        // make a box
        var geometry = new THREE.BoxGeometry(100, 100, 100);
        mesh = new THREE.Mesh(geometry, new THREE.MeshNormalMaterial());           
        mesh.position.z = 50;
        mesh.position.x = 300;
        mesh.position.y = 300;
        this.scene.add(mesh);
    }
});

Now to see it in phaser you have to create the Layer3D object in the phaser create function:
this.layer3d = new Game.Layer3D(game);

Finally, don't forget to call update in your update function. This will update the camera position in the three.js scene and render the scene to the viewport.
this.layer3d.update();

And That's really all there is to it. Special thanks to Rich on the Phaser forums for posting an example of rendering into Phaser from an off-screen canvas and also to everyone reading this, I hope this short tutorial was helpful for you to get started with 3D mix-ins in phaser.