Code viewer for World: Pac-Man (clone by Cbum)

// Cloned by Cbum on 5 Dec 2022 from World "Pac-Man" by Cbum 
// Please leave this clone trail here.
 
// Cloned by Cbum on 5 Dec 2022 from World "Zombie Death Baby" by Starter user 
// Please leave this clone trail here.
 


// ==== Starter World =================================================================================================
// This code is designed for use on the Ancient Brain site.
// This code may be freely copied and edited by anyone on the Ancient Brain site.
// To include a working run of this program on another site, see the "Embed code" links provided on Ancient Brain.
// ====================================================================================================================




// Putting it all together - How to make a touch game for mobile
// Based on Complex World and Touch World 

// touch drag of objects, touch hit of objects 
// mouse drag of objects, mouse click on objects 

// Splash screen (so click can auto-start audio) 
// Behind the splash screen, it is loading resources while waiting for you to click 
 
 
// Mobile:
// Touch drag to move agent     
// Touch tap to "zap" baby
// Touch pinch camera (built in)

// Desktop:
// Mouse drag to move agent     
// Mouse click to "zap" baby
// Mouse scroll camera (built in)

 
// ============================================================================================= 
// To do my own mouse/touch: 
// Over-ride certain "ABHandler" functions.  
// =============================================================================================

// Name inspired by "Sonic Death Monkey" in "High Fidelity"

 
 
 
 
 

// ===================================================================================================================
// === Start of tweaker's box ======================================================================================== 
// ===================================================================================================================

// The easiest things to modify are in this box.
// You should be able to change things in this box without being a JavaScript programmer.
// Go ahead and change some of these. What's the worst that could happen?

	
AB.clockTick       = 100;    

	// Speed of run: Step every n milliseconds. Default 100.
	
AB.maxSteps        = 1000000;   	// make it so run in practice never ends until user wants
									// if do put in a maximum run, 1000 is a pretty long run 

	// Length of run: Maximum length of run in steps. Default 1000.

AB.screenshotStep  = 200;   
  
	// Take screenshot on this step. (All resources should have finished loading.) Default 50.

AB.drawRunControls = false;
	
	// Scrap the Run/Step/Pause controls

	

//---- global constants: -------------------------------------------------------
	
// Switch between 3d and 2d view
const show3d =  false;	

const TEXTURE_WALL 	= '/uploads/kevin/maze.png' ;
const TEXTURE_MAZE 	= '/uploads/kevin/maze.png' ;
const TEXTURE_AGENT = '/uploads/kevin/pacman.png' ;
 
const TEXTURE_BABY 	= '/uploads/kevin/ghost.png' ;
const TEXTURE_DEAD 	= '/uploads/starter/ghost.3.png' ;
 
const SOUND_MAMA 	= '/uploads/kevin/ghostsiren.mp3';
const SOUND_SCREAM 	= '/uploads/kevin/eatghost.mp3';

const MUSIC_BACK  = '/uploads/kevin/wakawaka.mp3' ;

const SOUND_ALARM = '/uploads/kevin/gamelose.mp3' ;



const gridsize = 36;						// number of squares along side of world	   

const NOBOXES =  Math.trunc ( (gridsize * gridsize) / 10 );
		// density of maze - number of internal boxes

const squaresize 	= 100;						// size of square in pixels
const MAXPOS 		= gridsize * squaresize;	// length of one side in pixels 
	
const SKYCOLOR 		= 'black';					// a number, not a string 

 
const startRadiusConst	 	= MAXPOS * 1 ;			// distance from centre to start the camera at
const maxRadiusConst 		= MAXPOS * 10  ;		// maximum distance from camera we will render things  


// CSS style used for score output:
const scoreStyle = "font-weight: bold;  font-family: Segoe Print, Comic Sans, Impact, Bolton;";


	const NONEWBABIES 	= 2;			// how many babies to make when I kill one 

	const SCORE_KILL 	= 500;			// add this to score for every kill of a baby 

	const SCORE_CLOSE 	= -10;			// add this to score for every step close to a baby 

	
	

