Code viewer for World: Red vs Blue
//initiation of World Clock

AB.clockTick       = 100;    

//Max time
AB.maxSteps        = 100000;    

//Take a screen shot every n miliseconds
AB.screenshotStep  = 100;   
  
// Calling the textures for use on objects "Humans" and "Monsters"
const TEXTURE_HUMAN = "/uploads/octa1936/Blue_Color.jpg";

const TEXTURE_MONSTER= "/uploads/octa1936/Red_Color.jpg";

const FILE_ARRAY = ["/uploads/octa1936/Blue_Color.jpg",
                    "/uploads/octa1936/Red_Color.jpg"];
                    
                    
                    
//Credit for the Skybox images
// https://opengameart.org/content/mayhems-skyboxes
const SKYBOX_ARRAY = [										 
                "/uploads/goryacn2/h2s_bk.jpg",
                "/uploads/goryacn2/h2s_ft.jpg",
                "/uploads/goryacn2/h2s_up.jpg",
                "/uploads/goryacn2/h2s_dn.jpg",
                "/uploads/goryacn2/h2s_lf.jpg",
                "/uploads/goryacn2/h2s_rt.jpg"
                ];


const SKYCOLOR 	= 0xccffcc;

//Max size of the Armies
const ARMYSIZE = 100;

//size of objects
const objectsize = 500 ;
         
const MAXPOS                = 4000 ;            
const startRadiusConst	 	= MAXPOS * 1.5 ;
const maxRadiusConst 		= MAXPOS * 5 ;


//Initiate camera controls
ABHandler.MAXCAMERAPOS 		= MAXPOS * 10 ;

ABWorld.drawCameraControls 	= false; 

AB.drawRunControls 			= false;

// Initiate the two armies
    var THEARMY1 	= new Array( ARMYSIZE );
    
    var THEARMY2 	= new Array( ARMYSIZE );

	var textureArray = new Array ( FILE_ARRAY.length );

// Boolean variable which controls the win/lose states
var humanswin = false;
var monsterswin = false;


var theenemy, thehuman;
var enemy_texture, human_texture;



// loading the resources needed for the armies
function loadResources()
{
	for ( var i = 0; i < FILE_ARRAY.length; i++ ) 
	  startFileLoad ( i );
}


// for each item in the array, load them as a texture	
function startFileLoad ( n )
{
	var loader = new THREE.TextureLoader();

	loader.load ( FILE_ARRAY[n], function ( thetexture )  	 
	{
		thetexture.minFilter  = THREE.LinearFilter;
		textureArray[n] = thetexture;
		if ( asynchFinished() ) initArmy1(); initArmy2(); initWorld();
	});	
}

 
// Asynchronous initiation for the textures. If they exist, load resources.
function asynchFinished()
{
	for ( var i = 0; i < FILE_ARRAY.length; i++ ) 
		if ( ! textureArray[i] ) 
			return false;
		
	  return true;
}

