var canvas;
var delta = [ 0, 0 ];
var stage = [ window.screenX, window.screenY, window.innerWidth, window.innerHeight ];
getBrowserDimensions();
var themes = [ [ "#10222B", "#95AB63", "#BDD684", "#E2F0D6", "#F6FFE0" ],
[ "#362C2A", "#732420", "#BF734C", "#FAD9A0", "#736859" ],
[ "#0D1114", "#102C2E", "#695F4C", "#EBBC5E", "#FFFBB8" ],
[ "#2E2F38", "#FFD63E", "#FFB54B", "#E88638", "#8A221C" ],
[ "#121212", "#E6F2DA", "#C9F24B", "#4D7B85", "#23383D" ],
[ "#343F40", "#736751", "#F2D7B6", "#BFAC95", "#8C3F3F" ],
[ "#000000", "#2D2B2A", "#561812", "#B81111", "#FFFFFF" ],
[ "#333B3A", "#B4BD51", "#543B38", "#61594D", "#B8925A" ] ];
var theme;
var worldAABB, world, iterations = 1, timeStep = 1 / 20;
var walls = [];
var wall_thickness = 200;
var wallsSetted = false;
var bodies, elements, text;
var createMode = false;
var destroyMode = false;
var isMouseDown = false;
var mouseJoint;
var mouseX = 0;
var mouseY = 0;
var orientation = { x: 0, y: 1 };
var PI2 = Math.PI * 2;
var timeOfLastTouch = 0;
init();
play();
function init() {
canvas = document.getElementById( 'canvas' );
document.onmousedown = onDocumentMouseDown;
document.onmouseup = onDocumentMouseUp;
document.onmousemove = onDocumentMouseMove;
document.ondblclick = onDocumentDoubleClick;
document.addEventListener( 'touchstart', onDocumentTouchStart, false );
document.addEventListener( 'touchmove', onDocumentTouchMove, false );
document.addEventListener( 'touchend', onDocumentTouchEnd, false );
window.addEventListener( 'deviceorientation', onWindowDeviceOrientation, false );
// init box2d
worldAABB = new b2AABB();
worldAABB.minVertex.Set( -200, -200 );
worldAABB.maxVertex.Set( screen.width + 200, screen.height + 200 );
world = new b2World( worldAABB, new b2Vec2( 0, 0 ), true );
setWalls();
reset();
}
function play() {
setInterval( loop, 1000 / 40 );
}
function reset() {
var i;
if ( bodies ) {
for ( i = 0; i < bodies.length; i++ ) {
var body = bodies[ i ]
canvas.removeChild( body.GetUserData().element );
world.DestroyBody( body );
body = null;
}
}
// color theme
theme = themes[ Math.random() * themes.length >> 0 ];
document.body.style[ 'backgroundColor' ] = theme[ 0 ];
bodies = [];
elements = [];
createInstructions();
for( i = 0; i < 10; i++ ) {
createBall();
}
}
//
function onDocumentMouseDown() {
isMouseDown = true;
return false;
}
function onDocumentMouseUp() {
isMouseDown = false;
return false;
}
function onDocumentMouseMove( event ) {
mouseX = event.clientX;
mouseY = event.clientY;
}
function onDocumentDoubleClick() {
reset();
}
function onDocumentTouchStart( event ) {
if( event.touches.length == 1 ) {
event.preventDefault();
// Faking double click for touch devices
var now = new Date().getTime();
if ( now - timeOfLastTouch < 250 ) {
reset();
return;
}
timeOfLastTouch = now;
mouseX = event.touches[ 0 ].pageX;
mouseY = event.touches[ 0 ].pageY;
isMouseDown = true;
}
}
function onDocumentTouchMove( event ) {
if ( event.touches.length == 1 ) {
event.preventDefault();
mouseX = event.touches[ 0 ].pageX;
mouseY = event.touches[ 0 ].pageY;
}
}
function onDocumentTouchEnd( event ) {
if ( event.touches.length == 0 ) {
event.preventDefault();
isMouseDown = false;
}
}
function onWindowDeviceOrientation( event ) {
if ( event.beta ) {
orientation.x = Math.sin( event.gamma * Math.PI / 180 );
orientation.y = Math.sin( ( Math.PI / 4 ) + event.beta * Math.PI / 180 );
}
}
//
function createInstructions() {
var size = 250;
var element = document.createElement( 'div' );
element.width = size;
element.height = size;
element.style.position = 'absolute';
element.style.left = -200 + 'px';
element.style.top = -200 + 'px';
element.style.cursor = "default";
canvas.appendChild(element);
elements.push( element );
var circle = document.createElement( 'canvas' );
circle.width = size;
circle.height = size;
var graphics = circle.getContext( '2d' );
graphics.fillStyle = theme[ 3 ];
graphics.beginPath();
graphics.arc( size * .5, size * .5, size * .5, 0, PI2, true );
graphics.closePath();
graphics.fill();
element.appendChild( circle );
text = document.createElement( 'div' );
text.onSelectStart = null;
text.innerHTML = 'Love Forever!
You may only be one person to the world but you may be the world to one person.
I had give up my life if I could command one smille of your eyes, one touch of your hand.
I love You!';
text.style.color = theme[1];
text.style.position = 'absolute';
text.style.left = '0px';
text.style.top = '0px';
text.style.fontFamily = 'Georgia';
text.style.textAlign = 'center';
element.appendChild(text);
text.style.left = ((250 - text.clientWidth) / 2) +'px';
text.style.top = ((250 - text.clientHeight) / 2) +'px';
var b2body = new b2BodyDef();
var circle = new b2CircleDef();
circle.radius = size / 2;
circle.density = 1;
circle.friction = 0.3;
circle.restitution = 0.3;
b2body.AddShape(circle);
b2body.userData = {element: element};
b2body.position.Set( Math.random() * stage[2], Math.random() * -200 );
b2body.linearVelocity.Set( Math.random() * 400 - 200, Math.random() * 400 - 200 );
bodies.push( world.CreateBody(b2body) );
}
function createBall( x, y ) {
var x = x || Math.random() * stage[2];
var y = y || Math.random() * -200;
var size = (Math.random() * 100 >> 0) + 20;
var element = document.createElement("canvas");
element.width = size;
element.height = size;
element.style['position'] = 'absolute';
element.style['left'] = -200 + 'px';
element.style['top'] = -200 + 'px';
var graphics = element.getContext("2d");
var num_circles = Math.random() * 10 >> 0;
for (var i = size; i > 0; i-= (size/num_circles)) {
graphics.fillStyle = theme[ (Math.random() * 4 >> 0) + 1];
graphics.beginPath();
graphics.arc(size * .5, size * .5, i * .5, 0, PI2, true);
graphics.closePath();
graphics.fill();
}
canvas.appendChild(element);
elements.push( element );
var b2body = new b2BodyDef();
var circle = new b2CircleDef();
circle.radius = size >> 1;
circle.density = 1;
circle.friction = 0.3;
circle.restitution = 0.3;
b2body.AddShape(circle);
b2body.userData = {element: element};
b2body.position.Set( x, y );
b2body.linearVelocity.Set( Math.random() * 400 - 200, Math.random() * 400 - 200 );
bodies.push( world.CreateBody(b2body) );
}
//
function loop() {
if (getBrowserDimensions()) {
setWalls();
}
delta[0] += (0 - delta[0]) * .5;
delta[1] += (0 - delta[1]) * .5;
world.m_gravity.x = orientation.x * 350 + delta[0];
world.m_gravity.y = orientation.y * 350 + delta[1];
mouseDrag();
world.Step(timeStep, iterations);
for (i = 0; i < bodies.length; i++) {
var body = bodies[i];
var element = elements[i];
element.style.left = (body.m_position0.x - (element.width >> 1)) + 'px';
element.style.top = (body.m_position0.y - (element.height >> 1)) + 'px';
if (element.tagName == 'DIV') {
var rotationStyle = 'rotate(' + (body.m_rotation0 * 57.2957795) + 'deg)';
text.style.WebkitTransform = rotationStyle;
text.style.MozTransform = rotationStyle;
text.style.OTransform = rotationStyle;
// text.style.MsTransform = rotationStyle;
}
}
}
// .. BOX2D UTILS
function createBox(world, x, y, width, height, fixed) {
if (typeof(fixed) == 'undefined') {
fixed = true;
}
var boxSd = new b2BoxDef();
if (!fixed) {
boxSd.density = 1.0;
}
boxSd.extents.Set(width, height);
var boxBd = new b2BodyDef();
boxBd.AddShape(boxSd);
boxBd.position.Set(x,y);
return world.CreateBody(boxBd);
}
function mouseDrag()
{
// mouse press
if (createMode) {
createBall( mouseX, mouseY );
} else if (isMouseDown && !mouseJoint) {
var body = getBodyAtMouse();
if (body) {
var md = new b2MouseJointDef();
md.body1 = world.m_groundBody;
md.body2 = body;
md.target.Set(mouseX, mouseY);
md.maxForce = 30000 * body.m_mass;
md.timeStep = timeStep;
mouseJoint = world.CreateJoint(md);
body.WakeUp();
} else {
createMode = true;
}
}
// mouse release
if (!isMouseDown) {
createMode = false;
destroyMode = false;
if (mouseJoint) {
world.DestroyJoint(mouseJoint);
mouseJoint = null;
}
}
// mouse move
if (mouseJoint) {
var p2 = new b2Vec2(mouseX, mouseY);
mouseJoint.SetTarget(p2);
}
}
function getBodyAtMouse() {
// Make a small box.
var mousePVec = new b2Vec2();
mousePVec.Set(mouseX, mouseY);
var aabb = new b2AABB();
aabb.minVertex.Set(mouseX - 1, mouseY - 1);
aabb.maxVertex.Set(mouseX + 1, mouseY + 1);
// Query the world for overlapping shapes.
var k_maxCount = 10;
var shapes = new Array();
var count = world.Query(aabb, shapes, k_maxCount);
var body = null;
for (var i = 0; i < count; ++i) {
if (shapes[i].m_body.IsStatic() == false) {
if ( shapes[i].TestPoint(mousePVec) ) {
body = shapes[i].m_body;
break;
}
}
}
return body;
}
function setWalls() {
if (wallsSetted) {
world.DestroyBody(walls[0]);
world.DestroyBody(walls[1]);
world.DestroyBody(walls[2]);
world.DestroyBody(walls[3]);
walls[0] = null;
walls[1] = null;
walls[2] = null;
walls[3] = null;
}
walls[0] = createBox(world, stage[2] / 2, - wall_thickness, stage[2], wall_thickness);
walls[1] = createBox(world, stage[2] / 2, stage[3] + wall_thickness, stage[2], wall_thickness);
walls[2] = createBox(world, - wall_thickness, stage[3] / 2, wall_thickness, stage[3]);
walls[3] = createBox(world, stage[2] + wall_thickness, stage[3] / 2, wall_thickness, stage[3]);
wallsSetted = true;
}
// BROWSER DIMENSIONS
function getBrowserDimensions() {
var changed = false;
if (stage[0] != window.screenX) {
delta[0] = (window.screenX - stage[0]) * 50;
stage[0] = window.screenX;
changed = true;
}
if (stage[1] != window.screenY) {
delta[1] = (window.screenY - stage[1]) * 50;
stage[1] = window.screenY;
changed = true;
}
if (stage[2] != window.innerWidth) {
stage[2] = window.innerWidth;
changed = true;
}
if (stage[3] != window.innerHeight) {
stage[3] = window.innerHeight;
changed = true;
}
return changed;
}