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.

June 19, 2009

There's something about sarien.net that really floats my boat. Maybe it's the 8 bit goodness, or maybe it's the multiplayer twist, or maybe it's the crazy technology they're using. Whatever it is, I think sarien.net is awesome.

sarien.net - King's Quest 3

I love that they use the term DHTML rather than any of the fancy new monikers which Javascript + markup have take on in recent years.

June 14, 2009

Prototyping is a great way of making games. You make lots of small, quick prototypes, and iterate on them to "find the fun". Scripting languages like Python and Lua are really useful in this process and there are lots of nice libraries like Pygame to assist in the process.

It would be cool to be able to include players in the prototyping loop so that your game ideas can be tried out infront of an audience and get feedback early in the process. The democratisation of game design, I guess.

I've been thinking about this a lot lately, especially as I've been going through the frustrating process of trying to get my recent gamejam entry to work under Windows. It's a pygame based game which should port trivially, but it's still a fair bit of hair-tearing work. It's not much fun to have to do such a huge amount of laborious work just to get your game ideas infront of people so that they can play them, and tell you what they think.

To this end I've been working on the Javascript game library which I wrote about earlier. Recently my efforts have been in separating it from the processingjs library into a standalone system which will run on all the major browsers. Firefox, Safari, IE6, IE7 are currently tested and working.

Hopefully you'll be seeing more links like this on here in future:

.:[ circles demo ]:.

Download a zipfile of the source of the JSGameSoup library here:

http://mccormick.cx/dev/blogref/jsgamesoup-30.zip

Or check out a branch with bzr:

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

Patches welcome!

June 1, 2009

[ ]  dorkbotlondon #61
/|\  The summer season of dork is here
/ \

When:
   7pm, 4th June 2009
Where:
   The boxing club, Limehouse town hall, E14 7HA
   For directions and instructions for getting in to the building go here:
   http://dorkbotlondon.org/event/dorkbotlondon61/

Featuring presentations from the well-combed and frisky...

* RJDJ  - Chris McCormick
  (Pure data on the iphone)

* sketchPatch - Davide Della Casa
  (an online programming playground based on Processing, somewhere to
  experiment with code, reuse and collaborate on existing code, share
  and learn)

* Orbiter - an interactive sound environment - Vera-Maria Glahn & Marcus Wendt
  (Process of an interactive installation using generative sound and
  visuals and stereo motion tracking - from idea to play)

Plus!  Opendorks.  If you'd like to give a 7 minute ad-hoc
presentation about something then drop us a mail or let us know on the
night.  Or if you'd like to give a longer presentation drop us a mail
and we'll schedule you for a future dork.

http://dorkbotlondon.org/event/dorkbotlondon61/

May 25, 2009

I've been experimenting with the Javascript port of processing by John Resig and it seems like it could be quite good for rapidly prototyping games on the web. One of the great things about it is that it doesn't require any plugins or proprietary technologies like Flash, relying instead on the canvas element. There are some awesome demos of it in action on the website. I made a little fork which is optimised for the task of writing object oriented game code, which you can see in action below. Try clicking on the spinning asteroids.

My fork implements a basic mainloop into which you can inject new game entities with the function addEntity(); and a bunch of convenience methods which you can implement to draw your entities, or capture events like mouse clicks. As per processingjs, you can use processing's Java style syntax, or Javascript syntax instead. Here's the source to the above example:

size(400, 225);

function Asteroid(radius, x, y) {
    // variables
    this.x = x || random(0, width);
    this.y = y || random(0, height);
    this.angle = random(0, PI);
    this.radius = radius || 40;
    // velocities
    this.angleV = random(-0.1, 0.1);
    this.xV = random(-0.5, 0.5);
    this.yV = random(-0.5, 0.5);
    // structure of this shape
    this.points = [];
    this.randomPoint = function() {
        return random(-this.radius/2, this.radius/2);
    }
    for (i=0; i<round(this.radius / 5); i++)
        this.points.push([this.radius * Math.sin(i * PI / round(this.radius / 10)) + this.randomPoint(),
            this.radius * Math.cos(i * PI / round(this.radius / 10)) + this.randomPoint()]);
    this.poly = [];

    this.collisionPoly = function() {
        return this.poly;
    }

    this.mouseDown = function() {
        if (this.radius > 25) {
            addEntity(new Asteroid(this.radius / 3 * 2, this.x + this.randomPoint(), this.y + this.randomPoint()));
            addEntity(new Asteroid(this.radius / 3 * 2, this.x + this.randomPoint(), this.y + this.randomPoint()));
        }
        delEntity(this);
    }

    this.update = function() {
        // update all our state variables
        this.angle += this.angleV;
        this.x = (this.x + this.xV + width) % width;
        this.y = (this.y + this.yV + height) % height;
        // update our shape definition
        for (n=0; n<this.points.length; n++) {
            this.poly[n] = [this.points[n][0] * cos(this.angle) - this.points[n][1] * sin(this.angle) + this.x,
                this.points[n][0] * sin(this.angle) + this.points[n][1] * cos(this.angle) + this.y];
        }
    }

    this.draw = function() {
        stroke(255);
        noFill();
        beginShape();
        for (n=0; n<this.poly.length; n++) {
            vertex(this.poly[n][0], this.poly[n][1]);
        }
        endShape(CLOSE);
    }
}

addEntity(new Asteroid());
addEntity(new Asteroid());
addEntity(new Asteroid());
addEntity(new Asteroid());
addEntity(new Asteroid());

I you want to check out all of the code, including my modified version of processingjs, I've put my bzr repository online and you can get it like this:

bzr co http://mccormick.cx/dev/gameprocjs/

Or you can click here to download a zipfile of the source.

The main thing to be aware of is that any object added with addentity() should have an update() method, which will get called once per game loop to update your object's state, and a draw() method where you should put the code to draw your object. Other useful methods which you can implement include mouseDown() and mouseUp(), both of which require that you provide a method called collisionPoly() which returns a list of points that define a collision polygon for your game entity. Later I hope to add my Javascript recursive dimensional clustering implementation which will make it really simple to detect in-game collisions and will also require a method called getBoundingBox() which will make the collision detection and mouse-click-detection much more efficient.

Anyway, if you're interested in using this I'd love to hear from you!