Code viewer for World: Ch.4. Two grids.
 
// Over a few chapters, we are working up to a "Battleship" style Websocket game.

// Ch.4
// Make two grids 
// - my grid with randomised ships 
// - map of opponent's grid (initially unknown)



// === start of code ===========================================================================================================

// --- const (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 startRadiusConst	 	= MAXPOS * 2 ;		    // distance from centre to start the camera at - actually we will override this below 
const maxRadiusConst 		= MAXPOS * 10 ;			// maximum distance from camera we will render things  
	
const SKYCOLOR 		= 'lightyellow';			      


 const TEXTURE_WALL 	= '/uploads/chapters/stone.png' ;
 const TEXTURE_SHIP 	= '/uploads/chapters/ship.png' ;
 
// credit:
// https://commons.wikimedia.org/wiki/File:Square_stone_brick_Texture.jpg
// https://commons.wikimedia.org/wiki/File:Regina_Maris.JPG



// --- Some cosmetic improvements  --------------------------------------
// This section is not really important.
// Ancient Brain has a concept of a "run" that executes until n steps have passed. Also controls to pause that run.
// This is not that type of World. We can get rid of those controls.

AB.maxSteps                 = 1000000;         
AB.drawRunControls          = false;
ABWorld.drawCameraControls  = false;        // remove some controls to change the camera mode 
	
		 

// --- var (variables) --------------------------------------

var wall_texture, ship_texture; 



	ABWorld.init3d ( startRadiusConst, maxRadiusConst, SKYCOLOR  ); 

	loadTextures();		 	 
							
    AB.msg ( "Drag and scroll the mouse to move and zoom the camera.");				
    
    
	
function loadTextures()		  
{
	var loader1 = new THREE.TextureLoader();
	var loader2 = new THREE.TextureLoader();
		
	loader1.load ( TEXTURE_SHIP, function ( texture )  	 
	{
		ship_texture = texture;                  
		if ( wall_texture )	makeEverything();		// if both textures have loaded we can make everything 
	});	

	loader2.load ( TEXTURE_WALL, function ( texture )  		
	{
		wall_texture = texture;                  
		if ( ship_texture )	makeEverything();		  
	});	
}




//--- two 2D grids  -------------------------------------------------------------------------------

function translateMy ( i, j )			 
// the absolute 3D position of an (i,j) square on my grid is:           
//  width x = (i * squaresize)      
// height y = 0                                
//  depth z = (j * squaresize) 
{
	var v = new THREE.Vector3();
	
	v.x = (i * squaresize) ;   		 
	v.y = 0 ;	
	v.z = (j * squaresize) ;   	
	
	return v;
}


function translateOpponent ( i, j )		
// put 2nd grid beside the 1st grid, offset on the x dimension 
{
	var v = new THREE.Vector3();

	v.x = (i * squaresize) + MAXPOS ;   		 
	v.y = 0 ;	
	v.z = (j * squaresize) ;   	

	return v;
}


	
function makeEverything()		 
{
    makeGrids();
    makeShips();
}


function makeGrids()
{
	var i,j, shape, thecube, position, lookat;
	shape    = new THREE.BoxGeometry ( squaresize, squaresize, squaresize );			 
	 
	// make the two grids together:
	 for ( i = 0; i < gridsize ; i++ )           
	  for ( j = 0; j < gridsize ; j++ ) 
		if ( ( i==0 ) || ( i==gridsize-1 ) || ( j==0 ) || ( j==gridsize-1 ) )       // if at one of the edges  
		{
			thecube = new THREE.Mesh( shape );
			thecube.material = new THREE.MeshBasicMaterial( { map: wall_texture } );
			position = translateMy(i,j);                
			thecube.position.copy ( position ); 		
			ABWorld.scene.add(thecube);
			
			thecube = new THREE.Mesh( shape );
			thecube.material = new THREE.MeshBasicMaterial( { map: wall_texture } );
			position = translateOpponent(i,j);                
			thecube.position.copy ( position ); 		
			ABWorld.scene.add(thecube);
		}

// with two grids, need to figure where to put camera, and what to point it at 
// point it at approximately middle of the two grids:

    lookat = translateMy ( gridsize,  gridsize/2  );

// experiment to find some camera position off to the bottom:
//  position = new THREE.Vector3 (x, y, z);
    
    position = new THREE.Vector3 ( MAXPOS,   MAXPOS * 1.2,   MAXPOS * 1.3 );

   ABWorld.cameraCustom ( position, lookat );       // set up customised camera at this position to look at this point 
}


 
function makeShips()    
// make randomised ships 
// only make them in my grid - opponent's grid starts off unknown 
{
	 var  p, i, j, shape, thecube, position;
	 shape = new THREE.BoxGeometry ( squaresize, squaresize, squaresize );	
	 
	 // make a few random blocks using a "for" loop that goes round 5 times 
	 // would be nice to be able to say "do 5 times" but no easy way of saying that!
	 
	 for ( p = 1; p <=5 ; p++ )    
	 {
    	 thecube = new THREE.Mesh( shape );
     	 thecube.material =  new THREE.MeshBasicMaterial( { map: ship_texture } );
     	 i = AB.randomIntAtoB ( 1, gridsize-2 );    // positions 0 and (gridsize-1) are walls 
     	 j = AB.randomIntAtoB ( 1, gridsize-2 ); 
     	 position = translateMy ( i, j );        
     	 thecube.position.copy ( position ); 
    	 ABWorld.scene.add(thecube);
	 }
}
 
 
// === end of code ===========================================================================================================




 
// Exercises:
// Offset the 2nd grid to a new position.
// Move the camera to a new position.
// Change the point the camera looks at.
// Make a huge number of ships. Fill the grid.
// Make ships whose positions go "out of bounds" to see the value of bounds checking.
// Advanced exercise: Move the 2nd grid to be perpendicular to the 1st grid.
// Advanced exercise: Stop it putting 2 ships on the same square. 
// Advanced exercise: Make ships that cover 2 or 3 squares in a row. 

 
// Outcomes: Student can:
// Learn more about addressing a space with code, and how to offset objects to new positions.
// Learn how to address specific points in 3D space by creating 3D vectors in code. 
// Learn more about "for" loops.
// Learn how to use random number generation functions.
// If they do the advanced exercises: Create a variable number of objects, and learn how to keep track of what you have created.