// initiation of the armies
// both functions work in a similar manner.
// the objects are lined up in a 10*10 grid, once a row is full, 
// the x position will return to top, and the z position will move back one object length
function initArmy1()
{
 var t = 0;
 var r = 0;
 
 for ( var c=1 ; c <= ARMYSIZE / 10 ; c++ )
 {
    var shape = new THREE.BoxGeometry( objectsize, objectsize, objectsize );
  
  	var theobject  = new THREE.Mesh( shape );
  	var posx = ((objectsize * 5) - (c * objectsize));

  	theobject.position.x = posx;
  	theobject.position.z = objectsize * -2;   	
  	theobject.position.y = 0;
  	if (c > 10) theobject.position.z -= objectsize;
	
    theobject.material =  new THREE.MeshBasicMaterial ( { map: textureArray[r] } );   

	THEARMY1[t] = theobject;
	t++; 
  }
  
 for (c=1 ; c <= ARMYSIZE / 10; c++ )
 {
    shape = new THREE.BoxGeometry( objectsize, objectsize, objectsize );
  
  	theobject  = new THREE.Mesh( shape );
  	posx = ((objectsize * 5) - (c * objectsize));

  	theobject.position.x = posx;
  	theobject.position.z = objectsize * -3;   	
  	theobject.position.y = 0;
  	if (c > 10) theobject.position.z -= objectsize;
	
    theobject.material =  new THREE.MeshBasicMaterial ( { map: textureArray[r] } );   

	THEARMY1[t] = theobject;
	t++; 
  }

 for (c=1 ; c <= ARMYSIZE / 10; c++ )
 {
    shape = new THREE.BoxGeometry( objectsize, objectsize, objectsize );
  
  	theobject  = new THREE.Mesh( shape );
  	posx = ((objectsize * 5) - (c * objectsize));

  	theobject.position.x = posx;
  	theobject.position.z = objectsize * -4;   	
  	theobject.position.y = 0;
  	if (c > 10) theobject.position.z -= objectsize;
	
    theobject.material =  new THREE.MeshBasicMaterial ( { map: textureArray[r] } );   

	THEARMY1[t] = theobject;
	t++; 
  }
 
 for (c=1 ; c <= ARMYSIZE / 10; c++ )
 {
    shape = new THREE.BoxGeometry( objectsize, objectsize, objectsize );
  
  	theobject  = new THREE.Mesh( shape );
  	posx = ((objectsize * 5) - (c * objectsize));

  	theobject.position.x = posx;
  	theobject.position.z = objectsize * -5;   	
  	theobject.position.y = 0;
  	if (c > 10) theobject.position.z -= objectsize;
	
    theobject.material =  new THREE.MeshBasicMaterial ( { map: textureArray[r] } );   

	THEARMY1[t] = theobject;
	t++; 
  }
  
 for (c=1 ; c <= ARMYSIZE / 10; c++ )
 {
    shape = new THREE.BoxGeometry( objectsize, objectsize, objectsize );
  
  	theobject  = new THREE.Mesh( shape );
  	posx = ((objectsize * 5) - (c * objectsize));

  	theobject.position.x = posx;
  	theobject.position.z = objectsize * -6;   	
  	theobject.position.y = 0;
  	if (c > 10) theobject.position.z -= objectsize;
	
    theobject.material =  new THREE.MeshBasicMaterial ( { map: textureArray[r] } );   

	THEARMY1[t] = theobject;
	t++; 
  }
  
 for (c=1 ; c <= ARMYSIZE / 10; c++ )
 {
    shape = new THREE.BoxGeometry( objectsize, objectsize, objectsize );
  
  	theobject  = new THREE.Mesh( shape );
  	posx = ((objectsize * 5) - (c * objectsize));

  	theobject.position.x = posx;
  	theobject.position.z = objectsize * -7;   	
  	theobject.position.y = 0;
  	if (c > 10) theobject.position.z -= objectsize;
	
    theobject.material =  new THREE.MeshBasicMaterial ( { map: textureArray[r] } );   

	THEARMY1[t] = theobject;
	t++; 
  }
  
 for (c=1 ; c <= ARMYSIZE / 10; c++ )
 {
    shape = new THREE.BoxGeometry( objectsize, objectsize, objectsize );
  
  	theobject  = new THREE.Mesh( shape );
  	posx = ((objectsize * 5) - (c * objectsize));

  	theobject.position.x = posx;
  	theobject.position.z = objectsize * -8;   	
  	theobject.position.y = 0;
  	if (c > 10) theobject.position.z -= objectsize;
	
    theobject.material =  new THREE.MeshBasicMaterial ( { map: textureArray[r] } );   

	THEARMY1[t] = theobject;
	t++; 
  }
  
 for (c=1 ; c <= ARMYSIZE / 10; c++ )
 {
    shape = new THREE.BoxGeometry( objectsize, objectsize, objectsize );
  
  	theobject  = new THREE.Mesh( shape );
  	posx = ((objectsize * 5) - (c * objectsize));

  	theobject.position.x = posx;
  	theobject.position.z = objectsize * -9;   	
  	theobject.position.y = 0;
  	if (c > 10) theobject.position.z -= objectsize;
	
    theobject.material =  new THREE.MeshBasicMaterial ( { map: textureArray[r] } );   

	THEARMY1[t] = theobject;
	t++; 
  }
  
 for (c=1 ; c <= ARMYSIZE / 10; c++ )
 {
    shape = new THREE.BoxGeometry( objectsize, objectsize, objectsize );
  
  	theobject  = new THREE.Mesh( shape );
  	posx = ((objectsize * 5) - (c * objectsize));

  	theobject.position.x = posx;
  	theobject.position.z = objectsize * -10;   	
  	theobject.position.y = 0;
  	if (c > 10) theobject.position.z -= objectsize;
	
    theobject.material =  new THREE.MeshBasicMaterial ( { map: textureArray[r] } );   

	THEARMY1[t] = theobject;
	t++; 
  }
  
 for (c=1 ; c <= ARMYSIZE / 10; c++ )
 {
    shape = new THREE.BoxGeometry( objectsize, objectsize, objectsize );
  
  	theobject  = new THREE.Mesh( shape );
  	posx = ((objectsize * 5) - (c * objectsize));

  	theobject.position.x = posx;
  	theobject.position.z = objectsize * -11;   	
  	theobject.position.y = 0;
  	if (c > 10) theobject.position.z -= objectsize;
	
    theobject.material =  new THREE.MeshBasicMaterial ( { map: textureArray[r] } );   

	THEARMY1[t] = theobject;
	t++; 
  }
}

 
function initArmy2()
{
 var t = 0;
 var r = 1;
 
 for ( var c=1 ; c <= ARMYSIZE / 10 ; c++ )
 {
    var shape = new THREE.BoxGeometry( objectsize, objectsize, objectsize );
  
  	var theobject  = new THREE.Mesh( shape );
  	var posx = ((objectsize * 5) - (c * objectsize));

  	theobject.position.x = posx;
  	theobject.position.z = objectsize * 2;   	
  	theobject.position.y = 0;
  	if (c > 10) theobject.position.z -= objectsize;
	
    theobject.material =  new THREE.MeshBasicMaterial ( { map: textureArray[r] } );   

	THEARMY2[t] = theobject;
	t++; 
  }
  
 for (c=1 ; c <= ARMYSIZE / 10; c++ )
 {
    shape = new THREE.BoxGeometry( objectsize, objectsize, objectsize );
  
  	theobject  = new THREE.Mesh( shape );
  	posx = ((objectsize * 5) - (c * objectsize));

  	theobject.position.x = posx;
  	theobject.position.z = objectsize * 3;   	
  	theobject.position.y = 0;
  	if (c > 10) theobject.position.z -= objectsize;
	
    theobject.material =  new THREE.MeshBasicMaterial ( { map: textureArray[r] } );   


	THEARMY2[t] = theobject;
	t++; 
  }

 for (c=1 ; c <= ARMYSIZE / 10; c++ )
 {
    shape = new THREE.BoxGeometry( objectsize, objectsize, objectsize );
  
  	theobject  = new THREE.Mesh( shape );
  	posx = ((objectsize * 5) - (c * objectsize));

  	theobject.position.x = posx;
  	theobject.position.z = objectsize * 4;   	
  	theobject.position.y = 0;
  	if (c > 10) theobject.position.z -= objectsize;
	
    theobject.material =  new THREE.MeshBasicMaterial ( { map: textureArray[r] } );   

	THEARMY2[t] = theobject;
	t++; 
  }
  
 for (c=1 ; c <= ARMYSIZE / 10; c++ )
 {
    shape = new THREE.BoxGeometry( objectsize, objectsize, objectsize );
  
  	theobject  = new THREE.Mesh( shape );
  	posx = ((objectsize * 5) - (c * objectsize));

  	theobject.position.x = posx;
  	theobject.position.z = objectsize * 5;   	
  	theobject.position.y = 0;
  	if (c > 10) theobject.position.z -= objectsize;
	
    theobject.material =  new THREE.MeshBasicMaterial ( { map: textureArray[r] } );   

	THEARMY2[t] = theobject;
	t++; 
  }
  
 for (c=1 ; c <= ARMYSIZE / 10; c++ )
 {
    shape = new THREE.BoxGeometry( objectsize, objectsize, objectsize );
  
  	theobject  = new THREE.Mesh( shape );
  	posx = ((objectsize * 5) - (c * objectsize));

  	theobject.position.x = posx;
  	theobject.position.z = objectsize * 6;   	
  	theobject.position.y = 0;
  	if (c > 10) theobject.position.z -= objectsize;
	
    theobject.material =  new THREE.MeshBasicMaterial ( { map: textureArray[r] } );   

	THEARMY2[t] = theobject;
	t++; 
  }
 
 for (c=1 ; c <= ARMYSIZE / 10; c++ )
 {
    shape = new THREE.BoxGeometry( objectsize, objectsize, objectsize );
  
  	theobject  = new THREE.Mesh( shape );
  	posx = ((objectsize * 5) - (c * objectsize));

  	theobject.position.x = posx;
  	theobject.position.z = objectsize * 7;   	
  	theobject.position.y = 0;
  	if (c > 10) theobject.position.z -= objectsize;
	
    theobject.material =  new THREE.MeshBasicMaterial ( { map: textureArray[r] } );   

	THEARMY2[t] = theobject;
	t++; 
  }
  
 for (c=1 ; c <= ARMYSIZE / 10; c++ )
 {
    shape = new THREE.BoxGeometry( objectsize, objectsize, objectsize );
  
  	theobject  = new THREE.Mesh( shape );
  	posx = ((objectsize * 5) - (c * objectsize));

  	theobject.position.x = posx;
  	theobject.position.z = objectsize * 8;   	
  	theobject.position.y = 0;
  	if (c > 10) theobject.position.z -= objectsize;
	
    theobject.material =  new THREE.MeshBasicMaterial ( { map: textureArray[r] } );   

	THEARMY2[t] = theobject;
	t++; 
  }
  
 for (c=1 ; c <= ARMYSIZE / 10; c++ )
 {
    shape = new THREE.BoxGeometry( objectsize, objectsize, objectsize );
  
  	theobject  = new THREE.Mesh( shape );
  	posx = ((objectsize * 5) - (c * objectsize));

  	theobject.position.x = posx;
  	theobject.position.z = objectsize * 9;   	
  	theobject.position.y = 0;
  	if (c > 10) theobject.position.z -= objectsize;
	
    theobject.material =  new THREE.MeshBasicMaterial ( { map: textureArray[r] } );   

	THEARMY2[t] = theobject;
	t++; 
  }
  
 for (c=1 ; c <= ARMYSIZE / 10; c++ )
 {
    shape = new THREE.BoxGeometry( objectsize, objectsize, objectsize );
  
  	theobject  = new THREE.Mesh( shape );
  	posx = ((objectsize * 5) - (c * objectsize));

  	theobject.position.x = posx;
  	theobject.position.z = objectsize * 10;   	
  	theobject.position.y = 0;
  	if (c > 10) theobject.position.z -= objectsize;
	
    theobject.material =  new THREE.MeshBasicMaterial ( { map: textureArray[r] } );   

	THEARMY2[t] = theobject;
	t++; 
  }
  
 for (c=1 ; c <= ARMYSIZE / 10; c++ )
 {
    shape = new THREE.BoxGeometry( objectsize, objectsize, objectsize );
  
  	theobject  = new THREE.Mesh( shape );
  	posx = ((objectsize * 5) - (c * objectsize));

  	theobject.position.x = posx;
  	theobject.position.z = objectsize * 11;   	
  	theobject.position.y = 0;
  	if (c > 10) theobject.position.z -= objectsize;
	
    theobject.material =  new THREE.MeshBasicMaterial ( { map: textureArray[r] } );   

	THEARMY2[t] = theobject;
	t++; 
  }
}


