29a.ch

Box2Dflash Version 2.0 ported Javascript

Please note that this is experimental code!

Some weeks ago I wrote a script to convert version 2.0.2 of Box2DFlash to Javascript. I hesitated to release it because it is basically one big nasty hack that just happens to work. But as I got a few requests for it so I decided to release it. Please let me know if you do something with it. :)

Demo

Screenshot

You can see a demo of it in action here. You can click to trigger an explosion. On my notebook the demo runs fluidly in chrome. In firefox 3.5 it is pretty slow. In the current nightly it runs smooth as well. So I guess firefox is slowly catching up. Oh and just forget about IE.

Approach

At first thought this conversion would be trivial as both actionscript and javascript are dialects of ECMAScript. Well, I was wrong. Nevertheless I continued to follow my regex based approach, basically trying to ram my head through a wall. After a few attempts I succeeded to convert Box2DAS3 to javascript. It had a nasty bug tough. Two solid cubes were able to penetrate each other when the fell on their edges. The reason? ActionScript supports 'properties'. I didn't know about this and the conversion script does not support it. In the end I fixed the few properties in the translated code by hand because I was to lazy to add support for getters and setters to the conversion script. Now it seems to work pretty well. Please keep in mind, this is not a generic actionscript to javascript compiler, it's just a script that happens to work for box2dflash.

The explosions in the demo are simulated by shooting out a few tracer particles with a high density and velocity. The benefit over just applying an impulse to each object is that the strength of the impulse is proportional to the surface area. Also the force of the explosion will to some extend be redirected to the side by the floor. When using this in production code you would probably want to destroy this tracer particles after their first collision or a few seconds.

Please keep in mind, I'm not an expert on the subject. There are probably better and faster ways to approximate this than my crude way of using tracer particles (Navier-Stokes in javascript anybody? ;) ). Maybe I'll try to do some fluid dynamics on the gpu using webgl some day. It would be cool for sure.

Compiled Script

I compiled a single file version of the script using googles closure compiler. box2d.js.

Complete Zip

The zip file contains the actionscript source, the conversion script and a patch to fix some of the things the conversion script misses. box2d2.zip

Github

github.com/jwagner/box2d2-js

Documentation

I didn't write any. But you can use the documentation of box2dflash.

JS WARS media released under CC License


I decided to release some of JS WARS graphics and sounds under a creative commons attribution share alike license. If you want to use any of the other media please ask me.

Download jswars_media.zip (700kb)

Creative Commons License
This work by Jonas Wagner is licensed under a Creative Commons Attribution-Share Alike 2.5 Switzerland License.

Simulating Fire using Javascript and Canvas

This is another javascript effect I did. I might use it on the loading screen of my next javascript game as it doesn't need any textures (just like the starfield in jswars). It's based on an effect I wrote about 6? years ago. Sadly the canvas tag doesn't support palettes natively and mapping the colors in javscript too slow so the colors look less than optimal. Also chrome seems to render the result differently from firefox. This could be related to this issue.

Demo

Click the image to start the effect

How it works

Basically there are two maps, the heat map and the cooldown map. The cooldown map is generated using a noise function similar to perlin noise.

the noisemap

The noise texture is generated by first randomizing the alpha values and then drawing scaled versions of the noise texture onto itself. The high frequency noise was increased to create more flickering in the flames. The heat map is what you see before you click on the example. The algorithm then basically works like this:

  1. Noise is draw on top of image to cool it down
  2. The whole image is shifted up one row
  3. The heat map is applied to 'heat up' the pixels

For more details just read the source and feel free to ask questions.

Normal Mapping with Javascript and Canvas

I made a little experiment with normal mapping and phong shading in javascript which turned out to work quite well. I think with a little bit of tweaking it could be used in a real time game. Just move your mouse over the images bellow to see it in action. You'll need a modern browser supporting the canvas tag for this to work. Google Chrome seems to be the fastest.

Demo

Source

You can view the source code here: light.js. Feel free to copy from it, but please notify me if you use it for something cool. :) Also beware that the code is pretty hacky and unpolished.

How it works

The 3D effect is basically created using 2 textures. One contains the color of each pixel and the other the surface normal. The color image is rendered using only indirect lighting (ambient occlusion in that case). The direct light is then calculated in real time using phong shading without the diffuse part. For a more accurate description, read the source. ;)

color mapnormal map

Credits

The dragon head used in this demo comes from planetpixelemporium.com. The Buddah is from the Stanford 3D Scanning Repository and was rendered and baked using blender. Thanks for letting me use it.

2D Light/Shadow Effects Algorithm

I played around with 2d lighting for a game I'm working on. I'll probably post how it's done once it's a bit refined (and quicker!). It's currently written in C and running on the CPU. I'm looking for a way to do it using glsl though.

Generating SSL Cert for Apache

This is mostly just a note to myself, because I have to look it up every time I need to generate one, and the make-ssl-cert script that comes with debian doesn't appear to work.

openssl req -new -x509 -days 365 -nodes -out /tmp/cert.pem -keyout /tmp/cert.pem

