This is a simple example of using three JS as a 3d renderer and p2.js as 2d physics engine, to create a powerful 2.5D effect. A 2d physics engine is way faster and easier to handle then any 3d physics engine, perfect for HTML5 applications on desktop or mobile devices.
The script below is very simple and straight forward, it dosen’t include the Debug view you see in the top left to keep things as simple as possible. The script creates a 3d world and a 2d physics world, every object in the 3d world is connected with an object in the 2d physics world. The 2d physics world is simulated and the 3d world just follows this simulation. Each time the 2d physics world gets updated all the connected 3d bodies get an update as well.
This is a simple example of using three JS as a 3d renderer and p2.js as 2d physics engine, to create a powerful 2.5D effect. A 2d physics engine is way faster and easier to handle then any 3d physics engine, perfect for HTML5 applications on desktop or mobile devices.
apply Physics
(Push to add new boxes, use mouse to zoom and pan around)
//SET UP three JS SCENE
var scene = new THREE.Scene();//CREATE NEW THREE JS SCENE
var SCREEN_WIDTH = window.innerWidth, SCREEN_HEIGHT = window.innerHeight;
var renderer = new THREE.WebGLRenderer({antialias:true}); //INIT NEW THREE JS RENDERER
renderer.setClearColor(new THREE.Color('lightgrey'), 1) //SET BG COLOR
renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT); // SET SIZE
document.body.appendChild( renderer.domElement ); //APPLY CANVAS TO BODY
renderer.domElement.id = "canvas_threeJS";//ADD ID TO CANVAS
//ADD CAMERA TO THE SCENE
var VIEW_ANGLE = 45, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 0.1, FAR =1000;
var camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR);
camera.position.set(-4,6,8); //SET CAMERA POITION
scene.add(camera);
//HANDLE WINDOW RESIZE
window.addEventListener('resize', function(){
renderer.setSize( window.innerWidth, window.innerHeight )
camera.aspect = window.innerWidth / window.innerHeight
camera.updateProjectionMatrix();
}, false);
//ADD AMBIENT LIGHT
var ambientLight = new THREE.AmbientLight(0x404040);
scene.add(ambientLight)
// CONTROLS
var controls = new THREE.OrbitControls(camera);
controls.maxDistance = 14;
controls.noPan = true;
controls.maxPolarAngle = 1.4;
//ADD POINT LIGHT
var light = new THREE.PointLight(0xffffff,.7);
light.position.set(0,7,3);
scene.add(light);
//INIT PHYSICS
var world = new p2.World();
world.sleepMode = p2.World.BODY_SLEEPING;
//ADD EVENT LISTENER FOR BUTTON
document.getElementById("btn_add").onclick = addBox;
//ADD BACKGROUND CUBE
addBackground();
//START RENDER
update();
//ADD SKYBOX/BACKGROUND FUNCTION
function addBackground()
{
//CREATE NEW TEXTURE
var skyBoxTexture = new THREE.ImageUtils.loadTexture( 'assets/grid.png' );
skyBoxTexture.wrapS = skyBoxTexture.wrapT = THREE.RepeatWrapping;
skyBoxTexture.repeat.set( 4, 4 );
//CREATE MATERIAL FROM TEXTURE
var floorMat = new THREE.MeshPhongMaterial( { map: skyBoxTexture, side: THREE.BackSide,shininess: 1} );
//CREATE BOX WITH MATERIAL
var skyBox = new THREE.Mesh(new THREE.BoxGeometry(20,20,20), floorMat);
skyBox.position.y += 10;
scene.add(skyBox);
//CREATE P2 PHYSICS GROUND PLANE
var planeShape = new p2.Plane();
var planeBody = new p2.Body({position:[0,0]});
planeBody.name = "ground";
planeBody.data = skyBox;
planeBody.addShape(planeShape);
world.addBody(planeBody);
}
//ADD A NEW BOX FUNCTION
function addBox()
{
//CREATE RANDOM WIDTH AND HEIGHT SIZE
var w = 0.1+Math.random();
var h = 0.1+Math.random();
//ADD ELEMENT AT RANDOM X POSITION
var x = (Math.random()*10)-5;
var y = 3;
//CREATE NEW MATERIAL WITH RANDOM COLOR
var material = new THREE.MeshPhongMaterial( { color: getRandomColor() } );
//CREATE CUBE WITH RANDOM WIDTH AND HEIGHT
var cube = new THREE.Mesh(new THREE.BoxGeometry(w, h, .5), material);
cube.position.set(x,y,0)
scene.add(cube);
//CREATE P2 PHYSICS BOX AT RANDOM POSITION
var boxShape = new p2.Rectangle(w,h);
var boxBody = new p2.Body({ mass:1, position:[x,y],angularVelocity:1 });
boxBody.allowSleep = true;
boxBody.sleepSpeedLimit = 1;
boxBody.sleepTimeLimit = 1;
boxBody.data = cube; // ADD 3d OBJECT AS DATA VALUE
boxBody.name="box"; //ADD NAME TO THE P2 BODY
boxBody.addShape(boxShape);
world.addBody(boxBody);
}
//CREATES A RANDOM COLOR
function getRandomColor() {
var letters = '0123456789ABCDEF'.split('');
var color = '#';
for (var i = 0; i < 6; i++ ) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}
//UPDATE FUNCTION
function update()
{
//KEEP RENDERING
requestAnimationFrame( update );
//UPDATE PHYSICS
world.step(1/60);
//FOR EACH OBJECT IN P2 PHYSICS WORLD
for (var i = 0; i < world.bodies.length; i++)
{
//IF IT IS A BOX -> UPDATE POSITION AND ROTATION ACCORDINGLY
if(world.bodies[i].name == "box")
{
world.bodies[i].data.position.set(world.bodies[i].position[0],world.bodies[i].position[1],0);
world.bodies[i].data.rotation.z = world.bodies[i].angle;
}
};
//UPDATE 3D SCENE
renderer.render( scene, camera );
};
};