GenevaJS + Processing.js + Box2D.js
Demo by Alistair MacDonald [hyper-metrix.com/f1lt3r]For avid users of the Prototype.js library who enjoy the succinct syntax of jquery, and for jQuery developers who are locked down to a Prototype.js environment, GenevaJS provides a clean API, allowing jQuery commands to be run without loading the jQuery library. At only 7.8KB GenevaJS makes light work of jQuery syntax, that would otherwise cost you 64KB.
GenevaJS | ProcessingJS | Box2DJS
var props={};
var p;
var initPJS = function(url){
var canvas=document.getElementById("canvas");
p=Processing(canvas);
p=Processing(canvas,p.ajax("sketch.pjs"));
}
document.addEventListener("DOMContentLoaded",initPJS,false);
$(document).ready(function(){
$('input[value=Update sketch]').click(function(){
props.balls = $('input[name=balls]').val();
props.radius = $('input[name=radius]').val();
props.rest = $('input[name=rest]').val();
props.force = $('input[name=force]').val();
p.draw = function(){};
initPJS();
});
});
// sketch.pjs
/* PROCESSINGJS.COM - BOX2D.JS
Newton's Cradle in Processing.js with Box2D.js
Hyper-Metrix.com/F1LT3R */
// Set up the Box2D World
var worldAABB = new b2AABB();
worldAABB.minVertex.Set(-1000, -1000);
worldAABB.maxVertex.Set(1000, 1000);
var gravity = new b2Vec2(0, 300);
var doSleep = true;
var world = new b2World(worldAABB, gravity, doSleep);
// Get form values for balls |or| Define the number of balls and create the object array
int balls;
if ( props.balls ) { balls = props.balls; }
else { balls = 6; }
Object[][] ball = new Object[balls][4];
// Get form values for restitution
int rest;
if ( props.rest ) { rest = props.rest; }
else { rest = .9; }
// Get form values for radius
int radius;
if ( props.radius ) { radius = props.radius; }
else { radius = 10; }
// Get form values for force
int force;
if ( props.force ) { force = props.force; }
else { force = 5000; }
// Iterate through, creating new balls and joints
for(int i=0; i < balls; i++){
// Set the XY pos for the balls
int x=(i*41)+55, y=50;
// Create a Box2D circle
ball[i][0]=new b2CircleDef();
ball[i][0].density = 10;
ball[i][0].radius = radius*2;
ball[i][0].restitution = rest;
ball[i][0].friction = 1;
// Create Box2D Body for Circle
ball[i][1]=new b2BodyDef();
ball[i][1].AddShape(ball[i][0]);
ball[i][1].position.Set(x,y+125);
ball[i][2]=world.CreateBody(ball[i][1]);
// Create Box2D joint
ball[i][3]=new b2RevoluteJointDef();
ball[i][3].anchorPoint.Set(x,y);
ball[i][3].body1 = world.GetGroundBody();
ball[i][3].body2 = ball[i][2];
world.CreateJoint(ball[i][3]);
}
// Set up the animation speed and the calculations per frame
var timeStep = 1.0/30;
var iteration = 12;
// Set up the Processing.js Canvas
void setup(){
size(320,240);
frameRate(60);
stroke(255);
}
// Define color range
color color1 = color(255,0,0,100);
color color2 = color(0,255,0,100);
// Begin the draw loop
void draw(){
// Clear the background and fill with transparent grey
clear();
background(100,100,100,200);
// Ask Box2D to calculate another step in the world
world.Step(timeStep, iteration);
// Loop through the ball array and draw everything
for(int i=0; i < balls; i++){
b=ball[i];
line(b[3].anchorPoint.x,b[3].anchorPoint.y,b[2].m_position.x,b[2].m_position.y);
fill(lerpColor(color1,color2,1/balls*i));
rect(b[3].anchorPoint.x-10,b[3].anchorPoint.y-10,20,20);
ellipse(b[2].m_position.x,b[2].m_position.y,b[0].radius*2,b[0].radius*2);
}
}
// Apply an impulse to force any ball left when clicked on
void mouseClicked(){
for(int i=0; i < balls; i++){
b=ball[i][2];
r=ball[i][0].radius;
if( dist(mouseX,mouseY,b.m_position.x,b.m_position.y)<r ) {
b.WakeUp();
b.ApplyForce(new b2Vec2(0,2000000), new b2Vec2(force, b.m_position.y));
}
}
}