//--- change ABWorld defaults: -------------------------------

ABHandler.MAXCAMERAPOS 	= maxRadiusConst ;

ABHandler.GROUNDZERO		= true;						// "ground" exists at altitude zero

ABWorld.drawCameraControls = false; 


//--- skybox: -------------------------------

const SKYBOX_ARRAY = [										 
                "/uploads/kevin/arcade2.jpg",
                "/uploads/kevin/arcade2.jpg",
                "/uploads/kevin/arcade2.jpg",
                "/uploads/kevin/arcade2.jpg",
                "/uploads/kevin/arcade2.jpg",
                "/uploads/kevin/arcade2.jpg"
                ];
				
// ===================================================================================================================
// === End of tweaker's box ==========================================================================================
// ===================================================================================================================

// You will need to be some sort of JavaScript programmer to change things below the tweaker's box.

// can write CSS to page 
// document.write (of CSS at least) is good at the moment we include the JS, not later
 
 document.write ( ` <style>

    .mybutton 
    {
        border-radius: 0px;
        background-color: darkslategrey;	 
    }
        
    .mybutton:hover { background-color: darkcyan; }

    </style> ` );

 // we have a splash screen
 // behind the splash screen, newRun is running, loading resources 
 // do not start the run loop until resources ready AND splash screen is dismissed 

	var resourcesLoaded = false;
	var splashClicked = false;
	
	

const ACTION_LEFT 			= 0;		   
const ACTION_RIGHT 			= 1;
const ACTION_UP 			= 2;		 
const ACTION_DOWN 			= 3;
const ACTION_STAYSTILL 		= 4;

// in initial view, (smaller-larger) on i axis is aligned with (left-right)
// in initial view, (smaller-larger) on j axis is aligned with (away from you - towards you)



// contents of a grid square

const GRID_BLANK 	= 0;
const GRID_WALL 	= 1;
const GRID_MAZE 	= 2;
const GRID_AGENT 	= 3;
const GRID_BABY		= 4;
const GRID_DEAD		= 5;
 
 

 

var BOXHEIGHT;		// 3d or 2d box height 

var GRID 	= new Array ( gridsize );			// will in fact be a 2D array, see later   

var theagent;

var BABIES 	= new Array ( 1 ); 		 		// start at 1 and increase using array.push()


var wall_texture, agent_texture, baby_texture, dead_texture, maze_texture; 

// agent position  
var ai, aj;

var score;

 
 
	
function loadResources()		// asynchronous file loads - call initScene() when all finished 
{
	var loader1 = new THREE.TextureLoader();
	var loader2 = new THREE.TextureLoader();
	var loader3 = new THREE.TextureLoader();
	var loader4 = new THREE.TextureLoader();
	var loader5 = new THREE.TextureLoader();
	
	loader1.load ( TEXTURE_WALL, function ( thetexture )  		
	{
		thetexture.minFilter  = THREE.LinearFilter;
		wall_texture = thetexture;
		if ( asynchFinished() )	initScene();		// if all file loads have returned 
	});
		
	loader2.load ( TEXTURE_AGENT, function ( thetexture )  	 
	{
		thetexture.minFilter  = THREE.LinearFilter;
		agent_texture = thetexture;
		if ( asynchFinished() )	initScene();		 
	});	
	
	loader3.load ( TEXTURE_BABY, function ( thetexture )  
	{
		thetexture.minFilter  = THREE.LinearFilter;
		baby_texture = thetexture;
		if ( asynchFinished() )	initScene();		 
	});
	
	loader4.load ( TEXTURE_MAZE, function ( thetexture )  
	{
		thetexture.minFilter  = THREE.LinearFilter;
		maze_texture = thetexture;
		if ( asynchFinished() )	initScene();		 
	});
		
	loader5.load ( TEXTURE_DEAD, function ( thetexture )  
	{
		thetexture.minFilter  = THREE.LinearFilter;
		dead_texture = thetexture;
		if ( asynchFinished() )	initScene();		 
	});
	
}