Serialization of HTML5 web worker postMessage parameters in webkit

I played around with html5 web workers today. I quickly ran into an issue with chrome. Chrome (and probably also Safari) limit the messages that can be passed around to strings. The spec seems to allow arbitrary objects though, which works in firefox. Luckily Chrome supports native json, so here is a quick workaround.

// in the worker
if(navigator.userAgent.indexOf('WebKit')) {
    var _postMessage = postMessage;
    postMessage = function(data) {
        _postMessage(JSON.stringify(data));
    }
}
// in the page
worker.onmessage = function(e) {
    // assign it to a variable, e.data seems to be read-only
    var data = e.data;
    if(navigator.userAgent.indexOf('WebKit') != -1) {
       data = JSON.parse(data);
    }
// ..

In the worker monkey patching is easily possible. But I'm not aware of a nice way to intercept events so, I just put the decoding in the event handler. If I would need this in a lot of places I would probably write a higher order function the decode the argument.

Flip Images using HTML5 Canvas

You can flip an Image using HTML5 like this:

// flip x axis
ctx.scale(-1, 1);
ctx.drawImage(img, x, y);
// flip it back again
ctx.scale(-1, 1);

You can flip along the y axis in the same way. I'm note sure how fast this transformation is, in practice so you might need to cache it if you are doing realtime graphics.

Hand drawn lines using javascript canvas


For an upcoming game I'm working on I want the lines to look hand drawn. I found a nice paper on the subject. My algorithm is inspired by that paper, but not an exact implementation. But the results look good anyway. I also wrote a method to draw circles, but it needs improvement. Please let me know if you use it anywhere. :)

// randomize a variable
function fuzz(x, f){
    return x + Math.random()*f - f/2;
}

// estimate the movement of the arm
// x0: start
// x1: end
// t: step from 0 to 1
function handDrawMovement(x0, x1, t){
    return x0 + (x0-x1)*(
            15*Math.pow(t, 4) -
            6*Math.pow(t, 5) -
            10*Math.pow(t,3)
    )
}

// hand draw a circle
// ctx: Context2D
// x, y: Coordinates
// r: radius
function handDrawCircle(ctx, x, y, r){
    var steps = Math.ceil(Math.sqrt(r)*3);

    // fuzzyness dependent on radius
    var f = 0.12*r;

    // distortion of the circle
    var xs = 1.0+Math.random()*0.1-0.05;
    var ys = 2.0-xs;

    ctx.moveTo(x+r*xs, y);

    for(var i = 1; i <= steps; i++)
    {
        var t0 = (Math.PI*2/steps)*(i-1);
        var t1 = (Math.PI*2/steps)*i;
        var x0 = x+Math.cos(t0)*r*xs;
        var y0 = y+Math.sin(t0)*r*ys;
        var x1 = x+Math.cos(t1)*r*xs;
        var y1 = y+Math.sin(t1)*r*ys;

        ctx.quadraticCurveTo(fuzz(x0, f), fuzz(y0, f), x1, y1);
        ctx.moveTo(x1, y1);
    }
}

// inspired by this paper http://iwi.eldoc.ub.rug.nl/FILES/root/2008/ProcCAGVIMeraj/2008ProcCAGVIMeraj.pdf
function handDrawLine(ctx, x0, y0, x1, y1){
    ctx.moveTo(x0, y0)

    var d = Math.sqrt((x1-x0)*(x1-x0)+(y1-y0)*(y1-y0))

    var steps = d/25;
    if(steps < 4) {
        steps = 4;
    }

    // fuzzyness
    var f = 8.0;
    for(var i = 1; i <= steps; i++)
    {
        var t1 = i/steps;
        var t0 = t1-1/steps
        var xt0 = handDrawMovement(x0, x1, t0)
        var yt0 = handDrawMovement(y0, y1, t0)
        var xt1 = handDrawMovement(x0, x1, t1)
        var yt1 = handDrawMovement(y0, y1, t1)
        ctx.quadraticCurveTo(fuzz(xt0, f), fuzz(yt0, f), xt1, yt1)
        ctx.moveTo(xt1, yt1)
    }
}

Converting midi2wav using fluidsynth

Converting midi to wav using fluidsynth is not entirely trivial. Here is how I do it:

# convert opensolo.mid to fluidsynth.raw using the soundfont /usr/share/sounds/sf2/FluidR3_GM.sf2 
fluidsynth -l -i -a file -z 2048 /usr/share/sounds/sf2/FluidR3_GM.sf2 opensolo.mid
# convert fluidsynth.raw to fluidsynth.wav using sox
sox -b 16 -c 2 -s -r 44100 fluidsynth.raw fluidsynth.wav

You can use this together with the midi export of tuxguitar to export tuxguitar and guitarpro files to wav files.

Author

Jonas Wagner Jonas Wagner
Software Engineer
Zürich, Switzerland

More about me

Follow 29a_ch on Twitter

Experiments

screenshot screenshot screenshot screenshot

More Experiments

Latest Posts Tags Archive Links

guitarmasterclass.net (guitar lessons)