// Cloned by Jack on 17 Nov 2022 from World "Websockets Project" by Gareth Hogan // Please leave this clone trail here.// Cloned by Gareth Hogan on 12 Nov 2022 from World "Websockets boxes" by Starter user // Please leave this clone trail here.//--------------------------------------------------------------------------------------------------------------// CONSTS AND VARS//--------------------------------------------------------------------------------------------------------------
AB.clockTick =100;// Speed of run: Step every n milliseconds. Default 100.
AB.maxSteps =300;// Length of run: Maximum length of run in steps. Default 1000.
AB.screenshotStep =100;// Take screenshot on this step. (All resources should have finished loading.) Default 50.// Source: https://minecraft.fandom.com/wiki/List_of_block_textures// '/uploads/gareth22/example.jpg'const FILE_ARRAY =["/uploads/gareth22/dirt.jpg","/uploads/gareth22/diamond.jpg","/uploads/gareth22/redstone.jpg","/uploads/gareth22/redglass.jpg","/uploads/gareth22/blueglass.jpg","/uploads/gareth22/blorb.jpg","/uploads/gareth22/rorb.jpg"];//skybox array// http://stemkoski.github.io/Three.js/#skybox// https://jaxry.github.io/panorama-to-cubemap/const SKYBOX_ARRAY =["/uploads/gareth22/px-min.png","/uploads/gareth22/nx-min.png","/uploads/gareth22/py-min.png","/uploads/gareth22/ny-min.png","/uploads/gareth22/pz-min.png","/uploads/gareth22/nz-min.png"];const SKYCOLOR =0x000000;// colour of the skyconst gridsize =10;// number of squares along side of world const objectsize =100;// size of the objectsconstNumBoxes= gridsize*gridsize;// calculate the number of boxes that will be in the gridconst MAXPOS = gridsize * objectsize;// start things within these bounds const startRadiusConst = MAXPOS;// distance from centre to start the camera atconst maxRadiusConst = MAXPOS *5;// maximum distance from camera we will render things// constants used in the grid, each square has one number to show state, you can see what each number means hereconst GRID_BLANK =0;const GRID_USER1 =1;const GRID_USER2 =4;const GRID_COLOUR1 =2;const GRID_COLOUR2 =3;// each action has an associated numberconst ACTION_LEFT =0;const ACTION_RIGHT =1;const ACTION_UP =2;const ACTION_DOWN =3;// setup cameraABHandler.MAXCAMERAPOS = MAXPOS;ABWorld.drawCameraControls =false;
AB.drawRunControls =false;ABHandler.GROUNDZERO =true;// Variables to be usedvar step;// timervar textureArray =newArray(FILE_ARRAY.length);var GRID =newArray(gridsize);var ai, aj;//player 1var bi, bj;//player 2 var player1, player2;// the orb objects//--------------------------------------------------------------------------------------------------------------// PRELOAD RESOURCES//--------------------------------------------------------------------------------------------------------------function loadResources()// asynchronous file loads - call initScene() when all finished {for(var i =0; i < FILE_ARRAY.length; i++)
startFileLoad (i);// launch n asynchronous file loads}function startFileLoad(n)// asynchronous file load of texture n {var loader =new THREE.TextureLoader();
loader.load(FILE_ARRAY[n],function(thetexture){
thetexture.minFilter = THREE.LinearFilter;
textureArray[n]= thetexture;if(asynchFinished())
initScene();// initialize the scene when finished loading});}function asynchFinished()// all file loads returned {for(var i =0; i < FILE_ARRAY.length; i++){if(!textureArray[i])returnfalse;}returntrue;}function splashHTML()// HTML string to be shown in the splash{
string ="Colour the floor, QUICKLY! <br><font color=red><b>Red is the arrow keys</b></font> <br><font color=blue><b>Blue is WASD</b></font><br> Colour the most squares before time is up to win!";return(string);}
AB.newSplash(splashHTML());// show the splash
AB.splashClick(function()// when the start is pressed {
AB.removeSplash();// remove splash screen // ready to start run loop?
splashClicked =true;
step =0;ABWorld.render();
AB.runReady =true;
AB.socketOut("Start");// send out start command to all worlds so they remove the splashif(asynchFinished())
AB.runReady =true;// start run loop });//--------------------------------------------------------------------------------------------------------------// SETUP GRID//--------------------------------------------------------------------------------------------------------------function initScene()// called when all textures ready {var i, j, shape, theobject, borb, rorb;// various variables used in the gridfor(i =0; i < gridsize ; i++)// setting up the lists inside the grid list
GRID[i]=newArray(gridsize);// MAKING CUBESfor(i =0; i < gridsize ; i++){for(j =0; j < gridsize ; j++){
GRID[i][j]= GRID_BLANK;// default cube is blank
shape =new THREE.BoxGeometry(objectsize, objectsize, objectsize);
theobject =new THREE.Mesh(shape);
theobject.material =new THREE.MeshBasicMaterial({map: textureArray[0]});// textureArray[0] is for blank
theobject.position.copy(translate(i,j));// translate my (i,j) grid coordinates to three.js (x,y,z) coordinates ABWorld.scene.add(theobject);}}// PLAYER ORBS
borb =new THREE.SphereGeometry(50,32,16);// blue orb
rorb =new THREE.SphereGeometry(50,32,16);// red orb
player1 =new THREE.Mesh(borb);
player2 =new THREE.Mesh(rorb);
player1.material =new THREE.MeshBasicMaterial({map: textureArray[5]});
player2.material =new THREE.MeshBasicMaterial({map: textureArray[6]});
position1 = translateOrb(0,0)// placing it top left
player1.position.copy(position1)
position2 = translateOrb(9,9)// placing it bottom right
player2.position.copy(position2)ABWorld.scene.add(player1);ABWorld.scene.add(player2);//positions of the players
ai =0;
aj =0;
bi =9;
bj =9;
GRID[ai][aj]= GRID_USER1;
GRID[bi][bj]= GRID_USER2;ABWorld.scene.background =new THREE.CubeTextureLoader().load(SKYBOX_ARRAY,function(){ABWorld.render();});
AB.removeLoading();// remove loading screen}function translate(i, j)// translte x y coord into a 3D vector {var v =new THREE.Vector3();
v.y =0;
v.x =(i * objectsize)-(MAXPOS/2);
v.z =(j * objectsize)-(MAXPOS/2);return v;}function translateOrb(i, j)// translate for the ORB as they need to be one layer above the rest{var v =new THREE.Vector3();
v.y =100;
v.x =(i * objectsize)-(MAXPOS/2);
v.z =(j * objectsize)-(MAXPOS/2);return v;}function occupied(i, j)// is this square occupied{return(GRID[i][j]== GRID_USER1 || GRID[i][j]== GRID_USER2);}//--------------------------------------------------------------------------------------------------------------// MOVEMENT//--------------------------------------------------------------------------------------------------------------// arrow keys : LEFT, UP, RIGHT, DOWN, A, W, D, Svar OURKEYS =[37,38,39,40,65,87,68,83];function ourKeys(event){// checks if a key pressed is either WASD or arrow keysreturn(OURKEYS.includes(event.keyCode));}function keyHandler(event)// what to do when a key is pressed{if(!AB.runReady)returntrue;if(!ourKeys(event))returntrue;// cases for each different key// socketsender first sends to other worlds what to do, then does it locally using moveUserif(event.keyCode ==65) socketSender(ACTION_LEFT,1);if(event.keyCode ==87) socketSender(ACTION_DOWN,1);if(event.keyCode ==68) socketSender(ACTION_RIGHT,1);if(event.keyCode ==83) socketSender(ACTION_UP,1);if(event.keyCode ==37) socketSender(ACTION_LEFT,2);if(event.keyCode ==38) socketSender(ACTION_DOWN,2);if(event.keyCode ==39) socketSender(ACTION_RIGHT,2);if(event.keyCode ==40) socketSender(ACTION_UP,2);
event.stopPropagation(); event.preventDefault();returnfalse;}function moveUser(action, player)// moving the player, takes in the action to do, and which player to do it to {if(player ==1){// ai aj is where the player was, i j will be where they move tovar i = ai;var j = aj;}elseif(player ==2){var j = bj;var i = bi;}if(action == ACTION_LEFT ){if(i >0) i--;elsereturn;}elseif(action == ACTION_RIGHT ){if(i <9) i++;elsereturn;}elseif(action == ACTION_UP ){if(j <9) j++;elsereturn;}elseif(action == ACTION_DOWN){if(j >0) j--;elsereturn;}if(!occupied(i,j))// else just miss a turn cause you can't move into that space{if(player ==1){//diamond
GRID[ai][aj]= GRID_COLOUR1;// change colour of square you are moving off of
shape =new THREE.BoxGeometry(objectsize, objectsize, objectsize);
theobject =new THREE.Mesh(shape);
theobject.material =new THREE.MeshBasicMaterial({map: textureArray[1]});
theobject.position.copy(translate(ai,aj));// translate my (i,j) grid coordinates to three.js (x,y,z) coordinates ABWorld.scene.add(theobject);
position = translateOrb(i,j)// move their orb
player1.position.copy(position)
GRID[i][j]= GRID_USER1;// new square the player is standing on
shape =new THREE.BoxGeometry(objectsize, objectsize, objectsize);
theobject =new THREE.Mesh(shape);
theobject.material =new THREE.MeshBasicMaterial({map: textureArray[4]});// where user is
theobject.position.copy(translate(i,j));// translate my (i,j) grid coordinates to three.js (x,y,z) coordinates ABWorld.scene.add(theobject);}elseif(player ==2){//redstone
GRID[bi][bj]= GRID_COLOUR2;
shape =new THREE.BoxGeometry(objectsize, objectsize, objectsize);
theobject =new THREE.Mesh(shape);
theobject.material =new THREE.MeshBasicMaterial({map: textureArray[2]});
theobject.position.copy(translate(bi,bj));// translate my (i,j) grid coordinates to three.js (x,y,z) coordinates ABWorld.scene.add(theobject);
position = translateOrb(i,j)
player2.position.copy(position)
GRID[i][j]= GRID_USER2;
shape =new THREE.BoxGeometry(objectsize, objectsize, objectsize);
theobject =new THREE.Mesh(shape);
theobject.material =new THREE.MeshBasicMaterial({map: textureArray[3]});// where user is
theobject.position.copy(translate(i,j));// translate my (i,j) grid coordinates to three.js (x,y,z) coordinates ABWorld.scene.add(theobject);}if(player ==1){// now they are moved, update the coords where they are
ai = i;
aj = j;}elseif(player ==2){
bi = i;
bj = j;}}}//--------------------------------------------------------------------------------------------------------------// AB WORLD FUNCTIONS//--------------------------------------------------------------------------------------------------------------
AB.world.newRun =function(){
AB.loadingScreen();
AB.runReady =false;ABWorld.init3d(startRadiusConst, maxRadiusConst, SKYCOLOR );
loadResources();// aynch file loads, calls initScene() when it returns
document.onkeydown = keyHandler;
step =0;};function updatestatus(){// this shows the timervar status ="<font size=5 face=verdana> Time: <br>"+ step +"</font>";
$("#user_span3").html(status);};
AB.world.nextStep =function(){
step++;// each step the timer goes up and is shown
updatestatus();};function countScore(){// function to calculate score at the end of the game
scoreP1 =1;
scoreP2 =1;for(i =0; i < gridsize ; i++){for(j =0; j < gridsize ; j++){if(GRID[i][j]==2){
scoreP1 +=1;}elseif(GRID[i][j]==3){
scoreP2 +=1;}}}
console.log(scoreP1)
console.log(scoreP2)if(scoreP1 > scoreP2){
winner ="<br> <font color=blue> <B> The winner is ... PLAYER 1 </B> </font>"}elseif(scoreP2 > scoreP1){
winner ="<br> <font color=red> <B> The winner is ... PLAYER 2 </B> </font>"}else{
winner ="<br> <font color=green> <B> The game was a Draw</B> </font>"}return(winner);}
AB.world.endRun =function()// at the end of the run{if(step ==300){
$("#user_span4").html("<font size=5 face=verdana> <B>TIME UP</B> </font>");}
winner = countScore();
AB.msg(winner,7)// shows the winner};//--------------------------------------------------------------------------------------------------------------// SOCKETS//--------------------------------------------------------------------------------------------------------------
AB.socketStart();// start sockets
AB.socketIn =function(data)// incoming data on socket, i.e. clicks of other player {if(typeof data ==="string")// a string signals to take down the splash for all screens{
AB.removeSplash();
splashClicked =true;
step =0;ABWorld.render();
AB.runReady =true;}else// it will be a list containing the player and move to do{
action = data[0]
player = data[1]
moveUser(action, player);}};function socketSender(action, player)// function to send out the move to do, then do the move locally{
data =[action, player];
AB.socketOut(data);
moveUser(action, player);};