function asynchFinished()		 // all file loads returned 
{
	if ( wall_texture && agent_texture && baby_texture && dead_texture && maze_texture )  return true; 
	else return false;
}	
	
	
 

//--- grid system -------------------------------------------------------------------------------
// my numbering is 0 to gridsize-1

	
function occupied ( i, j )		// is this square occupied
{
 return ( GRID[i][j] != GRID_BLANK );
}

 
// translate my (i,j) grid coordinates to three.js (x,y,z) coordinates
// logically, coordinates are: y=0, x and z all positive (no negative)    
// logically my dimensions are all positive 0 to MAXPOS
// to centre everything on origin, subtract (MAXPOS/2) from all dimensions 

function translate ( i, j )			
{
	var v = new THREE.Vector3();
	
	v.y = 0;	
	v.x = ( i * squaresize ) - ( MAXPOS/2 );   		 
	v.z = ( j * squaresize ) - ( MAXPOS/2 );   	
	
	return v;
}


 

 
	
function initScene()		// all file loads have returned 
{
	 var i,j, shape, thecube;
	 
	// set up GRID as 2D array
	 
	 for ( i = 0; i < gridsize ; i++ ) 
		GRID[i] = new Array(gridsize);		 


	// set up walls
	 
	 for ( i = 0; i < gridsize ; i++ ) 
	  for ( j = 0; j < gridsize ; j++ ) 
		if ( ( i==0 ) || ( i==gridsize-1 ) || ( j==0 ) || ( j==gridsize-1 ) )
		{
			GRID[i][j] = GRID_WALL;		 
			shape    = new THREE.BoxGeometry ( squaresize, BOXHEIGHT, squaresize );			 
			thecube  = new THREE.Mesh( shape );
			thecube.material = new THREE.MeshBasicMaterial( { map: wall_texture } );
			
			thecube.position.copy ( translate(i,j) ); 		  	// translate my (i,j) grid coordinates to three.js (x,y,z) coordinates 
			ABWorld.scene.add(thecube);
		}
		else 
   			GRID[i][j] = GRID_BLANK;

		
   // set up maze 
   
    for ( var c=1 ; c <= NOBOXES ; c++ )
	{
		i = AB.randomIntAtoB(1,gridsize-2);		// inner squares are 1 to gridsize-2
		j = AB.randomIntAtoB(1,gridsize-2);
			
		GRID[i][j] = GRID_MAZE ;
		
		shape    = new THREE.BoxGeometry ( squaresize, BOXHEIGHT, squaresize );			 
		thecube  = new THREE.Mesh( shape );
		thecube.material = new THREE.MeshBasicMaterial( { map: maze_texture } );		  

		thecube.position.copy ( translate(i,j) ); 		  	// translate my (i,j) grid coordinates to three.js (x,y,z) coordinates 
		ABWorld.scene.add(thecube);		
	}
	 	 
   
	// set up first baby 

		BABIES[0] = newBaby();				   
	
	 
	
	// set up agent 
	// start in random location
	
	 do
	 {
	  i = AB.randomIntAtoB(1,gridsize-2);
	  j = AB.randomIntAtoB(1,gridsize-2);
	 }
	 while ( occupied(i,j) );  	  // search for empty square 

	 ai = i;
	 aj = j;
 	 GRID[i][j] = GRID_AGENT;

	 shape    = new THREE.BoxGeometry ( squaresize, BOXHEIGHT, squaresize );			 
	 theagent = new THREE.Mesh( shape );
	 theagent.material =  new THREE.MeshBasicMaterial( { map: agent_texture } );
	 theagent.position.copy ( translate(ai,aj) ); 		  	// translate my (i,j) grid coordinates to three.js (x,y,z) coordinates 
	 ABWorld.scene.add(theagent);


 // finally skybox 
 
ABWorld.scene.background = new THREE.CubeTextureLoader().load ( SKYBOX_ARRAY,	function() 
	{ 
		ABWorld.render(); 
		
		console.log ( "Resources loaded." );
		resourcesLoaded = true;
	
		if ( resourcesLoaded && splashClicked ) 
			AB.runReady = true;  		// start run loop 
	});
}
 
  
 

