Code viewer for World: Port of flying birds (clo...
AB.clockTick       = 1; // Speed of run: Step every n milliseconds. Default 100.
AB.maxSteps        = 65545;	// Length of run: Maximum length of run in steps. Default 1000.
AB.screenshotStep  = 50;   // For automatic generation of World images. Take screenshot on this step. (All resources should have finished loading.) Default 50.
AB.drawRunControls = true;
threeworld.drawCameraControls = false;var MOVESPEED = 3;

var GRAVITY = 6;
var FogDistance = 3000;
var FOV = 90;
const startRadius = 150;                  // distance from centre we start the camera at
const maxRadius = startRadius * 20;     // maximum distance from camera we render things 
const floorTextureFile = "/uploads/goobert/grass2.png" // floor texture

 const SKYBOX_ARRAY = [ // can load skybox of other user:
                "/uploads/starter/dawnmountain-xpos.png",
                "/uploads/starter/dawnmountain-xneg.png",
                "/uploads/starter/dawnmountain-ypos.png",
                "/uploads/starter/dawnmountain-yneg.png",
                "/uploads/starter/dawnmountain-zpos.png",
                "/uploads/starter/dawnmountain-zneg.png"
                ];

const mixers = [];
const clock = new THREE.Clock();

// AB customisations
// Select text and "Code Help" to see what these mean:

ABHandler.MAXCAMERAPOS      = maxRadius;
ABWorld.drawCameraControls  = false;  

THREE.PointerLockControls = function ( camera ) {

	var scope = this;

// 	camera.rotation.set( 0, 0, 0 );

	var pitchObject = new THREE.Object3D();
	pitchObject.add( camera );

	var yawObject = new THREE.Object3D();
	yawObject.position.y = 10;
	yawObject.add( pitchObject );

	var PI_2 = Math.PI / 2;

	var onMouseMove = function ( event ) {

		if ( scope.enabled === false ) return;

		var movementX = event.movementX || event.mozMovementX || event.webkitMovementX || 0;
		var movementY = event.movementY || event.mozMovementY || event.webkitMovementY || 0;

		yawObject.rotation.y -= movementX * 0.002;
		pitchObject.rotation.x -= movementY * 0.002;

		pitchObject.rotation.x = Math.max( - PI_2, Math.min( PI_2, pitchObject.rotation.x ) );
	};

	this.dispose = function () {

		document.removeEventListener( 'mousemove', onMouseMove, false );
	};

	document.addEventListener( 'mousemove', onMouseMove, false );

	this.enabled = false;

	this.getObject = function () {

		return yawObject;

	};

	this.getDirection = function () {

		// assumes the camera itself is not rotated

		var direction = new THREE.Vector3( 0, 0, 0 );
		var rotation = new THREE.Euler( 0, 0, 0 );

	}(); 

}; //==============================================================================

	AB.world.newRun = function() // this is called when the game is run
	{
        var camera, controls;
    	var objects = [];
    	var raycaster; 
        var moveForward = false;
    	var moveBackward = false;
    	var moveLeft = false;
    	var moveRight = false;
    	var canJump = false;
    	var prevTime = performance.now();
    	var velocity = new THREE.Vector3();
    	var direction = new THREE.Vector3();
    	var vertex = new THREE.Vector3();
    	var color = new THREE.Color();
	    ABWorld.init3d ( startRadius, maxRadius, color );  // init the 3d world             
	    initLights();     
	    loadModels(); 
	    
	    // skybox: 
        ABWorld.scene.background = new THREE.CubeTextureLoader().load ( SKYBOX_ARRAY );
        var WorldSize = 10000;
	    var BlockSize = 50;

	    var floorGeometry = new THREE.PlaneBufferGeometry( WorldSize, WorldSize );
        floorGeometry.rotateX( - Math.PI / 2 );

        // loading the floor texture
        var floorTexture = new THREE.ImageUtils.loadTexture ( floorTextureFile );
        floorTexture.minFilter = THREE.LinearFilter;
        floorTexture.wrapS = floorTexture.wrapT = THREE.RepeatWrapping;

        // world floor texture size and location
        floorTexture.offset.set( 0, 0 );
        floorTexture.repeat.set( WorldSize / BlockSize, WorldSize / BlockSize );
        var floor = new THREE.Mesh(floorGeometry, new THREE.MeshBasicMaterial({map : floorTexture}));
        floor.position.set(0,-500,0);
        threeworld.scene.add(floor);
        
        var onKeyDown = function ( event ) {

	    	switch ( event.keyCode ) {

				case 38: // up
				case 87: // w
					moveForward = true;
				// 	AB.backgroundMusic ( FOOTSTEPS );
					break;
                
                case 38: // up
                case 16: // shift
                    MOVESPEED = 7; // 
                    break;

				case 37: // left
				case 65: // a
					moveLeft = true; break;

				case 40: // down
				case 83: // s
					moveBackward = true;
					break;

				case 39: // right
				case 68: // d
					moveRight = true;
					break;

				case 32: // space
					if ( canJump === true ) velocity.y += 350;
					canJump = false;
					break;

			}

		};
		var onKeyUp = function ( event ) {

			switch( event.keyCode ) {

				case 38: // up
				case 87: // w
					moveForward = false;
					break;

                case 38: // up
                case 16: // shift
                    MOVESPEED = 3; // 
                    break;
                
				case 37: // left
				case 65: // a
					moveLeft = false;
					break;

				case 40: // down
				case 83: // s
					moveBackward = false;
                    break;

				case 39: // right
				case 68: // d
					moveRight = false;
					break;
			}

		};

	    camera = new THREE.PerspectiveCamera( FOV );
        threeworld.camera = camera;
	    threeworld.init3d ( 0,0, 0x7ec0ee  );

	    var light = new THREE.HemisphereLight( 0xeeeeff, 0x777788, 0.75 );
		light.position.set( 0.5, 1, 0.75 );
		threeworld.scene.add( light );

		threeworld.scene.fog = new THREE.Fog( 0xffffff, 0, FogDistance );

        controls = new THREE.PointerLockControls( camera );
        threeworld.scene.add( controls.getObject() );
    
        // event listener for key presses
		document.addEventListener( 'keyup', onKeyUp, false );
		document.addEventListener( 'keydown', onKeyDown, false );
		
		raycaster = new THREE.Raycaster( new THREE.Vector3(), new THREE.Vector3( 0, - 1, 0 ), 0, 10 );

	    $("#user_span1").html("Use <b>WASD</b> or <b>Arrows</b> to move and <b>shift</b> to run any direction.");
	    
	   // var blocker = $("#user_span2");
	    $("#user_span2").html("<p><b>Click screen to enable mouse controls</b></p>");
	    
	    var havePointerLock = 'pointerLockElement' in document || 'mozPointerLockElement' in document || 'webkitPointerLockElement' in document;
        console.log(havePointerLock);
        if ( havePointerLock ) {

			var element = document.body;

			var pointerlockchange = function ( event ) {

				if ( document.pointerLockElement === element || document.mozPointerLockElement === element || document.webkitPointerLockElement === element ) {

					controls.enabled = true;
					$("#user_span2").html("");

				} else
				{
					controls.enabled = false;
					$("#user_span2").html("<p><b>Click onto the game to return playing.</b></p>");

				}

			};

			var pointerlockerror = function ( event ) {

				console.error("pointerlockerror");

			};

			// Hook pointer lock state change events
			document.addEventListener( 'pointerlockchange', pointerlockchange, false );
			document.addEventListener( 'mozpointerlockchange', pointerlockchange, false );
			document.addEventListener( 'webkitpointerlockchange', pointerlockchange, false );

			document.addEventListener( 'pointerlockerror', pointerlockerror, false );
			document.addEventListener( 'mozpointerlockerror', pointerlockerror, false );
			document.addEventListener( 'webkitpointerlockerror', pointerlockerror, false );

			document.addEventListener( 'click', function ( event ) {

				// Ask the browser to lock the pointer
				element.requestPointerLock = element.requestPointerLock || element.mozRequestPointerLock || element.webkitRequestPointerLock;
				element.requestPointerLock();

			}, false );

		} else {

			$("#user_span1").html('<p>Your browser doesn\'t seem to support Pointer Lock API</p>');

		}
		


	}; //==============================================================================

	this.nextStep = function()		 
	{
        raycaster.ray.origin.copy( controls.getObject().position ); // this is the player's position
        raycaster.ray.origin.y -= 10; // this is the player's height

        var intersections = raycaster.intersectObjects( objects );

        var onObject = intersections.length > 0;

        var time = performance.now();
        var delta = ( time - prevTime ) / 1000;

        velocity.x -= velocity.x * 10.0 * delta;
        velocity.z -= velocity.z * 10.0 * delta;

        velocity.y -= GRAVITY;


        direction.z = Number( moveForward ) - Number( moveBackward );
        direction.x = Number( moveLeft ) - Number( moveRight );
        direction.normalize(); // this ensures consistent movements in all directions

        if ( moveForward || moveBackward ) velocity.z -= direction.z * 400.0 * MOVESPEED * delta;
        
        if ( moveLeft || moveRight ) velocity.x -= direction.x * 400.0 * MOVESPEED * delta;

        if ( onObject === true ) {

            velocity.y = Math.max( 0, velocity.y );
            canJump = true;

        }

        controls.getObject().translateX( velocity.x * delta );
        controls.getObject().translateY( velocity.y * delta );
        controls.getObject().translateZ( velocity.z * delta );

        if ( controls.getObject().position.y < 10 ) {

            velocity.y = 0;
            controls.getObject().position.y = 10;

            canJump = true;

        }

        prevTime = time;

	};

function loadModels() 
{
  const loader = new THREE.GLTFLoader();

  const onLoad = ( gltf, position ) => 
  {
    const model = gltf.scene.children[ 0 ];
    model.position.copy( position );

    const animation = gltf.animations[ 0 ];

    const mixer = new THREE.AnimationMixer( model );
    mixers.push( mixer );

    const action = mixer.clipAction( animation );
    action.play();

    ABWorld.scene.add( model );
  };

  const VegetaPosition      = new THREE.Vector3 ( 0,     0,   50 );
  const flamingoPosition    = new THREE.Vector3 ( 10,   0, -60 );
  const storkPosition       = new THREE.Vector3 ( 0,   -10, -70 );

 // can load 3D models of other user:
  loader.load ( '/uploads/liam/steve.glb',   glb => onLoad ( glb, VegetaPosition )   );
  loader.load ( '/uploads/liam/sevewalk.glb', gltf => onLoad ( gltf, flamingoPosition ) );
  loader.load ( '/uploads/humphrys/sevewalk.glb',    gltf => onLoad ( gltf, storkPosition )    );
  
}



function initLights() 
// the lights are needed to show up models
{
  const ambientLight = new THREE.AmbientLight( 0xffffff, 1 );
  ABWorld.scene.add( ambientLight );

  const frontLight = new THREE.DirectionalLight( 0xffffff, 1 );
  frontLight.position.set( 10, 10, 10 );

  const backLight = new THREE.DirectionalLight( 0xffffff, 1 );
  backLight.position.set( -10, 10, -10 );

  ABWorld.scene.add( frontLight, backLight );
}


// background music 
// can load music of other user:

 const MUSICFILE = '/uploads/test/StarCommander1.wav';
 AB.backgroundMusic ( MUSICFILE );