// Cloned by Lorcan Dunne on 1 Dec 2022 from World "Bomberman" by Enhanced
// Please leave this clone trail here.
// Cloned by Enhanced on 21 Jun 2018 from World "Cloned Bomberman" by Nathan Bonnard
// Please leave this clone trail here.
// Cloned by Nathan Bonnard on 1 Jun 2018 from World "Bomberman" by Mark McAdam
// Please leave this clone trail here.
/*
--------------------------------
New Features by Nathan Bonnard :
--------------------------------
The game was code with a unique object for the bomb of the player.
There was a bug when you wanted to put two bomb, the second one always killed the player.
Now you can't put bomb if there is already one.
It would have been too long to code the entire game so that you can drop many bombs.
----------------------------------
All credits to Simon Mark McAdam :
----------------------------------
*/
AB.drawRunControls = false;
const CLOCKTICK = 150; // speed of run - move things every n milliseconds
const MAXSTEPS = 1000; // length of a run before final score
const SCREENSHOT_STEP = 50;
//---- global constants: -------------------------------------------------------
const gridsize = 15; // number of squares along side of world
const squaresize = 100; // size of square in pixels
const MAXPOS = gridsize * squaresize; // length of one side in pixels
const NOBOXES = Math.trunc ( (gridsize * gridsize) / 15 );
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 at
const 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 DROP_BOMB = 5;
// contents of a grid square
const GRID_BLANK = 0;
const GRID_WALL = 1;
const GRID_MAZE = 2;
const GRID_WEAK = 3; //Weak walls can be blown up with bombs
const GRID_BOMB = 4;
// --- 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 )
return false;
else
return true;
}
function randomPick ( a, b )
{
if ( randomBoolean() )
return a;
else
return b;
}
//---- start of World class -------------------------------------------------------
function World() {
// most of World can be private
// regular "var" syntax means private variables:
var GRID = new Array (gridsize); // can query GRID about whether squares are occupied, will in fact be initialised as a 2D array
var WALLS = new Array ( 4 * gridsize ); // need to keep handle to each wall block object so can find it later to paint it
var STRONGCUBES = new Array ( NOBOXES );
var WEAKCUBES = new Array ( NOBOXES );
var EXPLOSIONS = new Array ( NOBOXES );
var theagent, theenemy, agentBomb, enemyBomb;
var noBomb = true;
var agentRotation = 0;
var enemyRotation = 0; // with 3D models, current rotation away from default orientation
// enemy and agent position on squares
var ei , ej, ai, aj, agentbombi, agentbombj, enemybombi, enemybombj;
var self = this; // needed for private fn to call public fn - see below
var steps;
var agentbombExploding = false;
var enemybombExploding = false;
var enemyBombPlaced = false;
var agentmiddle; //Explosion in four diections
var agentleftBlock;
var agentrightBlock;
var agentupBlock;
var agentdownBlock;
var enemymiddle; //Explosion in four diections
var enemyleftBlock;
var enemyrightBlock;
var enemyupBlock;
var enemydownBlock;
function initGrid()
{
for (var i = 0; i < gridsize ; i++)
{
GRID[i] = new Array(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
{
// variable objects
if ( ( ei == i ) && ( ej == j ) )
return true; // variable objects
if ( ( ai == i ) && ( aj == j ) )
return true;
if ( ( agentbombi == i ) && ( agentbombj == j ) )
return true;
if ( ( enemybombi == i ) && ( enemybombj == j ) )
return true;
if ( GRID[i][j] == GRID_WEAK )
return true;
// fixed objects
if ( GRID[i][j] == GRID_WALL )
return true;
if ( GRID[i][j] == GRID_MAZE )
return true;
return false;
}
function translate ( x )
{
return ( x - ( MAXPOS/2 ) );
}
function loadTextures()
{
var manager = new THREE.LoadingManager();
var loader = new THREE.OBJLoader( manager );
// load OBJ plus MTL (plus TGA files)
THREE.Loader.Handlers.add( /.tga$/i, new THREE.TGALoader() );
var m = new THREE.MTLLoader();
m.setTexturePath ( "/uploads/starter/" );
m.setPath ( "/uploads/starter/" );
m.load( "Peter_Parker.mtl", function( materials ) {
materials.preload();
var o = new THREE.OBJLoader();
o.setMaterials ( materials );
o.setPath ( "/uploads/starter/" );
o.load( "Peter_Parker.obj", function ( object ) {
buildenemy ( object );
} );
} );
// load OBJ plus MTL (plus TGA files)
m.load( "Peter_Parker.mtl", function( materials ) {
materials.preload();
var o = new THREE.OBJLoader();
o.setMaterials ( materials );
o.setPath ( "/uploads/starter/" );
o.load( "Peter_Parker.obj", function ( object ) {
buildagent ( object );
} );
} );
//change path
m.setPath ( "/uploads/mcadamm4/" );
m.load( "bomb.mtl", function( materials ) {
materials.preload();
var o = new THREE.OBJLoader();
o.setMaterials ( materials );
o.setPath ( "/uploads/mcadamm4/" );
o.load( "bomb.obj", function ( object ) {
buildAgentBomb ( object );
} );
} );
m.load( "bomb.mtl", function( materials ) {
materials.preload();
var o = new THREE.OBJLoader();
o.setMaterials ( materials );
o.setPath ( "/uploads/mcadamm4/" );
o.load( "bomb.obj", function ( object ) {
buildEnemyBomb ( object );
} );
} );
var loader1 = new THREE.TextureLoader();
loader1.load ( '/uploads/mcadamm4/novaexplosion.jpg', function ( thetexture ) {
thetexture.minFilter = THREE.LinearFilter;
paintExplosion ( new THREE.MeshBasicMaterial( { map: thetexture } ) );
} );
var loader2 = new THREE.TextureLoader();
loader2.load ( '/uploads/mcadamm4/blocks.jpg', function ( thetexture ) {
thetexture.minFilter = THREE.LinearFilter;
paintWalls ( new THREE.MeshBasicMaterial( { map: thetexture } ) );
} );
var loader3 = new THREE.TextureLoader();
loader3.load ( '/uploads/mcadamm4/blocks.jpg', function ( thetexture ) {
thetexture.minFilter = THREE.LinearFilter;
paintStrongBlocks ( new THREE.MeshBasicMaterial( { map: thetexture } ));
} );
var loader4 = new THREE.TextureLoader();
loader4.load ( '/uploads/mcadamm4/wood.jpg', function ( thetexture ) {
thetexture.minFilter = THREE.LinearFilter;
paintWeakBlocks ( new THREE.MeshBasicMaterial( { map: thetexture } ));
} );
}
function initSkybox()
{
// urban photographic skyboxes, credit:
// http://opengameart.org/content/urban-skyboxes
var materialArray = [
( new THREE.MeshBasicMaterial ( { map: THREE.ImageUtils.loadTexture( "/uploads/starter/dawnmountain-xpos.png" ), side: THREE.BackSide } ) ),
( new THREE.MeshBasicMaterial ( { map: THREE.ImageUtils.loadTexture( "/uploads/starter/dawnmountain-xneg.png" ), side: THREE.BackSide } ) ),
( new THREE.MeshBasicMaterial ( { map: THREE.ImageUtils.loadTexture( "/uploads/starter/dawnmountain-ypos.png" ), side: THREE.BackSide } ) ),
( new THREE.MeshBasicMaterial ( { map: THREE.ImageUtils.loadTexture( "/uploads/starter/dawnmountain-yneg.png" ), side: THREE.BackSide } ) ),
( new THREE.MeshBasicMaterial ( { map: THREE.ImageUtils.loadTexture( "/uploads/starter/dawnmountain-zpos.png" ), side: THREE.BackSide } ) ),
( new THREE.MeshBasicMaterial ( { map: THREE.ImageUtils.loadTexture( "/uploads/starter/dawnmountain-zneg.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 initThreeMaze()
{
var t1 = 0;
var t2 = 0;
for (var i = 0; i < gridsize ; i++)
for (var j = 0; j < gridsize ; j++)
if ( GRID[i][j] == GRID_MAZE )
{
var strongShape = new THREE.BoxGeometry( squaresize, squaresize, squaresize );
var strongCube = new THREE.Mesh( strongShape );
strongCube.material.color.setHex( BLANKCOLOR );
strongCube.position.x = translate ( i * squaresize );
strongCube.position.z = translate ( j * squaresize );
strongCube.position.y = 0;
threeworld.scene.add(strongCube);
STRONGCUBES[t1] = strongCube; // save it for later
t1++;
}
else if ( GRID[i][j] == GRID_WEAK )
{
var weakShape = new THREE.BoxGeometry( squaresize, squaresize, squaresize );
var weakCube = new THREE.Mesh( weakShape );
weakCube.material.color.setHex( BLANKCOLOR );
weakCube.position.x = translate ( i * squaresize );
weakCube.position.z = translate ( j * squaresize );
weakCube.position.y = 0;
threeworld.scene.add(weakCube);
WEAKCUBES[t2] = weakCube; // save it for later
t2++;
}
}
var strongArray = new Array(7); //This sets out the positions of the strong blocks on the grid
strongArray[0] = [5,9];
strongArray[1] = [2,4,5,6,8,9,10,12];
strongArray[2] = [2,12];
strongArray[3] = [2,3,5,6,8,9,11,12];
strongArray[4] = [5,9]
strongArray[5] = [2,3,5,7,9,11,12];
strongArray[6] = [1,2,7,12,13];
function initLogicalStrongBlocks() //Strong blocks cannot be blown up
{
var i = 0;
for(var j=1; j<=7; j++) //Top half of grid
{
for(var n=0; n<strongArray[i].length; n++)
{
GRID[strongArray[i][n]][j] = GRID_MAZE;
}
i++;
}
var k=0;
for(var l=13; l>=8; l--) //Bottom half of grid
{
for(var m=0; m<strongArray[k].length; m++)
{
GRID[strongArray[k][m]][l] = GRID_MAZE;
}
k++;
}
}
var weakArray = new Array(7); //This sets out the positions of the weak blocks on the grid
weakArray[0] = [8];
weakArray[1] = [1,3,7,11,13];
weakArray[2] = [5,9];
weakArray[3] = [1,7];
weakArray[4] = [2,3,11,12]
weakArray[5] = [6,8];
weakArray[6] = [4,10];
function initLogicalWeakBlocks() //Weak blocks can be blown up
{
var i = 0;
for(var j=1; j<=7; j++) //Top half of the grid
{
for(var n=0; n<weakArray[i].length; n++)
{
GRID[weakArray[i][n]][j] = GRID_WEAK;
}
i++;
}
var k=0;
for(var l=13; l>=8; l--) //Bottom half of the grid
{
for(var m=0; m<weakArray[k].length; m++)
{
GRID[weakArray[k][m]][l] = GRID_WEAK;
}
k++;
}
}
//PAINT
function paintEnemy ( child )
{
if ( child instanceof THREE.Mesh )
{
child.material.map = THREE.ImageUtils.loadTexture( "/uploads/starter/ghost.3.png" );
}
}
function paintAgent ( child )
{
if ( child instanceof THREE.Mesh )
{
child.material.map = THREE.ImageUtils.loadTexture( "/uploads/starter/pacman.jpg" );
}
}
function paintWalls ( material )
{
for ( var i = 0; i < WALLS.length; i++ )
{
if ( WALLS[i] )
WALLS[i].material = material;
}
}
function paintStrongBlocks ( material )
{
for ( var i = 0; i < STRONGCUBES.length; i++ )
{
if ( STRONGCUBES[i] )
STRONGCUBES[i].material = material;
}
}
function paintWeakBlocks ( material )
{
for ( var i = 0; i < WEAKCUBES.length; i++ )
{
if ( WEAKCUBES[i] )
WEAKCUBES[i].material = material;
}
}
function paintExplosion( material )
{
for(var i=0; i<=10; i++)
{
var shape = new THREE.SphereGeometry( 80, 80, 80 );
var sphere = new THREE.Mesh( shape );
sphere.material.color.setHex( BLANKCOLOR );
EXPLOSIONS[i] = sphere;
EXPLOSIONS[i].material = material;
}
}
// --- ENEMY -----------------------------------
function initLogicalEnemy()
{
ei = 1;
ej = 1;
}
function buildenemy ( object )
{
object.scale.multiplyScalar ( 50 ); // make 3d object n times bigger
object.traverse( paintEnemy );
theenemy = object;
//Starting Position of enemy one
theenemy.position.x = translate ( 1 * squaresize );
theenemy.position.y = ( -50 );
theenemy.position.z = translate ( 1 * squaresize );
threeworld.scene.add( theenemy );
}
function drawEnemy() // given ei, ej, draw it
{
if ( theenemy )
{
var x = translate ( ei * squaresize );
var z = translate ( ej * squaresize );
var y = -50;
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 igetAction()
{
if ( ei < ai )
return ( ACTION_RIGHT );
if ( ei > ai )
return ( ACTION_LEFT );
return ( ACTION_STAYSTILL );
}
function jgetAction()
{
if ( ej < aj )
return ( ACTION_UP );
if ( ej > aj )
return ( ACTION_DOWN );
return ( ACTION_STAYSTILL );
}
function enemyGetAction()
{
return randomPick ( igetAction(), jgetAction() );
}
function moveLogicalEnemy()
{
if(!enemyBombPlaced) //Enemy moves randomly until he sets a bomb, then he must escape the bombs blast
var a = enemyGetAction();
var i = ei;
var j = ej;
var bool = false;
if( occupiedByAgentBomb((ei-1),ej) || //Is there an agent bomb nearby that he must escape
occupiedByAgentBomb((ei+1),ej) ||
occupiedByAgentBomb(ei,(ej-1)) ||
occupiedByAgentBomb(ei,(ej+1)))
{
bool = true; //Make sure enemy dosnt move again after escaping
switch (esacpeDirection())
//Quite a few of the cases may be redundant if I have time I can cut the cases down
//by coupling AND's that have equivelant effects in the esacpeDirection() method
{
case 0://Left
i-=2;
ei = i;
ej = j;
break;
case 1://Right
i+=2;
ei = i;
ej = j;
break;
case 2://Up
j-=2;
ei = i;
ej = j;
break;
case 3://Down
j+=2;
ei = i;
ej = j;
break;
case 4://Left & Up
i--;
j--;
ei = i;
ej = j;
break;
case 5://Left & Down
i--;
j++;
ei = i;
ej = j;
break;
case 6://Right & Up
i++;
j--;
ei = i;
ej = j;
break;
case 7://Right & Down
i++;
j++;
ei = i;
ej = j;
break;
case 8://Down & Left
j++;
i--;
ei = i;
ej = j;
break;
case 9://Down & right
j++;
i++;
ei = i;
ej = j;
break;
case 10://Up and left
j--;
i--;
ei = i;
ej = j;
break;
case 11://Up and right
j--;
i++;
ei = i;
ej = j;
break;
case 12:
break;
}
}
if( occupiedByPlayer((ei-1),ej) ||
occupiedByPlayer((ei+1),ej) ||
occupiedByPlayer(ei,(ej-1)) ||
occupiedByPlayer(ei,(ej+1)) ||
occupiedByWeakBox((ei-1),ej) ||
occupiedByWeakBox((ei+1),ej) ||
occupiedByWeakBox(ei,(ej-1)) ||
occupiedByWeakBox(ei,(ej+1)))
{
bool = true;
switch (esacpeDirection())
//Quite a few of the cases may be redundant if I have time I can cut the cases down
//by coupling AND's with equivelant effects in the esacpeDirection() method
{
case 0://Left
i-=2;
enemyDrawBomb( ei, ej );
console.log(i,j);
ei = i;
ej = j;
break;
case 1://Right
i+=2;
enemyDrawBomb( ei, ej );
console.log(i,j);
ei = i;
ej = j;
break;
case 2://Up
j-=2;
enemyDrawBomb( ei, ej );
ei = i;
ej = j;
break;
case 3://Down
j+=2;
enemyDrawBomb( ei, ej );
ei = i;
ej = j;
break;
case 4://Left & Up
i--;
j--;
enemyDrawBomb( ei, ej );
ei = i;
ej = j;
break;
case 5://Left & Down
i--;
j++;
enemyDrawBomb( ei, ej );
ei = i;
ej = j;
break;
case 6://Right & Up
i++;
j--;
enemyDrawBomb( ei, ej );
ei = i;
ej = j;
break;
case 7://Right & Down
i++;
j++;
enemyDrawBomb( ei, ej );
ei = i;
ej = j;
break;
case 8://Down & Left
j++;
i--;
enemyDrawBomb( ei, ej );
ei = i;
ej = j;
break;
case 9://Down & right
j++;
i++;
enemyDrawBomb( ei, ej );
ei = i;
ej = j;
break;
case 10://Up and left
j--;
i--;
enemyDrawBomb( ei, ej );
ei = i;
ej = j;
break;
case 11://Up and right
j--;
i++;
enemyDrawBomb( ei, ej );
ei = i;
ej = j;
break;
case 12:
break;
}
}
if ( a == ACTION_LEFT && !bool) //If just moving randomly and not escaping his bomb
i--;
else if ( a == ACTION_RIGHT && !bool)
i++;
else if ( a == ACTION_UP && !bool)
j++;
else if ( a == ACTION_DOWN && !bool)
j--;
if ( !occupied(i,j) && !bool )
{
if ( true )
{
if ( a == ACTION_LEFT )
rotateEnemyTowards ( 3 * (Math.PI / 2) );
else if ( a == ACTION_RIGHT )
rotateEnemyTowards ( 1 * (Math.PI / 2) );
else if ( a == ACTION_UP )
rotateEnemyTowards ( 0 * (Math.PI / 2) );
else if ( a == ACTION_DOWN )
rotateEnemyTowards ( 2 * (Math.PI / 2) );
}
ei = i;
ej = j;
}
}
function esacpeDirection() //This method allows the enemy to escape the blasts of bombs if there is space
{
if (!occupied((ei-1),ej) && !occupied((ei-2),ej))
return 0; //Left
if(!occupied((ei+1),ej) && !occupied((ei+2),ej))
return 1; //Right
if(!occupied(ei,(ej-1)) && !occupied(ei,(ej-2)))
return 2; //Up
if(!occupied(ei,(ej+1)) && !occupied(ei,(ej+2)))
return 3; //Down
if(!occupied((ei-1),ej) && !occupied((ei-1),(ej-1)))
return 4; //Left & Up
if(!occupied((ei-1),ej) && !occupied((ei-1),(ej+1)))
return 5;//Left & Down
if(!occupied((ei+1),ej) && !occupied((ei+1),(ej-1)))
return 6;//Right & Up
if(!occupied((ei+1),ej) && !occupied((ei+1),(ej+1)))
return 7;//Right & Down
if(!occupied(ei,(ej+1)) && !occupied((ei-1),(ej+1)))
return 8;//Down & Left
if(!occupied(ei,(ej+1)) && !occupied((ei+1),(ej+1)))
return 9;//Down & right
if(!occupied(ei,(ej-1)) && !occupied((ei-1),(ej-1)))
return 10;//Up and left
if(!occupied(ei,(ej-1)) && !occupied((ei+1),(ej-1)))
return 11;//Up and right
else
return 12;//No escape route
}
const INTERIMROT = 10; // number of interim rotations drawn when model turns round
// interim renders not working
// temporary solution - rotate half-way - will continue the rotation later
function rotateEnemyTowards ( newRotation )
{
if ( enemyRotation == newRotation )
return;
var x = ( enemyRotation + newRotation ) / 2;
theenemy.rotation.set ( 0, x, 0 );
enemyRotation = x;
}
function buildAgentBomb( object )
{
object.scale.multiplyScalar ( 300 ); // make 3d object n times bigger
agentBomb = object;
}
function buildEnemyBomb( object )
{
object.scale.multiplyScalar ( 300 ); // make 3d object n times bigger
enemyBomb = object;
}
//DROP A BOMB
function agentDrawBomb()
{
//To void bugs, we can't throw bombs if there is alrdy one
if(noBomb)
{
noBomb = false;
agentbombi = ai; //Drop bomb at agents position
agentbombj = aj;
agentBomb.position.x = theagent.position.x;
agentBomb.position.y = (theagent.position.y + 50);
agentBomb.position.z = theagent.position.z;
threeworld.scene.add( agentBomb ); // Add a bomb
setTimeout(agentBombExplode, 2000); //Delay the bombs explosion so agent can clear the area
setTimeout(removeAgentBomb, 2000); //Delay the bombs removal to coincide with explosion
}
}
function enemyDrawBomb( enemyi, enemyj )
{
enemyBombPlaced = true;
enemybombi = enemyi; //Drop bomb at enemy's position
enemybombj = enemyj;
enemyBomb.position.x = theenemy.position.x;
enemyBomb.position.y = (theenemy.position.y + 50);
enemyBomb.position.z = theenemy.position.z;
threeworld.scene.add( enemyBomb ); // Add a bomb
setTimeout(enemyBombExplode, 2000); //Delay the bombs explosion enemy can clear the area
setTimeout(removeEnemyBomb, 2000); //Delay the bombs removal to coincide with explosion
}
function removeAgentBomb()
{
threeworld.scene.remove( agentBomb );
}
function removeEnemyBomb()
{
threeworld.scene.remove( enemyBomb );
enemyBombPlaced = false;
}
function agentBombExplode()
{
agentmiddle = EXPLOSIONS[0]; //Show explosions and then remove them
agentleftBlock = EXPLOSIONS[1];
agentrightBlock = EXPLOSIONS[2];
agentupBlock = EXPLOSIONS[3];
agentdownBlock = EXPLOSIONS[4];
//-------------------------------------------
//The explosions form a cross so five need to be added
var x = translate ( agentbombi * squaresize );
var z = translate ( agentbombj * squaresize );
var y = ( 0 );
agentmiddle.position.x = x;
agentmiddle.position.y = y;
agentmiddle.position.z = z;
threeworld.scene.add(agentmiddle);
//-------------------------------------------
var leftx = translate ( (agentbombi-1) * squaresize );
var leftz = translate ( agentbombj * squaresize );
var lefty = ( 0 );
agentleftBlock.position.x = leftx;
agentleftBlock.position.y = lefty;
agentleftBlock.position.z = leftz;
threeworld.scene.add(agentleftBlock);
//-------------------------------------------
var rightx = translate ( (agentbombi+1) * squaresize );
var rightz = translate ( agentbombj * squaresize );
var righty = ( 0 );
agentrightBlock.position.x = rightx;
agentrightBlock.position.y = righty;
agentrightBlock.position.z = rightz;
threeworld.scene.add(agentrightBlock);
//-------------------------------------------
var upx = translate ( agentbombi * squaresize );
var upz = translate ( (agentbombj-1) * squaresize );
var upy = ( 0 );
agentupBlock.position.x = upx;
agentupBlock.position.y = upy;
agentupBlock.position.z = upz;
threeworld.scene.add(agentupBlock);
//-------------------------------------------
var downx = translate ( agentbombi * squaresize );
var downz = translate ( (agentbombj+1) * squaresize );
var downy = ( 0 );
agentdownBlock.position.x = downx;
agentdownBlock.position.y = downy;
agentdownBlock.position.z = downz;
threeworld.scene.add(agentdownBlock);
setTimeout(removeAgentExplosion, 500);
noBomb = true;
//-------------------------------------------
//Remove any weak blocks that were hit in the blast
for( var n=0; n<WEAKCUBES.length; n++ )
{
if( WEAKCUBES[n].position.x == leftx && WEAKCUBES[n].position.z == leftz)
{
threeworld.scene.remove(WEAKCUBES[n]);
GRID[(agentbombi-1)][agentbombj] = GRID_BLANK;
}
if( WEAKCUBES[n].position.x == rightx && WEAKCUBES[n].position.z == rightz)
{
threeworld.scene.remove(WEAKCUBES[n]);
GRID[(agentbombi+1)][agentbombj] = GRID_BLANK;
}
if( WEAKCUBES[n].position.x == upx && WEAKCUBES[n].position.z == upz)
{
threeworld.scene.remove(WEAKCUBES[n]);
GRID[agentbombi][(agentbombj-1)] = GRID_BLANK;
}
if( WEAKCUBES[n].position.x == downx && WEAKCUBES[n].position.z == downz )
{
threeworld.scene.remove(WEAKCUBES[n]);
GRID[agentbombi][(agentbombj+1)] = GRID_BLANK;
}
agentbombExploding = true;
}
//-------------------------------------------
}
function enemyBombExplode()
{
enemymiddle = EXPLOSIONS[5]; //Show explosions and then remove them
enemyleftBlock = EXPLOSIONS[6];
enemyrightBlock = EXPLOSIONS[7];
enemyupBlock = EXPLOSIONS[8];
enemydownBlock = EXPLOSIONS[9];
//-------------------------------------------
var x = translate ( enemybombi * squaresize );
var z = translate ( enemybombj * squaresize );
var y = ( 0 );
enemymiddle.position.x = x;
enemymiddle.position.y = y;
enemymiddle.position.z = z;
threeworld.scene.add(enemymiddle);
//-------------------------------------------
var leftx = translate ( (enemybombi-1) * squaresize );
var leftz = translate ( enemybombj * squaresize );
var lefty = ( 0 );
enemyleftBlock.position.x = leftx;
enemyleftBlock.position.y = lefty;
enemyleftBlock.position.z = leftz;
threeworld.scene.add(enemyleftBlock);
//-------------------------------------------
var rightx = translate ( (enemybombi+1) * squaresize );
var rightz = translate ( enemybombj * squaresize );
var righty = ( 0 );
enemyrightBlock.position.x = rightx;
enemyrightBlock.position.y = righty;
enemyrightBlock.position.z = rightz;
threeworld.scene.add(enemyrightBlock);
//-------------------------------------------
var upx = translate ( enemybombi * squaresize );
var upz = translate ( (enemybombj-1) * squaresize );
var upy = ( 0 );
enemyupBlock.position.x = upx;
enemyupBlock.position.y = upy;
enemyupBlock.position.z = upz;
threeworld.scene.add(enemyupBlock);
//-------------------------------------------
var downx = translate ( enemybombi * squaresize );
var downz = translate ( (enemybombj+1) * squaresize );
var downy = ( 0 );
enemydownBlock.position.x = downx;
enemydownBlock.position.y = downy;
enemydownBlock.position.z = downz;
threeworld.scene.add(enemydownBlock);
setTimeout(removeEnemyExplosion, 500);
//-------------------------------------------
//Remove any weak blocks that were hit in the blast
for( var n=0; n<WEAKCUBES.length; n++ )
{
if( WEAKCUBES[n].position.x == leftx && WEAKCUBES[n].position.z == leftz)
{
threeworld.scene.remove(WEAKCUBES[n]);
GRID[(enemybombi-1)][enemybombj] = GRID_BLANK;
}
if( WEAKCUBES[n].position.x == rightx && WEAKCUBES[n].position.z == rightz)
{
threeworld.scene.remove(WEAKCUBES[n]);
GRID[(enemybombi+1)][enemybombj] = GRID_BLANK;
}
if( WEAKCUBES[n].position.x == upx && WEAKCUBES[n].position.z == upz)
{
threeworld.scene.remove(WEAKCUBES[n]);
GRID[enemybombi][(enemybombj-1)] = GRID_BLANK;
}
if( WEAKCUBES[n].position.x == downx && WEAKCUBES[n].position.z == downz )
{
threeworld.scene.remove(WEAKCUBES[n]);
GRID[enemybombi][(enemybombj+1)] = GRID_BLANK;
}
enemybombExploding = true; //Stops the enemy moving back into his own bombs blast
}
}
function removeAgentExplosion()
{
threeworld.scene.remove(agentmiddle);
threeworld.scene.remove(agentleftBlock);
threeworld.scene.remove(agentrightBlock);
threeworld.scene.remove(agentupBlock);
threeworld.scene.remove(agentdownBlock);
}
function removeEnemyExplosion()
{
threeworld.scene.remove(enemymiddle);
threeworld.scene.remove(enemyleftBlock);
threeworld.scene.remove(enemyrightBlock);
threeworld.scene.remove(enemyupBlock);
threeworld.scene.remove(enemydownBlock);
}
function agentBlownUp() //Did the Agent get blown up in the explosion
{
if( occupiedByPlayer(agentbombi,agentbombj) ||
occupiedByPlayer((agentbombi-1),agentbombj) ||
occupiedByPlayer((agentbombi+1),agentbombj) ||
occupiedByPlayer(agentbombi,(agentbombj-1)) ||
occupiedByPlayer(agentbombi,(agentbombj+1)))
return true;
agentbombi = 0; //Reset bomb position to outside map
agentbombj = 0;
return false;
}
function enemyBlownUp() //Did the Enemy get blown up in the explosion
{
if( occupiedByPlayer(enemybombi,enemybombj) ||
occupiedByPlayer((enemybombi-1),enemybombj) ||
occupiedByPlayer((enemybombi+1),enemybombj) ||
occupiedByPlayer(enemybombi,(enemybombj-1)) ||
occupiedByPlayer(enemybombi,(enemybombj+1)))
return true;
enemybombi = 14; //Reset bomb position to outside map
enemybombj = 14;
return false;
}
function occupiedByPlayer ( i, j ) // is this square occupied by a player
{
if ( ( ei == i ) && ( ej == j ) )
return true; // variable objects
if ( ( ai == i ) && ( aj == j ) )
return true;
return false;
}
function occupiedByWeakBox( i, j)
{
if( (GRID[i][j] == GRID_WEAK) )
return true;
return false;
}
function occupiedByAgentBomb( i, j)
{
if( (agentbombi==i) && (agentbombj==j) )
return true;
return false;
}
// --- AGENT -----------------------------------
function initLogicalAgent()
{
ai = 13;
aj = 13;
}
function buildagent ( object )
{
object.scale.multiplyScalar ( 50 ); // make 3d object n times bigger
object.traverse( paintAgent );
theagent = object;
//Starting Position of enemy one
theagent.position.x = translate ( 13 * squaresize );
theagent.position.y = ( -50 );
theagent.position.z = translate ( 13 * squaresize );
theagent.rotation.set ( 0, 3, 0 );
threeworld.scene.add( theagent );
}
function drawAgent() // given ai, aj, draw it
{
if ( theagent )
{
var x = translate ( ai * squaresize );
var z = translate ( aj * squaresize );
var y = -50;
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 moveLogicalAgent( a ) //Agent is controlled by the user via keyboard
{
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) )
{
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, +270
if ( a == ACTION_LEFT )
rotateAgentTowards ( 3 * (Math.PI / 2) );
else if ( a == ACTION_RIGHT )
rotateAgentTowards ( 1 * (Math.PI / 2) );
else if ( a == ACTION_UP )
rotateAgentTowards ( 0 * (Math.PI / 2) );
else if ( a == ACTION_DOWN )
rotateAgentTowards ( 2 * (Math.PI / 2) );
}
ai = i;
aj = j;
}
}
function rotateAgentTowards ( newRotation )
{
if ( agentRotation == newRotation )
return;
var x = ( agentRotation + newRotation ) / 2;
theagent.rotation.set ( 0, x, 0 );
agentRotation = x;
}
function keyHandler(e)
{
// user control
// Note that this.takeAction(a) is constantly running at same time, redrawing the screen.
if (e.keyCode == 32)
agentDrawBomb();
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 );
}
function headerText()
{
var status = "[SPACEBAR] = Drop Bomb , [Arrow Keys] = Move Agent ";
$("#user_span1").html( status );
}
//--- public functions / interface / API ----------------------------------------------------------
this.endCondition; // If set to true, run will end.
this.newRun = function()
{
steps = 0;
this.endCondition = false;
initGrid();
initLogicalWalls();
initLogicalStrongBlocks();
initLogicalWeakBlocks();
initLogicalAgent();
initLogicalEnemy();
if ( true )
{
threeworld.init3d ( startRadiusConst, maxRadiusConst, SKYCOLOR );
// LIGHT
var 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);
// MUSIC
var x = "<audio id=theaudio src=/uploads/mcadamm4/westworld.mp3 autoplay loop> </audio>" ;
$("#user_span2").html( x );
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.nextStep = function()
{
var a = 4;
steps++;
headerText();
if(steps%5==0)
setTimeout(moveLogicalEnemy,4000);
if ( true )
{
drawAgent();
drawEnemy();
if(agentbombExploding) //Is there a bomb exploding
{
agentbombExploding = false; //Bomb has exploded so reset
if(agentBlownUp()) // Has someone been blown up by the bomb
{
this.endCondition = true;
var x = "<audio id=theaudio src=/uploads/mcadamm4/gameover.mp3 autoplay loop> </audio>" ;
$("#user_span2").html( x );
}
}
if(enemybombExploding) //Is there a bomb exploding
{
enemybombExploding = false; //Bomb has exploded so reset
if(enemyBlownUp()) // Has someone been blown up by the bomb
{
this.endCondition = true;
var x = "<audio id=theaudio src=/uploads/mcadamm4/gameover.mp3 autoplay loop> </audio>" ;
$("#user_span2").html( x );
}
}
}
};
this.endRun = function()
{
var status = "GAME OVER!!";
$("#user_span1").html( status );
};
}
//---- end of World class -------------------------------------------------------