// --- babies -----------------------------------
 
 
function newBaby()
{
	var i, j;
	do
	{
	  i = AB.randomIntAtoB(1,gridsize-2);
	  j = AB.randomIntAtoB(1,gridsize-2);
	}
	while ( occupied(i,j) );  	 					// search for empty square 
	 
	GRID[i][j] = GRID_BABY;
	 
	var shape    = new THREE.BoxGeometry( squaresize, BOXHEIGHT, squaresize );			 
  	var thecube  = new THREE.Mesh( shape );
	thecube.material = new THREE.MeshBasicMaterial( { map: baby_texture } );  
	
	thecube.position.copy ( translate(i,j) ); 		  	// translate my (i,j) grid coordinates to three.js (x,y,z) coordinates 

 	ABWorld.scene.add(thecube);

	return ( new Array ( thecube, i, j ) );				// save it for later, array, object plus i,j position
}


function newBabies() 		// make NONEWBABIES new babies 
{	
 	for ( var c=1 ; c <= NONEWBABIES ; c++ )
 	{
 		var baby = newBaby();		  
 		BABIES.push ( baby );					// add to array 
 	}	
 }


function moveBabies()
{ 
 for ( var c = 0; c < BABIES.length; c++ )
 { 
	var thebaby = BABIES[c][0];
	var ei 		= BABIES[c][1];
	var ej 		= BABIES[c][2];
	var i, j; 
	 
	// move towards agent 
	// put some randomness in so it won't get stuck with barriers 

	 if ( ei < ai )  i = AB.randomIntAtoB(ei, ei+1); 
	 if ( ei == ai ) i = ei; 
	 if ( ei > ai )  i = AB.randomIntAtoB(ei-1, ei); 

	 if ( ej < aj )  j = AB.randomIntAtoB(ej, ej+1); 
	 if ( ej == aj ) j = ej; 
	 if ( ej > aj )  j = AB.randomIntAtoB(ej-1, ej); 
	 
	 if ( ! occupied(i,j) )  	 	// if no obstacle then move, else just miss a turn for this baby 
	 {
		GRID[ei][ej] = GRID_BLANK;
		GRID[i][j]   = GRID_BABY;
		thebaby.position.copy ( translate(i,j) ); 		  	// translate my (i,j) grid coordinates to three.js (x,y,z) coordinates 
		BABIES[c] = new Array ( thebaby, i, j );			// update list of positions 
 	 }
 }
}





// --- agent -----------------------------------
// movement caused by user actions 


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;
	 theagent.position.copy ( translate(ai,aj) ); 		  	// translate my (i,j) grid coordinates to three.js (x,y,z) coordinates 
 }
}





// --- user actions - keyboard and touch handling functions: ----------------------------------------

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;		// number of events in the current drag 


function initDrag ( x, y )		// x,y position on screen
{
	if ( ! AB.runReady ) return true; 		// not ready yet 

	startX 	= x;						 
	startY 	= y;
	dragevents = 0;
	
	tryHitBabies ( x, y );		// check if this is a tap not a drag - and if it hits a baby 
};



function drag ( x, y )			// compare with previous x,y position on screen to get direction of drag
{
	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;
};
 
 
 
 
 
// --- kill babies and make new ones ------------------------------------------------------------------- 
 
function tryHitBabies ( x, y )		// we did an x,y touch/click, did it hit a baby 
{
 for ( var c = 0; c < BABIES.length; c++ )
 {
	var thebaby = BABIES[c][0];
	var ei 		= BABIES[c][1];
	var ej 		= BABIES[c][2];

	if ( ABWorld.hitsObject ( x, y, thebaby ) )	        // detect hit object 
	{
		soundScream();							// make a noise 

		score = score + SCORE_KILL ;			// increase score 
		 
		GRID[ei][ej] = GRID_DEAD ;    		// stationary obstacle - basically part of the maze now 

		thebaby.material = new THREE.MeshBasicMaterial( { map: dead_texture } );  
		
		// remove thebaby from array, so it will no longer move 
		BABIES.splice(c,1);			 
		
		// make new baby/babies:
		newBabies();
		
		return;						// assume only can hit one baby 
	}
 }
}
    

	

