Code viewer for World: Space Hero (clone by Leigh...

// Cloned by Leigh Reilly on 5 Dec 2022 from World "Space Hero" by Enhanced 
// Please leave this clone trail here.
 


// Cloned by Enhanced on 13 Jun 2018 from World "Space hero in threeworld" by Mathias Bazin 
// Please leave this clone trail here.
 


// Customise AB run parameters (optional).
// The following 3 parameters can be customised. (They have default values.)

//===============================================================
//Comments:
// Adapted the game to fit the threeworld object. Add audio and visual feedback through the game and mouse hides when playing. 
//===============================================================

threeworld.drawCameraControls = false;
AB.drawRunControls = false;


AB.clockTick       = 20;    

	// Speed of run: Step every n milliseconds. Default 100.
	
AB.maxSteps        = 10000;    

	// 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.

	

function World() { 
    

					// length of a run before final score

	//
	const ACTION_LEFT 		= 0;		   
    const ACTION_RIGHT 		= 1;
    const ACTION_UP 		= 2;		 
    const ACTION_DOWN 		= 3;
    const ACTION_STAYSTILL 	= 4;
    
    const COLLISIONAUDIO = "/uploads/mathias/boom.mp3";
    const DIFFUPAUDIO = "/uploads/mathias/diffUp.mp3"
    
    const startRadiusConst = 100
    const maxRadiusConst = 1000
    const SKYCOLOR = 0x000000;
    
   var player, gem;
   var mouse = new THREE.Vector2();
   var enemies = [];
   var enemySpeed = 3;
   var scoreDiv = document.getElementById( "score" );
   var bestScoreDiv = document.getElementById( "bestScore" );
   var sphereRadius = 10;
   var enemyRangeX = 550;
   var enemyRangeY = 700;
   var gemRange = 700;
   var score = 0;
   var best = 0;
   var stars = [];
   var starSpeed = 8;
   var difficulty = 0;
   var timeToShake = 0;
   
    var canvas = document.getElementById("ab-runcanvas");
    
    var camPos = new THREE.Vector3(0,0,600);
    var camLook = new THREE.Vector3(0,0,-1000);

 	var self = this;						// needed for private fn to call public fn - see below 
 	
 	function shakeCamera()
 	{
 	    if (timeToShake == 0)
 	    {
 	        camPos.x = 0;
 	        camPos.y = 0;
 	    }
 	    else if ( timeToShake > 0 )
 	    {
 	        camPos.x += randomintAtoB(-20,20);
 	        camPos.y += randomintAtoB(-20,20);
 	        
 	        timeToShake--;
 	        
 	        console.log(camPos.x, camPos.y, camPos.z);

 	    }
 	    
 	    threeworld.follow = camPos;
        threeworld.lookat = camLook;
 	}
 	
 	function randomfloatAtoB ( A, B )			 
    {
     return ( A + ( Math.random() * (B-A) ) );
    }

 	function randomintAtoB ( A, B )			 
    {
        return  ( Math.round ( randomfloatAtoB ( A, B ) ) );
    }
 	
	
	
	function moveAgent( a )			 
    { 
        var i = ai;
        var j = aj;		 

        if ( a == ACTION_LEFT ) 	i--;
        else if ( a == ACTION_RIGHT ) 	i++;
        else if ( a == ACTION_UP ) 	j++;
        else if ( a == ACTION_DOWN ) 	j--;

        if ( ! occupied(i,j) ) 		// else just miss a turn 
        {
	        GRID[ai][aj] = GRID_BLANK;
	        GRID[i][j]   = GRID_AGENT;
	        ai = i;
	        aj = j;
	        player.position.copy ( translate(ai,aj) ); 		  	// translate my (i,j) grid coordinates to three.js (x,y,z) coordinates 
        }
    }
	
	var OURKEYS = [ 37, 38, 39, 40 ];

    function ourKeys ( event ) { return ( OURKEYS.includes ( event.keyCode ) ); }
	
    function keyHandler ( event )		    
    {
	    if ( ! AB.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 == 37 )   moveAgent ( ACTION_LEFT 	);   
        if ( event.keyCode == 38 )   moveAgent ( ACTION_DOWN  	); 	 
        if ( event.keyCode == 39 )   moveAgent ( ACTION_RIGHT 	); 	 
        if ( event.keyCode == 40 )   moveAgent ( ACTION_UP		);   
	
	    event.stopPropagation(); event.preventDefault(); return false;
    }
    var startX, startY; 

    var dragevents;
// 	function onMouseMove(event) 
// 	{

//          // Update the mouse variable
//         event.preventDefault();
//         mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
//         mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;
        
//         console.log("mouse x :", mouse.x);
        
//         // Make the sphere follow the mouse
//         var vector = new THREE.Vector3(mouse.x, mouse.y, 0.5);
//         vector.unproject( threeworld.camera );
//         var dir = vector.sub( threeworld.camera.position ).normalize();
//         var distance = - threeworld.camera.position.z / dir.z;
//         var pos = threeworld.camera.position.clone().add( dir.multiplyScalar( distance ) );
//         theagent.position.copy(pos);
  
//         // Make the sphere follow the mouse
// //      mouseMesh.position.set(event.clientX, event.clientY, 0);
//     }
	
	function initDrag ( x, y )              // x,y position on screen
    {
        startX  = x;                                             
        startY  = y;
        dragevents = 0;
    }



    function drag ( x, y )                 
    {
        	if ( ! AB.runReady ) return true; 		// not ready yet 

	        if ( ( dragevents % 4 ) === 0 )		 // slow it down to respond to every nth event - too many events
	        {
			    if ( x > startX ) 	moveAgent ( ACTION_RIGHT 	);
		        else if ( x < startX ) 	moveAgent ( ACTION_LEFT 	);

			    if ( y > startY ) 	moveAgent ( ACTION_UP 		);
		        else if ( y < startY ) 	moveAgent ( ACTION_DOWN		);
	        }
	
	        dragevents++;
	
	        startX 	= x;						 
	        startY 	= y;
	    }// console.log("fene", $(window).height());
        
    //     theagent.position.x = x - $(window).width()/2;
    //     theagent.position.y = -y + $(document).height()/2;
        
    //     // console.log("mouse",x,y);
    //     // console.log("agent", theagent.position.x, theagent.position.y);

    //     $('html').css({cursor: 'none'});
        
    //     dragevents++;
            
    //     startX  = x;                                             
    //     startY  = y;
    // }

    // function onMouseUp(){
    //     console.log("yeq")
    //     $('html').css({cursor: 'auto'});
    // }
	
	this.newRun = function()
	{
		threeworld.init3d ( startRadiusConst, maxRadiusConst, SKYCOLOR  ); 

// 		threeworld.camera.position.z = 600;
        
        threeworld.follow = camPos;
        threeworld.lookat = camLook;
        
        threeworld.cameraMove();

		enemies = [];
        stars = [];
   
        enemyRangeX = 550;
        enemyRangeY = 700;
        gemRange = 500;

        geometry = new THREE.SphereGeometry( 15, 20, 20 );
        material = new THREE.MeshLambertMaterial( { map: THREE.ImageUtils.loadTexture('/uploads/rossfraney3/rock.jpg' )} );
        
        geometry2 = new THREE.SphereGeometry( 3, 3, 3 );
        material2 = new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture('/uploads/rossfraney3/glass.jpg' )} );

        radius = 1000;
        nboxes = 50;

        for(var i = 0; i<nboxes; i++){
            var cube = new THREE.Mesh( geometry, material );
            cube.castShadow = false;
            cube.receiveShadow = false;
            threeworld.scene.add( cube );
            cube.position.set(radius/2 - radius * Math.random(), radius/2 - radius * Math.random(), 0.0);
            enemies.push( cube );
        }
        for(var i = 0; i<nboxes*2; i++){
            var star = new THREE.Mesh( geometry2, material2 );
            threeworld.scene.add( star );
            star.position.set(radius/2 - radius * Math.random(), radius/2 - radius * Math.random(), 0.0);
            stars.push( star );
        }
        
        //
        
        gem = new THREE.Mesh( geometry, new THREE.MeshLambertMaterial({map: THREE.ImageUtils.loadTexture('/uploads/rossfraney3/fire.jpg'), side:THREE.FrontSide}));
        gem.position.set( gemRange/2 - gemRange * Math.random(),gemRange/2 - gemRange * Math.random(),0.0);
        gem.castShadow = false;
        gem.receiveShadow = false;

        threeworld.scene.add( gem );

        player = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial({map: THREE.ImageUtils.loadTexture('/uploads/rossfraney3/earthbare.jpg'), side:THREE.FrontSide}) );
        threeworld.scene.add( player );
        // window.addEventListener( 'mousemove', onMouseMove, false );


        var skyGeometry = new THREE.SphereGeometry ( 3000, 60, 40 );    
        var uniforms = {
            texture: { type: 't', value: THREE.ImageUtils.loadTexture('sky.jpg')}
        };
        var skyMaterial = new THREE.MeshBasicMaterial({ map: THREE.ImageUtils.loadTexture('/uploads/rossfraney3/ESO.jpg')});
  
        var theskybox = new THREE.Mesh ( skyGeometry, skyMaterial );
        theskybox.scale.set(-5, 5, 5);
        theskybox.eulerOrder = 'XYZ'
        theskybox.renderDepth = 500.0;
        threeworld.scene.add( theskybox );                                         
  
        var light = new THREE.PointLight(0xffffff);
        light.position.set(0,250,0);
        threeworld.scene.add(light); //add light to world (From a nearby star, obviously)
        var x = "<audio  id=theaudio  src=/uploads/starter/SuspenseStrings.mp3   autoplay loop> </audio>" ;
                $("#user_span2").html( x );
   
        threehandler.initMouseDrag      = initDrag;
        threehandler.mouseDrag          = drag
        
        //document.addEventListener("click", onMouseUp);
        document.onkeydown 			= keyHandler;
 			
	// override ABHandler default (which is camera control) to use my own functions:

		myControls();
        // canvas.addEventListener("mouseup", onMouseUp);
	};

    function myControls()
{
		ABHandler.initTouchDrag 	= initDrag;
		ABHandler.touchDrag			= drag
		
// 		ABHandler.initMouseDrag 	= initDrag;
// 		ABHandler.mouseDrag			= drag
}






	this.nextStep = function()		 
	{
		// Code for Three.js re-drawing of objects.  

		for( var i = 0; i < enemies.length; i++ ){
		    if(enemies[i].position.y < -500){
	        //enemies[i].position.x = enemyRangeX/2 - enemyRangeX * Math.random();
	        enemies[i].position.y = 500;
		    } 
		    else{
		     if ( enemies[i].position.distanceTo( player.position ) < 2 * sphereRadius) { // if there's a player-enemy collision
		        timeToShake = 10;
			 	score = 0;
			 	let boom = new Audio( COLLISIONAUDIO );
			 	boom.play();
			 	enemySpeed = 3;
			 	starSpeed = 8;
			 	difficulty = 0;
			 	
			 	enemies[i].position.set(radius/2 - radius * Math.random(), radius/2 - radius * Math.random(), 0.0)
 			    
 			    gem.position.x = gemRange/2 - gemRange * Math.random();
 			    gem.position.y = gemRange/2 - gemRange * Math.random();
			 }
			enemies[i].position.y -= enemySpeed;
			}
		}
		for( var i = 0; i < stars.length; i++ ){
		    if(stars[i].position.y < -500){
	        stars[i].position.y = 500;
		    }
		    stars[i].position.y -= starSpeed; 
		}
		gem.rotation.y += .02;
		player.rotation.x += .002;
		player.rotation.y += .02;

		var status = " <center> <b> Collect the Suns. For each multiple of 5 difficulty will increase.</b></BR>Score: " + score + " &nbsp Best Score: " + best + "  &nbsp Difficulty Level: " + difficulty + "</center>";
 		$("#user_span4").html( status );

 		if(player.position.distanceTo( gem.position ) < 2 * sphereRadius){ //agent grabs sun 
 			gem.position.x = gemRange/2 - gemRange * Math.random();
 			gem.position.y = gemRange/2 - gemRange * Math.random();
 			score ++;
 			var y = "<audio  id=theaudio  src=/uploads/rossfraney3/elevatording.mp3  autoplay  > </audio>" ;
  		    $("#user_span3").html( y );
 			if(score % 5 === 0){ //difficulty up !
 			    
 			    let diffUpAudio = new Audio( DIFFUPAUDIO );
 			    diffUpAudio.play()
 				enemySpeed++;
 				starSpeed++;
 				difficulty++;
 			}
 			if(score > best){
 				best = score;
 			}
 		}
 		
 		shakeCamera();

	};


}