// Demo of 3d models// skeleton credit// http://tf3dm.com/3d-model/skeleton-with-organs-91102.html// Peter Parker credit// http://tf3dm.com/download-page.php?url=spider-man-4998// male credit// https://threejs.org/examples/#webgl_loader_objconst CLOCKTICK =150;// speed of run - move things every n millisecondsconst MAXSTEPS =1000;// length of a run before final score//---- global constants: -------------------------------------------------------const gridsize =20;// number of squares along side of world const squaresize =100;// size of square in pixelsconst MAXPOS = gridsize * squaresize;// length of one side in pixels const NOBOXES =Math.trunc ((gridsize * gridsize)/4);const SKYCOLOR =0xffffcc;// a number, not a string const BLANKCOLOR = SKYCOLOR ;// make objects this color until texture arrives (from asynchronous file read)const LIGHTCOLOR =0xffffff;const startRadiusConst = MAXPOS *0.8;// distance from centre to start the camera atconst skyboxConst = MAXPOS *3;// where to put skybox const maxRadiusConst = MAXPOS *5;// maximum distance from camera we will render things //--- Mind can pick one of these actions -----------------const ACTION_LEFT =0;const ACTION_RIGHT =1;const ACTION_UP =2;const ACTION_DOWN =3;const ACTION_STAYSTILL =4;const JUMP_UP =5;const JUMP_DOWN =6;const JUMP_LEFT =7;const JUMP_RIGHT =8;// contents of a grid squareconst GRID_BLANK =0;const GRID_WALL =1;const GRID_MAZE =2;// --- some useful random functions -------------------------------------------function randomfloatAtoB ( A, B ){return( A +(Math.random()*(B-A)));}function randomintAtoB ( A, B ){return(Math.round ( randomfloatAtoB ( A, B )));}function randomBoolean(){if(Math.random()<0.5){returnfalse;}else{returntrue;}}function randomPick ( a, b ){if( randomBoolean())return a;elsereturn b;}//---- start of World class -------------------------------------------------------functionWorld(){// most of World can be private // regular "var" syntax means private variables:var GRID =newArray(gridsize);// can query GRID about whether squares are occupied, will in fact be initialised as a 2D array var WALLS =newArray(4* gridsize );// need to keep handle to each wall block object so can find it later to paint it var MAZE =newArray( NOBOXES );var theagent, theenemy, theenemy2, theenemy3, theenemy4;var agentRotation =0;var enemyRotation =0;// with 3D models, current rotation away from default orientationvar enemyRotation2 =0;var enemyRotation3 =0;var enemyRotation4 =0;// enemy and agent position on squaresvar ei, ej, ai, aj, e2i, e2j, e3i, e3j, e4i, e4j;var badsteps;var goodsteps;var step;var self =this;// needed for private fn to call public fn - see below function initGrid(){for(var i =0; i < gridsize ; i++){
GRID[i]=newArray(gridsize);// each element is an array for(var j =0; j < gridsize ; j++){
GRID[i][j]= GRID_BLANK ;}}}function occupied ( i, j )// is this square occupied{if(( ei == i )&&( ej == j ))returntrue;// variable objects if(( ai == i )&&( aj == j ))returntrue;if(( e2i == i )&&( e2j == j ))returntrue;if(( e3i == i )&&( e3j == j ))returntrue;if(( e4i == i )&&( e4j == j ))returntrue;if( GRID[i][j]== GRID_WALL )returntrue;// fixed objects if( GRID[i][j]== GRID_MAZE )returntrue;returnfalse;}function translate ( x ){return( x -( MAXPOS/2));}// --- asynch load textures from file ----------------------------------------// credits:// http://commons.wikimedia.org/wiki/File:Old_door_handles.jpg?uselang=en-gb// https://commons.wikimedia.org/wiki/Category:Pac-Man_icons// https://commons.wikimedia.org/wiki/Category:Skull_and_crossbone_iconsfunction loadTextures(){var manager =new THREE.LoadingManager();var loader =new THREE.OBJLoader( manager );
loader.load("/uploads/ashcass/trantula.obj", buildenemy );
loader.load("/uploads/ashcass/trantula.obj", buildenemy2 );
loader.load("/uploads/ashcass/trantula.obj", buildenemy3 );
loader.load("/uploads/ashcass/fly.obj", buildenemy4 );// load simple OBJ
loader.load("/uploads/ashcass/fly.obj", buildagent );var loader1 =new THREE.TextureLoader();
loader1.load ('/uploads/ashcass/brick.jpg',function( thetexture ){
thetexture.minFilter = THREE.LinearFilter;
paintWalls (new THREE.MeshBasicMaterial({ map: thetexture }));});var loader2 =new THREE.TextureLoader();
loader2.load ('/uploads/starter/latin.jpg',function( thetexture ){
thetexture.minFilter = THREE.LinearFilter;
paintMaze (new THREE.MeshBasicMaterial({ map: thetexture }));});}function buildenemy ( object ){
object.scale.multiplyScalar (1000);// make 3d object n times bigger
object.traverse( paintEnemy );
theenemy = object;
threeworld.scene.add( theenemy );}function paintEnemy ( child ){if( child instanceof THREE.Mesh){
child.material.map = THREE.ImageUtils.loadTexture("/uploads/ashcass/hair.jpg");}}function buildenemy2 ( object ){
object.scale.multiplyScalar (1000);// make 3d object n times bigger
object.traverse( paintEnemy2 );
theenemy2 = object;
threeworld.scene.add( theenemy2 );}function paintEnemy2 ( child ){if( child instanceof THREE.Mesh){
child.material.map = THREE.ImageUtils.loadTexture("/uploads/ashcass/hair.jpg");}}function buildenemy3 ( object ){
object.scale.multiplyScalar (1000);// make 3d object n times bigger
object.traverse( paintEnemy3 );
theenemy3 = object;
threeworld.scene.add( theenemy3 );}function paintEnemy3 ( child ){if( child instanceof THREE.Mesh){
child.material.map = THREE.ImageUtils.loadTexture("/uploads/ashcass/hair.jpg");}}function buildenemy4 ( object ){
object.scale.multiplyScalar (25000);// make 3d object n times bigger
object.traverse( paintEnemy4 );
theenemy4 = object;
threeworld.scene.add( theenemy4 );}function paintEnemy4 ( child ){if( child instanceof THREE.Mesh){
child.material.map = THREE.ImageUtils.loadTexture("/uploads/ashcass/gold.jpg");}}function buildagent ( object ){
object.scale.multiplyScalar (25000);
object.traverse( paintAgent );
theagent = object;
threeworld.scene.add( theagent );}function paintAgent ( child ){if( child instanceof THREE.Mesh){
child.material.map = THREE.ImageUtils.loadTexture("/uploads/ashcass/flytext.jpg");}}function addparker ( object ){
object.scale.multiplyScalar (70);
theagent = object;
threeworld.scene.add( theagent );}function initSkybox(){// urban photographic skyboxes, credit:// http://opengameart.org/content/urban-skyboxesvar materialArray =[(new THREE.MeshBasicMaterial({ map: THREE.ImageUtils.loadTexture("/uploads/ashcass/snap3.png"), side: THREE.BackSide})),(new THREE.MeshBasicMaterial({ map: THREE.ImageUtils.loadTexture("/uploads/ashcass/snap1.png"), side: THREE.BackSide})),(new THREE.MeshBasicMaterial({ map: THREE.ImageUtils.loadTexture("/uploads/ashcass/snapsky.png"), side: THREE.BackSide})),(new THREE.MeshBasicMaterial({ map: THREE.ImageUtils.loadTexture("/uploads/ashcass/snapfloor.png"), side: THREE.BackSide})),(new THREE.MeshBasicMaterial({ map: THREE.ImageUtils.loadTexture("/uploads/ashcass/snap2.png"), side: THREE.BackSide})),(new THREE.MeshBasicMaterial({ map: THREE.ImageUtils.loadTexture("/uploads/ashcass/snap4.png"), side: THREE.BackSide})),];var skyGeometry =new THREE.CubeGeometry( skyboxConst, skyboxConst, skyboxConst );var skyMaterial =new THREE.MeshFaceMaterial( materialArray );var theskybox =new THREE.Mesh( skyGeometry, skyMaterial );
threeworld.scene.add( theskybox );// We are inside a giant cube}function initLogicalWalls()// set up logical walls in data structure, whether doing graphical run or not {for(var i =0; i < gridsize ; i++)for(var j =0; j < gridsize ; j++)if(( i==0)||( i==gridsize-1)||( j==0)||( j==gridsize-1)){
GRID[i][j]= GRID_WALL ;}}function initThreeWalls()// graphical run only, set up blank boxes, painted later {var t =0;for(var i =0; i < gridsize ; i++)for(var j =0; j < gridsize ; j++)if( GRID[i][j]== GRID_WALL ){var shape =new THREE.BoxGeometry( squaresize, squaresize, squaresize );var thecube =new THREE.Mesh( shape );
thecube.material.color.setHex( BLANKCOLOR );
thecube.position.x = translate ( i * squaresize );// translate my simple (i,j) block-numbering coordinates to three.js (x,y,z) coordinates
thecube.position.z = translate ( j * squaresize );
thecube.position.y =0;
threeworld.scene.add(thecube);
WALLS[t]= thecube;// save it for later
t++;}}function paintWalls ( material )// paint blank boxes {for(var i =0; i < WALLS.length; i++){if( WALLS[i]) WALLS[i].material = material;}}function initLogicalMaze(){for(var c=1; c <= NOBOXES ; c++){var i = randomintAtoB(1,gridsize-2);// inner squares are 1 to gridsize-2var j = randomintAtoB(1,gridsize-2);
GRID[i][j]= GRID_MAZE ;}}function initThreeMaze(){var t =0;for(var i =0; i < gridsize ; i++)for(var j =0; j < gridsize ; j++)if( GRID[i][j]== GRID_MAZE ){var shape =new THREE.BoxGeometry( squaresize, squaresize, squaresize );var thecube =new THREE.Mesh( shape );
thecube.material.color.setHex( BLANKCOLOR );
thecube.position.x = translate ( i * squaresize );
thecube.position.z = translate ( j * squaresize );
thecube.position.y =0;
threeworld.scene.add(thecube);
MAZE[t]= thecube;// save it for later
t++;}}function paintMaze ( material ){for(var i =0; i < MAZE.length; i++){if( MAZE[i]) MAZE[i].material = material;}}// --- enemy functions -----------------------------------function drawEnemy()// given ei, ej, draw it {if( theenemy ){var x = translate ( ei * squaresize );var z = translate ( ej * squaresize );var y =(0);
theenemy.position.x = x;
theenemy.position.y = y;
theenemy.position.z = z;
threeworld.lookat.copy ( theenemy.position );// if camera moving, look back at where the enemy is
threeworld.lookat.y =( squaresize *1.5);// point camera higher up}}function initLogicalEnemy(){// start in random location:var i, j;do{
i = randomintAtoB(1,8);
j = randomintAtoB(1,8);}while( occupied(i,j));// search for empty square
ei = i;
ej = j;}function moveLogicalEnemy( a ){var i = ei;var j = ej;if( a == ACTION_LEFT ){ i--;}elseif( a == ACTION_RIGHT ){ i++;}elseif( a == ACTION_UP ){ j++;}elseif( a == ACTION_DOWN ){ j--;}if(! occupied(i,j)){if(true){// if going to actually move, then turn body towards move// rotate by some amount of radians from the normal position // in degrees: +0, +90, +180, +270if( a == ACTION_LEFT ){ rotateAgentTowards (3*(Math.PI /2));}elseif( a == ACTION_RIGHT ){ rotateAgentTowards (1*(Math.PI /2));}elseif( a == ACTION_UP ){ rotateAgentTowards (0*(Math.PI /2));}elseif( a == ACTION_DOWN ){ rotateAgentTowards (2*(Math.PI /2));}}
ei = i;
ej = j;}}function drawEnemy2()// given e2i, e2j, draw it {if( theenemy2 ){var x = translate ( e2i * squaresize );var z = translate ( e2j * squaresize );var y =(0);
theenemy2.position.x = x;
theenemy2.position.y = y;
theenemy2.position.z = z;
threeworld.lookat.copy ( theenemy2.position );// if camera moving, look back at where the enemy is
threeworld.lookat.y =( squaresize *1.5);// point camera higher up}}function initLogicalEnemy2(){// start in random location:var i, j;do{
i = randomintAtoB(8,17);
j = randomintAtoB(1,17);}while( occupied(i,j));// search for empty square
e2i = i;
e2j = j;}function moveLogicalEnemy2(a){var i = e2i;var j = e2j;if( a == ACTION_LEFT ){ i--;}elseif( a == ACTION_RIGHT ){ i++;}elseif( a == ACTION_UP ){ j++;}elseif( a == ACTION_DOWN ){ j--;}if(! occupied(i,j)){if(true){// if going to actually move, then turn body towards move// rotate by some amount of radians from the normal position // in degrees: +0, +90, +180, +270if( a == ACTION_LEFT ){ rotateAgentTowards (3*(Math.PI /2));}elseif( a == ACTION_RIGHT ){ rotateAgentTowards (1*(Math.PI /2));}elseif( a == ACTION_UP ){ rotateAgentTowards (0*(Math.PI /2));}elseif( a == ACTION_DOWN ){ rotateAgentTowards (2*(Math.PI /2));}}
e2i = i;
e2j = j;}}function drawEnemy3()// given ei, ej, draw it {if( theenemy3 ){var x = translate ( e3i * squaresize );var z = translate ( e3j * squaresize );var y =(0);
theenemy3.position.x = x;
theenemy3.position.y = y;
theenemy3.position.z = z;
threeworld.lookat.copy ( theenemy3.position );// if camera moving, look back at where the enemy is
threeworld.lookat.y =( squaresize *1.5);// point camera higher up}}function initLogicalEnemy3(){// start in random location:var i, j;do{
i = randomintAtoB(1,17);
j = randomintAtoB(8,17);}while( occupied(i,j));// search for empty square
e3i = i;
e3j = j;}function moveLogicalEnemy3( a ){var i = e3i;var j = e3j;if( a == ACTION_LEFT ){ i--;}elseif( a == ACTION_RIGHT ){ i++;}elseif( a == ACTION_UP ){ j++;}elseif( a == ACTION_DOWN ){ j--;}if(! occupied(i,j)){if(true){if( a == ACTION_LEFT ){ rotateAgentTowards (3*(Math.PI /2));}elseif( a == ACTION_RIGHT ){ rotateAgentTowards (1*(Math.PI /2));}elseif( a == ACTION_UP ){ rotateAgentTowards (0*(Math.PI /2));}elseif( a == ACTION_DOWN ){ rotateAgentTowards (2*(Math.PI /2));}}
e3i = i;
e3j = j;}}function drawEnemy4()// given ei, ej, draw it {if( theenemy4 ){var x = translate ( e4i * squaresize );var z = translate ( e4j * squaresize );var y =(0);
theenemy4.position.x = x;
theenemy4.position.y = y;
theenemy4.position.z = z;
threeworld.lookat.copy ( theenemy4.position );// if camera moving, look back at where the enemy is
threeworld.lookat.y =( squaresize *1.5);// point camera higher up}}function initLogicalEnemy4(){// start in random location:var i, j;do{
i = randomintAtoB(8,17);
j = randomintAtoB(8,17);}while( occupied(i,j));// search for empty square
e4i = i;
e4j = j;}function moveLogicalEnemy4( a ){var i = e4i;var j = e4j;if( a == ACTION_LEFT ){ i--;}elseif( a == ACTION_RIGHT ){ i++;}elseif( a == ACTION_UP ){ j++;}elseif( a == ACTION_DOWN ){ j--;}if(! occupied(i,j)){if(true){// if going to actually move, then turn body towards move// rotate by some amount of radians from the normal position // in degrees: +0, +90, +180, +270if( a == ACTION_LEFT ){ rotateAgentTowards (3*(Math.PI /2));}elseif( a == ACTION_RIGHT ){ rotateAgentTowards (1*(Math.PI /2));}elseif( a == ACTION_UP ){ rotateAgentTowards (0*(Math.PI /2));}elseif( a == ACTION_DOWN ){ rotateAgentTowards (2*(Math.PI /2));}}
e4i = i;
e4j = j;}}const INTERIMROT =10;// number of interim rotations drawn when model turns round// all rotations positive 0 to 2 PI // interim renders not working// temporary solution - rotate half-way - will continue the rotation laterfunction rotateEnemyTowards ( newRotation ){if( enemyRotation == newRotation )return;// else var x =( enemyRotation + newRotation )/2;
theenemy.rotation.set(0, x,0);
enemyRotation = x;}function rotateEnemy2Towards ( newRotation ){if( enemyRotation2 == newRotation )return;// else var y =( enemyRotation2 + newRotation )/2;
theenemy2.rotation.set(0, y,0);
enemyRotation2 = y;}function rotateEnemy3Towards ( newRotation ){if( enemyRotation3 == newRotation )return;// else var y =( enemyRotation3 + newRotation )/2;
theenemy3.rotation.set(0, y,0);
enemyRotation3 = y;}function rotateEnemy4Towards ( newRotation ){if( enemyRotation4 == newRotation )return;// else var y =( enemyRotation4 + newRotation )/2;
theenemy4.rotation.set(0, y,0);
enemyRotation4 = y;}// --- agent functions -----------------------------------function drawAgent()// given ai, aj, draw it {if( theagent ){var x = translate ( ai * squaresize );var z = translate ( aj * squaresize );var y =(0);
theagent.position.x = x;
theagent.position.y = y;
theagent.position.z = z;
threeworld.follow.copy ( theagent.position );// follow vector = agent position (for camera following agent)
threeworld.follow.y =( squaresize *1.5);// put camera higher up}}function initLogicalAgent(){// start in random location:var i, j;do{
i =1;
j =1;}while( occupied(i,j));// search for empty square
ai = i;
aj = j;}function moveLogicalAgent( a )// this is called by the infrastructure that gets action a from the Mind {var i = ai;var j = aj;if( a == ACTION_LEFT ){ i--;}elseif( a == ACTION_RIGHT ){ i++;}elseif( a == ACTION_UP ){ j++;}elseif( a == ACTION_DOWN ){ j--;}elseif( a == JUMP_LEFT ){ i = i-2;}elseif( a == JUMP_RIGHT ){ i= i+2;}elseif( a == JUMP_UP ){ j = j+2;}elseif( a == JUMP_DOWN ){ j= j-2;}if(! occupied(i,j)){if(true){// if going to actually move, then turn body towards move// rotate by some amount of radians from the normal position // in degrees: +0, +90, +180, +270if( a == ACTION_LEFT ){ rotateAgentTowards (3*(Math.PI /2));}elseif( a == ACTION_RIGHT ){ rotateAgentTowards (1*(Math.PI /2));}elseif( a == ACTION_UP ){ rotateAgentTowards (0*(Math.PI /2));}elseif( a == ACTION_DOWN ){ rotateAgentTowards (2*(Math.PI /2));}}
ai = i;
aj = j;}}function keyHandler(e)// user control // Note that this.takeAction(a) is constantly running at same time, redrawing the screen.{if(e.keyCode ==37) moveLogicalAgent ( ACTION_LEFT );if(e.keyCode ==38) moveLogicalAgent ( ACTION_DOWN );if(e.keyCode ==39) moveLogicalAgent ( ACTION_RIGHT );if(e.keyCode ==40) moveLogicalAgent ( ACTION_UP );if(e.keyCode ==65) moveLogicalAgent ( JUMP_LEFT );if(e.keyCode ==87) moveLogicalAgent ( JUMP_DOWN );if(e.keyCode ==68) moveLogicalAgent ( JUMP_RIGHT );if(e.keyCode ==88) moveLogicalAgent ( JUMP_UP );}function rotateAgentTowards ( newRotation ){if( agentRotation == newRotation )return;// else var x =( agentRotation + newRotation )/2;
theagent.rotation.set(0, x,0);
agentRotation = x;}// --- score: -----------------------------------function badstep()// is the enemy within one square of the agent{if((Math.abs(ei - ai)<2)&&(Math.abs(ej - aj)<2))returntrue;elsereturnfalse;}function updateStatus(){var score = self.getScore();var status =" Step: "+ step +" out of "+ MAXSTEPS +". Score: "+ score;
$("#user_span1").html( status );}//--- public functions / interface / API ----------------------------------------------------------// must have this public variable:this.endCondition;// If set to true, run will end. this.win;this.newRun =function(){
$("#user_span2").html(" <font color = green > <B> Make it to gold fly without being caught </B> </font> ");this.win =false;this.endCondition =false;
badsteps =0;
goodsteps =0;
step =0;// define logical data structure for the World, even if no graphical representation:
initGrid();
initLogicalWalls();
initLogicalMaze();
initLogicalAgent();
initLogicalEnemy();
initLogicalEnemy2();
initLogicalEnemy3();
initLogicalEnemy4();if(true){
threeworld.init3d ( startRadiusConst, maxRadiusConst, SKYCOLOR );// lightvar ambient =new THREE.AmbientLight();
threeworld.scene.add( ambient );var thelight =new THREE.DirectionalLight( LIGHTCOLOR,3);
thelight.position.set( startRadiusConst, startRadiusConst, startRadiusConst );
threeworld.scene.add(thelight);// musicvar x ="<audio id=theaudio src=/uploads/starter/SuspenseStrings.mp3 autoplay loop> </audio>";
$("#user_span2").html( x );// music credit// http://www.dl-sounds.com/royalty-free/suspense-strings/
initSkybox();
initThreeWalls();
initThreeMaze();
loadTextures();// will return sometime later, but can go ahead and render now
document.onkeydown = keyHandler;}};this.getState =function(){var x =[ ai, aj, ei, ej ];return( x );};this.takeAction =function( a ){
step++;//moveLogicalAgent(a);if(( step %2)==0)// slow the enemy down to every nth step
moveLogicalEnemy(a);
moveLogicalEnemy2(a);
moveLogicalEnemy3(a);//moveLogicalEnemy4(a); if( badstep())
badsteps++;else
goodsteps++;if(true){
drawAgent();
drawEnemy();
drawEnemy2();
drawEnemy3();
drawEnemy4();
updateStatus();}function die(){if((((ei == ai-1)&&(ej == aj))||((ei== ai+1)&&(aj == ej))||((ai == ei)&&(ej==aj+1))||((ai == ei)&&(aj-1== ej)))||(((ai-1== e2i)&&(e2j == aj))||((ai+1==e2i)&&(aj==e2j))||((ai == e2i)&&(e2j==aj+1))||((ai == e2i)&&(aj-1== e2j)))||(((ai-1== e3i)&&(e3j == aj))||((ai+1==e3i)&&(aj==e3j))||((ai == e3i)&&(e3j==aj+1))||((ai == e3i)&&(aj-1== e3j)))){returntrue;}elsereturnfalse;}if(die()){this.endCondition =true;}function captureTarget(){if(((ai-1== e4i)&&(e4i == aj))||((ai+1== e4i)&&(aj==e4j))||((ai == e4i)&&(e4i==aj+1))||((ai == e4i)&&(aj-1== e4j))){
$("#user_span3").html(" <font color = green > <B> YOU WIN </B> </font> ");returntrue;}elsereturnfalse;}if(captureTarget())this.endCondition =true;this.win =true;};this.endRun =function(){if(true){if(this.endCondition &&this.win)
$("#user_span6").html (" <font color = red > <B> GAME OVER </B> </font> ");else
$("#user_span6").html (" <font color = red > <B> GAME OVER </B> </font> ");}};this.getScore =function(){return goodsteps;};}//---- end of World class -------------------------------------------------------