// initiation of the world.
// The world is rendered, the loading screen is removed and it is ready to run.
// The skybox is loaded in.
// The buttons are linked with the "summon" and "attack" functions.

function initWorld()
{
    ABWorld.scene.background = new THREE.CubeTextureLoader().load ( SKYBOX_ARRAY,	function() 
	 { 
		ABWorld.render(); 
		AB.removeLoading();
		AB.runReady = true; 		
	 });
  	
  	AB.msg ( ` <hr> <p> Multi-user game. Pick a side. Click on the buttons to summon units for the sides. First one to reach 100 wins! <p>
  	        <button onclick='humans();'  class=ab-largenormbutton > Humans </button>  
            <button onclick='monsters();'  class=ab-largenormbutton > Monsters </button> <p>
            <p> You can attack the opposing side to reduce their numbers!
            <button onclick='attackM();' class=ab-largenormbutton > Monsters Attack! </button>
            <button onclick='attackH();' class=ab-largenormbutton > Humans Attack! </button> <p>` );
            
   // AB.msg (`<button onclick='attackH();' class=ab-largenormbutton > Humans Attack!</button>` );
}


// The world is loaded on startup
AB.world.newRun = function() 
{
	AB.loadingScreen();

	AB.runReady = false;  

	ABWorld.init3d ( startRadiusConst, maxRadiusConst, SKYCOLOR  ); 

	
	loadResources();
	
};


