See raw JS.
// Cloned by Ian Gilligan on 12 Feb 2019 from World "v0.43 Pool Predictor Prototype" by Ian Gilligan // Please leave this clone trail here. // Cloned by Ian Gilligan on 5 Feb 2019 from World "v0.3 Pool Predictor Prototype" by lillisl2 // Please leave this clone trail here. // Cloned by lillisl2 on 4 Feb 2019 from World "v0.2 Pool Predictor Prototype" by Ian Gilligan // Please leave this clone trail here. // Cloned by Ian Gilligan on 1 Feb 2019 from World "lillisl2 0.2 Pool Predictor Prototype" by lillisl2 // Please leave this clone trail here. // Cloned by lillisl2 on 1 Feb 2019 from World "0.1 Pool Predictor Prototype" by Ian Gilligan // Please leave this clone trail here. // Cloned by Ian Gilligan on 30 Jan 2019 from World "Pool Predictor Prototype" by lillisl2 // Please leave this clone trail here. // Cloned by lillisl2 on 28 Jan 2019 from World "Cloned Bouncy Balls" by Ian Gilligan // Please leave this clone trail here. // Cloned by Ian Gilligan on 28 Jan 2019 from World "Bouncy Balls" by Starter user // Please leave this clone trail here. // ==== Starter World =============================================================================================== // (c) Ancient Brain Ltd. All rights reserved. // This code is only for use on the Ancient Brain site. // This code may be freely copied and edited by anyone on the Ancient Brain site. // This code may not be copied, re-published or used on any other website. // To include a run of this code on another website, see the "Embed code" links provided on the Ancient Brain site. // ================================================================================================================== // Physijs based World // Bouncy balls // =================================================================================================================== // === Start of tweaker's box ======================================================================================== // =================================================================================================================== // The easiest things to modify are in this box. // You should be able to change things in this box without being a JavaScript programmer. // Go ahead and change some of these. What's the worst that could happen? AB.screenshotStep = 50; // Take screenshot on this step. (All resources should have finished loading.) Default 50. // =================================================================================================================== // === Variables & Constants ========================================================================================= // =================================================================================================================== const OBJPATH = "/uploads/gilligi2/"; // path of OBJ and MTL const OBJNAME = "PoolTable.obj"; const MTLNAME = "pooltable.mtl"; const MODELLENGTH = 11054; const MODELWIDTH = 6279; const SCALE = 0.009; const BALLSIZE = 2; // size of each ball const BALLPOS = BALLSIZE * 100; // x,z start position of balls is random in this interval const BALLHEIGHT = BALLSIZE * 2; // y start position of balls const HEAVYIMPACT = 10; // heavy impacts have y velocity greater than this const GROUNDSIZE = 150; // size of table const startRadius = MODELWIDTH * 0.02; // camera start distance const maxRadius = MODELLENGTH * 0.03; // camera max distance const TEXTURE_GROUND = "/uploads/gilligi2/8451323128.png"; //colour of ground (green) const TEXTURE_WALL = "/uploads/lillisl2/8451232143.png"; //colour of walls (brown) const SKYCOLOR = 0xffffff; //colour of sky / background (white) // friction and restitution between 0 and 1: var GROUND_FRICTION = 0.4; // friction of ground const GROUND_RESTITUTION = 0.5; // restitution of ground const WALL_FRICTION = 0.4; // friction of wall const WALL_RESTITUTION = 1; // restitution of wall const BALL_FRICTION = 0.1; // friction of ball const BALL_RESTITUTION = 1; // restitution of ball var LIMIT = [7,7,1,1]; // limit values of each type of balls [yellow, red, black, white] var BALL_CHOICE = 0; // the ball that the user has currently selected const BALL_TYPE = [ // what each value of ball choice (0-3) represent "Yellow", "Red", "Black", "White"]; // define gravity along x,y,z dimensions: var gravity = new THREE.Vector3 (0, -100, 0); const BALL_MASS = 1; // mass of ball const FILE_ARRAY = [ // colours of each ball [yellow, red, black, white] "/uploads/gilligi2/8451323595.png", "/uploads/gilligi2/8451323612.png", "/uploads/gilligi2/8451147306.png", "/uploads/gilligi2/8451147292.png"]; var MIN_POWER = 1; var MAX_POWER = 5; var difficulty = "Easy"; var YOURCOLOR = "None"; var CALCULATED = false; ABWorld.drawCameraControls = false; // =================================================================================================================== // === End of tweaker's box ========================================================================================== // =================================================================================================================== // You will need to be some sort of JavaScript programmer to change things below the tweaker's box. var resourcesLoaded = false; var splashClicked = false; function World() { var textureArray = new Array ( FILE_ARRAY.length ); var ground_texture; var self = this; var GROUND; var table; var p_height = 25; function loadResources() // asynchronous file loads - call initScene() when all finished { var m = new THREE.MTLLoader(); m.setTexturePath (OBJPATH); m.setPath (OBJPATH); m.load ( MTLNAME, function ( materials ) { materials.preload(); var o = new THREE.OBJLoader(); o.setMaterials ( materials ); o.setPath ( OBJPATH ); o.load ( OBJNAME, function ( object ) { table = object; if ( asynchFinished() ) initScene(); }); }); for (var j = 0; j < FILE_ARRAY.length; j++){ startFileLoad (j);}} function startFileLoad(n) // asynchronous file load of texture n { var loader = new THREE.TextureLoader(); loader.load (FILE_ARRAY[n], function (thetexture) { thetexture.minFilter = THREE.LinearFilter; textureArray[n] = thetexture; if (asynchFinished()) initScene(); });} function asynchFinished() // all file loads returned { if (! table){ return false;} return true;} function initScene() // all file loads have returned { // --- Light ------------------------------------------------------------------ var light = new THREE.DirectionalLight(0xFFFFFF, 0.7); // close to origin, high up, works best for shadows light.position.set(0, 40, 0); light.target.position.copy(ABWorld.scene.position); light.castShadow = true; // how far away to draw shadows: light.shadow.camera.left = -20; light.shadow.camera.right = 20; light.shadow.camera.bottom = -20; light.shadow.camera.top = 20; // higher quality shadows at expense of computation time: light.shadow.mapSize.width = 2048; light.shadow.mapSize.height = 2048; light.shadow.bias = -0.1; ABWorld.scene.add(light); // --- Table ------------------------------------------------------------------- table.position.y = 0; table.position.x = -15; table.position.z = 0; ABWorld.scene.add(table); // --- Ground ------------------------------------------------------------------ var ground_material = Physijs.createMaterial(new THREE.MeshStandardMaterial(), GROUND_FRICTION, GROUND_RESTITUTION); // ground as plane allows bounces but seems to be infinite plane var ground = new Physijs.BoxMesh(new THREE.BoxGeometry(MODELLENGTH * SCALE, 1, MODELWIDTH * SCALE), ground_material, 0); ground.position.y = p_height; ground.collisions = 0; ground.receiveShadow = true; //ABWorld.scene.add(ground); GROUND = ground; // --- Wall -------------------------------------------------------------------- var wall_material = Physijs.createMaterial(new THREE.MeshStandardMaterial(), WALL_FRICTION, WALL_RESTITUTION); var wall1 = new Physijs.BoxMesh(new THREE.BoxGeometry(MODELLENGTH * SCALE, 6, MODELWIDTH * SCALE * 0.075), wall_material, 0); wall1.position.z = 28; wall1.collisions = 0; wall1.receiveShadow = true; var wall2 = new Physijs.BoxMesh(new THREE.BoxGeometry(MODELLENGTH * SCALE, 6, MODELWIDTH * SCALE * 0.075), wall_material, 0); wall2.position.z = -28; wall2.collisions = 0; wall2.receiveShadow = true; var wall3 = new Physijs.BoxMesh(new THREE.BoxGeometry(MODELLENGTH * SCALE * 0.05, 6, MODELWIDTH * SCALE), wall_material, 0); wall3.position.x = 52; wall3.collisions = 0; wall3.receiveShadow = true; var wall4 = new Physijs.BoxMesh(new THREE.BoxGeometry(MODELLENGTH * SCALE * 0.05, 6, MODELWIDTH * SCALE), wall_material, 0); wall4.position.x = -52; wall4.collisions = 0; wall4.receiveShadow = true; // --- Bumper -------------------------------------------------------------------- var bumper1 = new Physijs.BoxMesh(new THREE.BoxGeometry(MODELLENGTH * SCALE * 0.35, 6, MODELWIDTH * SCALE * 0.075 * 1.5), wall_material, 0); bumper1.position.z = 23.5; bumper1.position.x = 23.5; bumper1.position.y = -0.1; bumper1.collisions = 0; bumper1.receiveShadow = true; var bumper2 = new Physijs.BoxMesh(new THREE.BoxGeometry(MODELLENGTH * SCALE * 0.35, 6, MODELWIDTH * SCALE * 0.075 * 1.5), wall_material, 0); bumper2.position.z = 23.5; bumper2.position.x = -23.5; bumper2.collisions = 0; bumper2.receiveShadow = true; var bumper3 = new Physijs.BoxMesh(new THREE.BoxGeometry(MODELLENGTH * SCALE * 0.35, 6, MODELWIDTH * SCALE * 0.075 * 1.5), wall_material, 0); bumper3.position.z = -23.5; bumper3.position.x = 23.5; bumper3.position.y = -0.1; bumper3.collisions = 0; bumper3.receiveShadow = true; var bumper4 = new Physijs.BoxMesh(new THREE.BoxGeometry(MODELLENGTH * SCALE * 0.35, 6, MODELWIDTH * SCALE * 0.075 * 1.5), wall_material, 0); bumper4.position.z = -23.5; bumper4.position.x = -23.5; bumper4.collisions = 0; bumper4.receiveShadow = true; var bumper5 = new Physijs.BoxMesh(new THREE.BoxGeometry(MODELLENGTH * SCALE * 0.03, 6, MODELWIDTH * SCALE * 0.55), wall_material, 0); bumper5.position.z = 0; bumper5.position.x = 48; bumper5.receiveShadow = true; var bumper6 = new Physijs.BoxMesh(new THREE.BoxGeometry(MODELLENGTH * SCALE * 0.03, 6, MODELWIDTH * SCALE * 0.55), wall_material, 0); bumper6.position.z = 0; bumper6.position.x = -48; bumper6.receiveShadow = true; ground.add(wall1); ground.add(wall2); ground.add(wall3); ground.add(wall4); ground.add(bumper1); ground.add(bumper2); ground.add(bumper3); ground.add(bumper4); ground.add(bumper5); ground.add(bumper6); ABWorld.scene.add(ground); ABWorld.render(); console.log("Resources loaded."); resourcesLoaded = true;} function increaseFriction(){ if (GROUND_FRICTION + 0.05 < 1.0){ GROUND_FRICTION += 0.05;} else {GROUND_FRICTION = 1.0;} } function decreaseFriction(){ if (GROUND_FRICTION - 0.05 > 0.0){ GROUND_FRICTION -= 0.05;} else {GROUND_FRICTION = 0.0;} } function decreasePowerMin(){ if (MIN_POWER > 1) {MIN_POWER -= 1;}} function increasePowerMin(){ if (MIN_POWER < MAX_POWER) {MIN_POWER += 1;}} function decreasePowerMax(){ if (MIN_POWER < MAX_POWER) {MAX_POWER -= 1;}} function increasePowerMax(){ if (MAX_POWER < 5) {MAX_POWER += 1;}} function selectBall(x) { BALL_CHOICE = x;} function setDifficulty(x){ difficulty = x; } function setColor(x){ YOURCOLOR = x; } function createBall(object) { if ( resourcesLoaded && splashClicked && LIMIT[BALL_CHOICE] !== 0) { var ball_material = Physijs.createMaterial(new THREE.MeshLambertMaterial({map: textureArray[BALL_CHOICE]}), BALL_FRICTION, BALL_RESTITUTION); var ball_geometry = new THREE.SphereGeometry(BALLSIZE, 100, 100); var ball = new Physijs.SphereMesh(ball_geometry, ball_material, BALL_MASS); ball.collisions = 0; ball.castShadow = true; //ball.position.set(1, 40, 1); ball.position.set(object.x, object.y + 2, object.z); ball.addEventListener('collision', function(other_object, relative_velocity, relative_rotation, contact_normal) { var mainImpact = relative_velocity.y; // impact in direction of gravity console.log(Math.abs(mainImpact)); if (Math.abs(mainImpact) > HEAVYIMPACT) // main impact, not lesser ones as it settles { //soundCollision(); } }); ABWorld.scene.add(ball); LIMIT[BALL_CHOICE] -= 1; } } var OURKEYS = [49, 50, 51, 52]; function ourKeys(event) {return(OURKEYS.includes(event.keyCode));} function keyHandler(event) { if (! ABRun.runReady) {return true;} // not ready yet // if not handling this key, send it to default: if (! ourKeys(event)) {return true;} // else handle it and prevent default: if ( event.keyCode == 49 ) {selectBall(0);} else if ( event.keyCode == 50 ) {selectBall(1);} else if ( event.keyCode == 51 ) {selectBall(2);} else if ( event.keyCode == 52 ) {selectBall(3);} event.stopPropagation(); event.preventDefault(); return false; } var startX, startY; var dragevents; // number of events in the current drag function click(event) { var object = (ABWorld.hitsObjectPoint(event.x, event.y, GROUND)); // returns null if no hit if (object !== null){ createBall(object);}} //for future drag functionality //function initDrag (x, y) //{} //function drag (x, y) //{} function initPreOptions() { var s = "<p align=\"center\"><button id='yellowButton'>Yellow</button> <button id='redButton'>Red</button> <button id='blackButton'>Black</button> <button id='whiteButton'>White</button></p>"; $("#user_span2").html(s); s ="<p align=\"center\"><button id='decreaseFrictionButton'>-</button> <button id='increaseFrictionButton'>+</button></p> "; $("#user_span4").html(s); s ="<p align=\"center\"><button id='decreasePowerMinButton'>- Min</button> <button id='increasePowerMinButton'>+ Min</button> <button id='decreasePowerMaxButton'>- Max</button> <button id='increasePowerMaxButton'>+ Max</button></p> "; $("#user_span6").html(s); s = "<p align=\"center\"><button id='easyButton'>Easy</button> <button id='mediumButton'>Medium</button> <button id='hardButton'>Hard</button></p>"; $("#user_span8").html(s); s ="<p align=\"center\"><button id='yourNButton'>None</button> <button id='yourYButton'>Yellow</button> <button id='yourRButton'>Red</button></p>"; $("#user_span10").html(s); //colour pick events document.getElementById("yellowButton").addEventListener("click", function() { selectBall(0); }, false); document.getElementById("redButton").addEventListener("click", function() { selectBall(1); }, false); document.getElementById("blackButton").addEventListener("click", function() { selectBall(2); }, false); document.getElementById("whiteButton").addEventListener("click", function() { selectBall(3); }, false); //friction choice events document.getElementById("decreaseFrictionButton").addEventListener("click", function() { decreaseFriction(); }, false); document.getElementById("increaseFrictionButton").addEventListener("click", function() { increaseFriction(); }, false); //power choice events document.getElementById("decreasePowerMinButton").addEventListener("click", function() { decreasePowerMin(); }, false); document.getElementById("increasePowerMinButton").addEventListener("click", function() { increasePowerMin(); }, false); document.getElementById("decreasePowerMaxButton").addEventListener("click", function() { decreasePowerMax(); }, false); document.getElementById("increasePowerMaxButton").addEventListener("click", function() { increasePowerMax(); }, false); //set difficulty document.getElementById("easyButton").addEventListener("click", function() { setDifficulty("Easy"); }, false); document.getElementById("mediumButton").addEventListener("click", function() { setDifficulty("Medium"); }, false); document.getElementById("hardButton").addEventListener("click", function() { setDifficulty("Hard"); }, false); // set the colour of balls your playing as document.getElementById("yourNButton").addEventListener("click", function() { setColor("None"); }, false); document.getElementById("yourYButton").addEventListener("click", function() { setColor("Yellow"); }, false); document.getElementById("yourRButton").addEventListener("click", function() { setColor("Red"); }, false); //document.getElementById("idButton").addEventListener("click", function() { func(var); }, false); } function initPostOptions() { } function updatePreHUD() { $("#user_span1").html("<p align=\"center\">Ball Selected: <b>"+ BALL_TYPE[BALL_CHOICE] + "</b></p>"); $("#user_span3").html("<p align=\"center\">Ground Friction: <b>" + Number.parseFloat(GROUND_FRICTION).toFixed(2) + "</b></p>"); $("#user_span5").html("<p align=\"center\">Power: <b>" + MIN_POWER + " to " + MAX_POWER + "</b></p>"); $("#user_span7").html("<p align=\"center\">The Difficultly is set to: <b>" + difficulty + "</b></p>"); $("#user_span9").html("<p align=\"center\">Your Color: <b>" + YOURCOLOR + "</b></p>"); } // --- public interface ---------------------------------------------------------------------- this.newRun = function() { ABWorld.init3d(startRadius, maxRadius, SKYCOLOR); // sets up renderer, scene, camera initPreOptions(); // can adjust renderer: ABWorld.renderer.shadowMap.enabled = true; // scene is Physijs.Scene, not THREE.Scene // can adjust scene - change gravity from default: ABWorld.scene.setGravity ( gravity ); loadResources(); // asynchronous file loads // calls initScene() when all done ABWorld.lookat.copy ( ABWorld.scene.position ); ABWorld.scene.simulate(); // Physics simulate - runs on independent timer to AB nextStep // user actions document.onkeydown = keyHandler; document.ondblclick = click; //ABHandler.initTouchDrag = initDrag; //ABHandler.touchDrag = drag //ABHandler.initMouseDrag = initDrag; //ABHandler.mouseDrag = drag }; this.nextStep = function() // not used { if (CALCULATED === false){ updatePreHUD();} else { initPostOptions(); updatePostHUD();} }; } // --- Splash screen -------------------------------------------------------------- AB.newSplash ("Demo of Physics API"); // when user clicks/touches button on splash screen, audio starts and run starts: $("#splashbutton").click (function() { AB.removeSplash(); // remove splash screen splashClicked = true; });