June 29, 2009

This weekend, in between watching Captain Picard versus Gandalf and having a birthday drink, I somehow managed to find some time to work on my web based games library, currently tentatively named 'JSGameSoup'. Click through the image to try out a little demo which uses it:

AsteroidsTNG revision 40

This demo doesn't do that much except let you fly around, but you can see where it's leading, and what the library is basically capable of. The idea is to make a Free Software game development environment which can be trivially deployed to web browsers and portable devices like Android, Nintendo DS, etc. I want to keep it completely free of proprietary technologies so that people don't have to rely on Flash, for example, to develop games for the web and beyond. I am pretty excited with how things are going. So far it seems to work well and speedily with the three majority rendering engines; Gecko, IE, and that KHTML fork that some company started. In other words, the demo runs with acceptible quality and speed on the majority of operating systems in the majority of browsers, with no fiddly tweaking - Hooray! \o/

Even though I've only just started doing it, I am really liking this new way of making and releasing games and game libraries, where I get to release them right here on this blog to you, the three people who read it. :) I really need to set up comments here as well, so I can actually get some feedback on the releases (but please feel free to email me). I think the fact that making games feels fun again, is a very good sign that I'm on the right track.

Anyway, as usual, here is the source code:

jsgamesoup-39.zip

or if you are a bazaar user:

bzr branch http://mccormick.cx/dev/jsgamesoup/

AsteroidsTNG-40.zip

or the repo:

bzr branch http://mccormick.cx/dev/AsteroidsTNG/

JSGameSoup is LGPLv3 and AsteroidsTNG is GPLv3.

The code of the Asteroids themselves is quite similar to what I posted before, except that it uses canvas commands now, instead of processingjs commands to draw. Here's the code that drives the ship:

function Ship(world) {
    this.world = world;
    this.world.player = this;
    this.x = gs.width / 2;
    this.y = gs.height / 2;
    this.angle = 0;
    this.speed = 0;
    this.points = [[0, -13], [-7, 7], [7, 7]];
    this.poly = [];
    this.lastsmoke = null;

    this.keyHeld_37 = this.keyDown_37 = function () {
        this.angle -= 0.1;
    }

    this.keyHeld_39 = this.keyDown_39 = function () {
        this.angle += 0.1;
    }

    this.keyDown_38 = function () {
        this.speed = 1;
    }

    this.keyHeld_38 = function () {
        if (this.speed < 3.0)
            this.speed += 0.3;
    }

    this.keyDown = function (keyCode) {
        //console.log(keyCode);
    }

    this.update = function() {
        if (this.speed > 0.1)
            this.speed -= 0.1;
        else
            this.speed = 0;
        this.x = (this.x + this.speed * Math.sin(this.angle) + gs.width) % gs.width;
        this.y = (this.y - this.speed * Math.cos(this.angle) + gs.height) % gs.height;
        for (n=0; n<this.points.length; n++) {
            this.poly[n] = [this.points[n][0] * Math.cos(this.angle) - this.points[n][1] * Math.sin(this.angle) + this.x, this.points[n][0] * Math.sin(this.angle) + this.points[n][1] * Math.cos(this.angle) + this.y];
        }
        if (this.speed && (!gs.inEntities(this.lastsmoke) || gs.distance([this.lastsmoke.x, this.lastsmoke.y], [this.x, this.y]) > 15)) {
            this.lastsmoke = new Smoke(this.x - 9 * Math.sin(this.angle), this.y + 9 * Math.cos(this.angle));
            gs.addEntity(this.lastsmoke);
        }
    }

    this.draw = function(c) {
        c.strokeStyle = 'rgba(255, 255, 255, 1.0)';
        gs.polygon(this.poly);
    }
}

And here is the object/class defining the little smoke particles which come out of the ship:

function Smoke(x, y) {
    this.x = x;
    this.y = y;
    this.life = 1.0;

    this.draw = function(c) {
        c.strokeStyle = 'rgba(200, 200, 200, ' + this.life + ')';
        c.beginPath();
        c.arc(this.x, this.y, 2, 0, Math.PI*2, true);
        c.closePath();
        c.stroke();
    }

    this.update = function() {
        this.life -= 0.08;
        if (this.life < 0)
        {
            gs.delEntity(this);
            this.life = 0.01;
        }
    }
}

The whole game is launched like this, where gs is the JSGameSoup() object that is automatically created by the framework:

w = new World();
gs.addEntity(w);
gs.addEntity(new Ship(w));
for (n=0; n<3; n++) {
    gs.addEntity(new Asteroid(w));
}

To me this code feels like it does quite a lot for just a little bit of work, and that's always nice.

Need software development advice? Book a call with me.