Code viewer for World: Stacker Builder
AB.loadingScreen();                
/////////////////////////////////////////////////////////////////////////
//Music//////////////Credit:
const MUSICFILE = '/uploads/thomasmoriarty/music1.mp3';
AB.backgroundMusic ( MUSICFILE );

/////////////////////////////////////////////////////////////////////////
//SKYBOX//////////////Credit: 

 const SKYBOX_ARRAY = [										 
                "/uploads/thomasmoriarty/posz_4.jpg",
                "/uploads/thomasmoriarty/posz_4.jpg",
                "/uploads/thomasmoriarty/posz_4.jpg",
                "/uploads/thomasmoriarty/posz_4.jpg",
                "/uploads/thomasmoriarty/posz_4.jpg",
                "/uploads/thomasmoriarty/posz_4.jpg"
                ];
			
////////////////////////////////////////////////////////////////////////
//Constants//

const skycolor          = 'lightblue'; 
const boxcolor          = 'black';
const objectsize    = 100;                  // size of object   
const startRadius   = 3000;                 // distance from centre we start the camera at
const maxRadius     = startRadius * 10;     // maximum distance from camera we render things 
const floor = "/uploads/thomasmoriarty/floor.jpg"

world.gravity.set(0, -10, 0);
    
////////////////////////////////////////////////////////////////////////
//Variables//
// the object is a cube (each dimension equal):

var score = 0;
var s = 0;
var x = 10;
var objectlength = 400
   
var shape       = new THREE.BoxGeometry ( objectlength , objectlength, 200 );
var material    = new THREE.MeshBasicMaterial ( { color: boxcolor.toLowerCase() } );
var theobject   = new THREE.Mesh ( shape, material );

 addLayer(0, 0, originalBoxSize, originalBoxSize);

 addLayer(-10, 0, originalBoxSize, originalBoxSize, "x");


function animation()
{
    const speed = 0.15;
    
    const topLayer = stack[stack.length - 1];
    topLayer.threejs.position[topLayer.direction] += speed;
}



const REQUESTWORLDSTATE = 0;
const SENDWORLDSTATE = 1;
var joined = false;


// when you join a World:
var data = [ REQUESTWORLDSTATE , null ];
AB.socketOut ( data );    // broadcast to existing clients 

// define function for incoming messages 
AB.socketUserlist = function ( data )   // data = array [ messagetype, payload ]
{
  if ( ( joined ) && ( data[0] == REQUESTWORLDSTATE ) ) 
  {
     // tell the other client what the world state is
     var data = [ SENDWORLDSTATE, worldstate ];
     AB.socketOut ( data );
 }

  else if ( ( ! joined ) && ( data[0] == SENDWORLDSTATE ) ) 
  {
    var worldstate = data[1];
    // set my world to match  worldstate    
    joined = true;
    // note with more than 2 players: even if multiple clients respond with the world state, I will only process once, since now joined = true 
  }
};


////////////////////////////////////////////////////////////////////////
//Main world function///

AB.world.newRun = function() 
{
    // start a 3D scene: 
    ABWorld.init3d ( startRadius, maxRadius, skycolor ); 
    
    let gameStarted = false;
    stack = [];
    overhang = [];
    
    window.addEventListener("click", () => {
        if (!gameStarted) {
            renderer.setAnimationLoop(animation);
            gameStarted = true;
        } else {
            
            const topLayer = stack[stack.length - 1];
            const direction = topLayer.direction;
            
            const nextX = direction = "x" ? 0 : -10;
            const nextZ = direction = "z" ? 0 : -10;
            const newWidth = objectlength;
            const newDepth = objectlength;
            const nextDirection = direction = "x" ? "z" : "x";
            
            addLayer(nextX, nextZ, newWidth, newDepth, nextDirection);

        }
    });
    // add the object to the scene:
    ABWorld.scene.add ( theobject );
    
    function generateBox(x, y, z, width, depth, falls) {
     const geometry = new THREE.BoxGeometry(width, boxHeight, depth);
     const color = new THREE.Color(`hsl(${30 + stack.length * 4}, 100%, 50%)`);
     const material = new THREE.MeshLambertMaterial({ color });
     const mesh = new THREE.Mesh(geometry, material);
     mesh.position.set(x, y, z);
     scene.add(mesh);
    }  
    
function addlayer(x, z, width, depth, direction) {
    const y = objectlength * stack.length;
    const layer = generateBox(x, y, z, width, depth, false);
    layer.direction = direction;
    stack.push(layer);
}
 
function addOverhang(x, z, width, depth) {
  const y = objectlength * (stack.length - 1); 
  const overhang = generateBox(x, y, z, width, depth, true);
  overhangs.push(overhang);
}
    
    const aspect = window.innerWidth / window.innerHeight;
    const width = 10;
    const height = width / aspect;
    
    const camera = new THREE.OrthographicCamera(
        width / -2,
        width / -2,
        height / -2,
        height / -2,
        1,
        100
        );

    camera.position.set(4,4,4);
    camera.lookAt(0,0,0);

     const texturefile  = '/uploads/thomasmoriarty/car.jpeg';
     var   loader       = new THREE.TextureLoader();
     


    
    //The skybox loads the background textures//
    ABWorld.scene.background = new THREE.CubeTextureLoader().load ( SKYBOX_ARRAY,	function() 
	 { 
		ABWorld.render(); 
		AB.removeLoading();
		AB.runReady = true; 		
	 });
	 
	 loader.load ( texturefile, function ( thetexture ) 
    {			 
        thetexture.minFilter  = THREE.LinearFilter;
        theobject.material    = new THREE.MeshBasicMaterial ( { map: thetexture } );
    }); 
	 
	

};

AB.world.nextStep = function()
{
    theobject.position.x = theobject.position.x       
};

AB.newSplash (" <H2> Welcome to Franks Tower Building Inc, Your job is to build the biggest tower in all the land, You do this by pressing space at the right time but careful! Do it too early or too late and we might be saying goodbye to tower builders of the year, can I count on you? </H2>");


// define what splash screen click does:

$("#splashbutton").click ( function ()        
{
  AB.removeSplash();                    
  AB.runReady = true;              
});