// --- score and status: -----------------------------------


function babyClose()			
// is a baby close to (within one square of) the agent
// note because of the wall, co-ordinates at +1 and -1 always exist 
{
 if ( GRID[ai-1][aj-1] == GRID_BABY ) return true;
 if ( GRID[ai-1][aj]   == GRID_BABY ) return true;
 if ( GRID[ai-1][aj+1] == GRID_BABY ) return true;

 if ( GRID[ai][aj-1]   == GRID_BABY ) return true;
 if ( GRID[ai][aj]     == GRID_BABY ) return true;
 if ( GRID[ai][aj+1]   == GRID_BABY ) return true;
 
 if ( GRID[ai+1][aj-1] == GRID_BABY ) return true;
 if ( GRID[ai+1][aj]   == GRID_BABY ) return true;
 if ( GRID[ai+1][aj+1] == GRID_BABY ) return true;
 
 return false;
}


function agentBlocked()			// agent is blocked on the 4 compass sides (not diagonal)
{
 return ( 	occupied (ai-1,aj) 		&& 
			occupied (ai+1,aj)		&&
			occupied (  ai,aj+1)	&&
			occupied (  ai,aj-1) 			);		
} 

AB.world.newRun = function() 
{
	score = 0;

	if ( show3d )
	{
	 BOXHEIGHT = squaresize;
	 ABWorld.init3d ( startRadiusConst, maxRadiusConst, SKYCOLOR  ); 	
	}	     
	else
	{
	 BOXHEIGHT = 1;
	 ABWorld.init2d ( startRadiusConst, maxRadiusConst, SKYCOLOR  ); 		     
	}
	
	
	// newRun can run behind splash screen 
	// do not start run loop until resources ready AND splash screen is dismissed 
	
	AB.runReady = false; 		
	
	loadResources();		// aynch file loads		
							// calls initScene() when it returns 

	
	// redirect keyboard and touch event handling to my own functions:  

		document.onkeydown 			= keyHandler;
 			
	// override ABHandler default (which is camera control) to use my own functions:

		myControls();
			
	// Toggle between my mouse/touch controls and default mouse/touch controls 
	var buttons = 	" <p> <button onclick='myControls();' 											class='ab-normbutton mybutton' >My controls		</button> " +
					"     <button onclick='ABHandler.defaultTouch(); ABHandler.defaultMouse();' 	class='ab-normbutton mybutton' >Default controls	</button> </p> ";
	AB.msg ( buttons, 3 );
};

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

AB.world.nextStep = function ()
{
   for ( var c = 0; c < BABIES.length; c++ )
		if ( Math.random() < 0.05 )	
			soundMama();						// baby noises now and then, increasing as no. of babies increases 

	if ( ( AB.step % 2 ) == 0 )		moveBabies();  		// slow babies down to every nth step

	if ( babyClose() )	 score = score + SCORE_CLOSE;		// lose points every step you are close to a baby 

	AB.msg ( " Step: " + AB.step + " Score: <span style='" + scoreStyle + "'>" + score + "</span>" );		 

	
	  if ( agentBlocked() )			// if agent blocked in, run over 
	  {
		AB.abortRun = true;
		musicPause();
		soundAlarm();
	  }
};

B.world.endRun = function()
{
  musicPause(); 
  
  if ( AB.abortRun )		AB.msg ( " <br> <font color=red> <B> You are trapped. You lose!   </B> </font>    ", 2  );
  else    					AB.msg ( " <br> <font color=green> <B> Run over. You survived! </B> </font>    ", 2  );
};

// --- Background Music ----------------------------------------

var backmusic;
 	
