=== File http://localhost/subjectPrograms/ClientSideOnly/ball_pool/js/Main.js === 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 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 ); // 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 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 = 'Hello!

This is how it works:

1. Drag a ball.
2. Click on the background.
3. Shake your browser.
4. Double click.
5. Play!
'; >>> 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 = 0 + delta[0]; >>> world.m_gravity.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; } } } // .. 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; } Total lines (including un-executable): 502 Total executable lines: 256 Covered lines: 232 Coverage: ~90% Errors:0 errors/warningsh in the script: