
    var World = function () {
        this.bodies = [];
        this.behaviors = [];
        this.renderer = undefined;
        this.paused = true;
        this.ratio = 100; // pixels/meter
        this.width = 600;
        this.height = 500;

        this.movingBody = null;
        this.lastStep = 0;
        this.lastMove = 0;

        /* event handlers */
        this.onMove = this._onMove.bind( this );
        this.onEnd = this._onEnd.bind( this );
    };

    World.prototype.init = function () {
    };

    World.prototype.start = function () {
        if ( !this.paused ) {
            return;
        }
        this.lastStep = now();

        raf( this.step.bind( this ) );

        this.paused = false;
    };

    World.prototype.step = function() {
        var i, body,
            thisStep = now(),
            dt = ( thisStep - this.lastStep ) / 1000; // in seconds

        // dt = 16 / 1000; // DEBUG

        this.lastStep = thisStep;

        for ( i = 0; i < this.behaviors.length; i++ ) {
            for ( var j = 0; j < this.bodies.length; j++ ) {
                body = this.bodies[ j ];
                this.behaviors[ i ].behave( body );
            }
        }

        for ( i = 0; i < this.bodies.length; i++ ) {
            body = this.bodies[ i ];
            body.step( dt );
        }

        if ( this.renderer ) {
            this.renderer.draw( this.bodies );
        }

        if ( !this.paused ) {
            raf( this.step.bind( this ) );
        }
    };

    World.prototype.add = function( body ) {
        body.world = this;
        this.bodies.push( body );
    };

    World.prototype.apply = function( behavior ) {
        this.behaviors.push( behavior );
    };

    World.prototype.setRenderer = function ( renderer ) {
        this.renderer = renderer;
        this.width = this.renderer.width;
        this.height = this.renderer.height;

        this.renderer.on( startEvent, this._onClick.bind( this ) );
    };

    World.prototype.pause = function () {
        this.paused = true;
    };

    World.prototype.resume = function () {
        this.start();
    };

    World.prototype._onClick = function ( e ) {
        var offset = this.renderer.el.getBoundingClientRect(),
            x = e.pageX || e.touches[0].pageX - offset.left,
            y = e.pageY || e.touches[0].pageY - offset.top,
            body,
            i;

        if ( this.paused ) {
            return;
        }

        // Consider the later a body is added to world, the higher z-index it has.
        for ( i = this.bodies.length - 1; i >= 0; i-- ) {
            body = this.bodies[ i ];
            if ( body.contains( x, y ) ) {
                body.setStatus( "MOVING" );
                this.movingBody = body;

                this.renderer.on( moveEvent, this.onMove );

                return;
            }
        }

    };

    World.prototype._onMove = function ( e ) {
        var offset = this.renderer.el.getBoundingClientRect(),
            x = isMobile ? e.touches[0].pageX - offset.left : e.pageX,
            y = isMobile ? e.touches[0].pageY - offset.top : e.pageY,
            moveTime = now(),
            dt = moveTime - this.lastMove,
            body = this.movingBody,
            velocity;

        e.preventDefault();
        e.stopPropagation();

        if ( !body ) {
            this.lastMove = 0;
            return;
        }

        if ( x > offset.width - ( body.radius || body.width/2 ) || y > offset.height - ( body.radius || body.height/2 ) ) {
            this.lastMove = 0;
            return;
        }

        body.prevPosition.set( x, y );

        body.move( Physics.Vector.create( x, y ) );

        velocity = Physics.Vector.copy( body.position ).sub( body.prevPosition ).scale( 1000 / dt );

        Physics.Vector.release( body.velocity );
        body.velocity = velocity;

        this.lastMove = moveTime;
        this.renderer.on( endEvent, this.onEnd );
    };

    World.prototype._onEnd = function () {
        this.movingBody.setStatus( "NORMAL" );
        this.movingBody = null;
        this.renderer.off( moveEvent, this.onMove );
        this.renderer.off( endEvent, this.onEnd );
    };

    Physics.World = World;

@@ -495,24 +495,25 @@
 nction () %7B%0A
+%0A
     %7D;%0A%0A    
@@ -883,45 +883,8 @@
 ds%0A%0A
-        // dt = 16 / 1000; // DEBUG%0A%0A
     
@@ -2770,16 +2770,74 @@
 nMove );
+%0A                this.renderer.on( endEvent, this.onEnd );
 %0A%0A      
@@ -2874,25 +2874,24 @@
 %7D%0A        %7D%0A
-%0A
     %7D;%0A%0A    
@@ -3429,112 +3429,36 @@
 f ( 
-x %3E offset.width - ( body.radius %7C%7C body.width/2 ) %7C%7C y %3E offset.height - ( body.radius %7C%7C body.height/2
+!this._isMovable( body, x, y
  ) )
@@ -3557,25 +3557,24 @@
 et( x, y );%0A
-%0A
         body
@@ -3609,25 +3609,24 @@
 ( x, y ) );%0A
-%0A
         velo
@@ -3841,104 +3841,840 @@
     
-    this.renderer.on( endEvent, this.onEnd );%0A    %7D;%0A%0A    World.prototype._onEnd = function () %7B
+%7D;%0A%0A    World.prototype._isMovable = function ( body, x, y ) %7B%0A        var horizontalDistance = body.radius %7C%7C body.width/2,%0A            verticalDistance = body.radius %7C%7C body.height/2,%0A            boundary = this.renderer.el.getBoundingClientRect();%0A%0A        if ( x + horizontalDistance %3E= boundary.left + boundary.width ) %7B%0A            return false;%0A        %7D%0A        if ( x - horizontalDistance %3C= boundary.left  ) %7B%0A            return false;%0A        %7D%0A        if ( y + verticalDistance %3E= boundary.top + boundary.height ) %7B%0A            return false;%0A        %7D%0A        if ( y - verticalDistance %3C= boundary.top ) %7B%0A            return false;%0A        %7D%0A%0A        return true;%0A    %7D;%0A%0A    World.prototype._onEnd = function () %7B%0A        if ( now() - this.lastMove %3E 200 ) %7B%0A            this.movingBody.velocity.set( 0, 0 );%0A        %7D%0A
 %0A   

fix mouse event handlers