function initMusic()		// called by user interaction 
{
	backmusic = AB.backgroundMusic ( MUSIC_BACK );
}
	
function musicPlay()   { backmusic.play();  }
function musicPause()  { backmusic.pause(); }

// --- Sound Effects ----------------------------------------
var thealarm = new Audio ( SOUND_ALARM );

var mama1 = new Audio( SOUND_MAMA );
var mama2 = new Audio( SOUND_MAMA );
var mama3 = new Audio( SOUND_MAMA );
var mama4 = new Audio( SOUND_MAMA );
var mama5 = new Audio( SOUND_MAMA );
 
var scream1 = new Audio( SOUND_SCREAM );
var scream2 = new Audio( SOUND_SCREAM );
var scream3 = new Audio( SOUND_SCREAM );
var scream4 = new Audio( SOUND_SCREAM );
var scream5 = new Audio( SOUND_SCREAM );
  
										 
function soundAlarm()
{
	thealarm.play();							  
}

function soundMama()		 // allow multiple sounds at same time 
{
	
	if ( ! AB.audioIsPlaying ( mama1 ) ) 	{ mama1.play(); return; }
	if ( ! AB.audioIsPlaying ( mama2 ) ) 	{ mama2.play(); return; }
	if ( ! AB.audioIsPlaying ( mama3 ) ) 	{ mama3.play(); return; }
	if ( ! AB.audioIsPlaying ( mama4 ) ) 	{ mama4.play(); return; }
	if ( ! AB.audioIsPlaying ( mama5 ) ) 	{ mama5.play(); return; }
	
	// else  

	var a = new Audio( SOUND_MAMA );		
	a.play();
}
 
  
function soundScream()		  // allow multiple sounds at same time
{
	
	if ( ! AB.audioIsPlaying ( scream1 ) ) 	{ scream1.play(); return; }
	if ( ! AB.audioIsPlaying ( scream2 ) ) 	{ scream2.play(); return; }
	if ( ! AB.audioIsPlaying ( scream3 ) ) 	{ scream3.play(); return; }
	if ( ! AB.audioIsPlaying ( scream4 ) ) 	{ scream4.play(); return; }
	if ( ! AB.audioIsPlaying ( scream5 ) ) 	{ scream5.play(); return; }
	
	// else  

	var a = new Audio( SOUND_SCREAM );		
	a.play();
}

// --- Intro Screen --------------------------------------------------------------
function instructionsHtml()		// HTML format string of instructions for splash screen 
{
	var s = "Pac-Man is an action maze chase video game. Run around the maze from the ghosts whilst clicking them to rack up your points! Game ends when you are overwhelmed and trapped by the ghosts!";
	
	if ( AB.onDesktop() ) 	s = s + " Desktop instructions: Arrow keys or mouse drag to move. Click the ghosts to eat them. " ;
	else 					s = s + " Mobile instructions: Touch drag to move. Touch the ghost to eat them. " ;

	s = s + SCORE_KILL + " points for eating a ghost. " + SCORE_CLOSE + " points for every step you are close to a ghost.";
	return ( s );
}

// display splash screen with instructions 
	
	AB.newSplash ( instructionsHtml() );	
	
// touch on splash screen button will mark multiple audio objects as good for JS to call without further user interaction  

	AB.splashClick ( function ()        
	{		
		thealarm.play();	thealarm.pause();		   

		mama1.play();	mama1.pause();		   
		mama2.play();	mama2.pause();		   
		mama3.play();	mama3.pause();		   
		mama4.play();	mama4.pause();		   
		mama5.play();	mama5.pause();		   

		scream1.play();	scream1.pause();		   
		scream2.play();	scream2.pause();		   
		scream3.play();	scream3.pause();		   
		scream4.play();	scream4.pause();		   
		scream5.play();	scream5.pause();		   

	 	initMusic();

		AB.removeSplash();			// remove splash screen 
		
		// ready to start run loop? 
		
		splashClicked = true;
		
		if ( resourcesLoaded && splashClicked ) 
			AB.runReady = true;  		// start run loop 
	});