Raphaël :: Simple Physics Engine

Integration of Raphael with simple physics simulation.

HTML

<div id="the_canvas"></div>

CSS

#the_canvas { background-color: white; width:250px; height:250px; }

JavaScript

/*
 * Simple Physics Engine with Raphael SVG Library
 * http://jsfiddle.net/user/klenwell/fiddles/
 *
 * TODO:
 *   Add start/stop button
 *
 * NOTES:
 *   Resolves vanishing ball issue by adding last_point method to ball object
 *     for Physics.find_contact_point, but still occasional wedging issues
 */
var __VERSION__ = "0.4.0"
var inspector = {};
var R = undefined; // Raphael as global


var Graphics = {

    init: function(canvas) {
        this.center_x = canvas.offsetWidth / 2.0;
        this.center_y = canvas.offsetHeight / 2.0;
        this.R = Raphael(canvas, canvas.offsetWidth, Graphics.offsetHeight);
    },
    
    draw_circle: function(c) {
        var screen_x = this.world_to_screen_x(c.x);
        var screen_y = this.world_to_screen_y(c.y);
        
        var el = R.circle(screen_x, screen_y, c.r).attr({
            fill: "black",
            stroke: "none",
            opacity: c.opacity || 1.0
        });
        
        if ( c.stroke_width ) {
            el.attr({
                'stroke-width': c.stroke_width,
                stroke: c.stroke_color                
            });
        };
        
        return el;
    },
    
    draw_ball: function(ball) {
        return this.draw_circle(ball);
    },
    
    draw_world: function(world) {
        return this.draw_circle(world);
    },

    world_to_screen_x: function(x) {
        return this.center_x + x;
    },

    world_to_screen_y: function(y) {
        return this.center_y - y;
    },
};


var Physics = {
    
    collide_balls: function(ball1, ball2) {
        // calculate restitution
        // TODO: add elasticity attr to circles
        var ball1_elasticity = 1.0;
        var ball2_elasticity = 1.0;
        var restitution = ball1_elasticity * ball2_elasticity;
        
        // invert masses
        var im1 = 1.0 / ball1.m;
        var im2 = 1.0 / ball2.m;
        
        // get minimum translation distance
        var delta = ball1.point().subtract(ball2.point());
    ...