// There are no next step actions
AB.world.nextStep = function()
{

};

// the end conditions for the Game, if one side reaches 100 units they win.
AB.world.endRun = function()
{
    if(AB.abortRun && humanswin) AB.msg ("<br><font color=blue> <B> GAME OVER: HUMANS WIN! </B></font>", 2);
    else if(AB.abortRun && monsterswin) AB.msg ("<br><font color=red> <B> GAME OVER: MONSTERS WIN! </B></font>", 2);
};


// Websocket functions
// Credit to Starter User and the "Websocket Boxes" for the websocket framework.

AB.socketStart();


// functions for the buttons. Summoning humans/monsters and Attacking humans/monsters.
function humans()  {    summonHuman();      AB.socketOut (); }
function monsters() {   summonMonster();    AB.socketOut (); }
function attackH() {    attackHuman();      AB.socketOut (); }
function attackM() {    attackMonster();    AB.socketOut (); }

// Variable h is a counter for the amount of human units on the field.
var h = 0;

// For every click, one human object is added to the world scene and the counter goes up by one.
function summonHuman()
{

    ABWorld.scene.add(THEARMY1[h]);
    h ++;
    
    if (h > THEARMY1.length)
    {
        humanswin = true;
        AB.abortRun = true;
    }
}

// Variable m serves the same purpose for monsters as h does for humans.
var m = 0;

// summonMonster functions the same way as summonHuman. One monster object is summoned per click, m goes up by one.
function summonMonster()
{

    ABWorld.scene.add(THEARMY2[m]);
    m ++;
    
    if (m > THEARMY2.length)
    {
        monsterswin = true;
        AB.abortRun = true;
    }
}

// attackHuman is the function which removes a monster from the field. Once per click, a monster object is removed and m goes down by one.
function attackHuman()
{
    ABWorld.scene.remove(THEARMY2[m]);
    m --;
    
    if(m <= 0) m = 0;
}

// attackMonster removes a human object from the field and ticks h down by one.
function attackMonster()
{
    ABWorld.scene.remove(THEARMY1[h]);
    h --;
    
    if(h <= 0) h = 0;
}

// socketIn functions control the intake from the users.
// each function takes input in from users.
AB.socketIn = function()
{
    if ( ! AB.runReady ) return;
    summonHuman();
};

AB.socketIn = function()
{
    if (! AB.runReady ) return;
    summonMonster();
};

AB.socketIn = function()
{
    if (! AB.runReady ) return;
    attackHuman();
};

AB.socketIn = function()
{
    if (! AB.runReady ) return;
    attackMonster();
};