const NOBOXES =Math.trunc (((gridsize*gridsize)/100)*7);//around 7% of the level will be walls, seems to give favourable results const squaresize =100;// size of square in pixelsconst MAXPOS = gridsize * squaresize;// length of one side in pixels const SKYCOLOR =0xffffcc;// a number, not a string const BLANKCOLOR = SKYCOLOR ;// make objects this color until texture arrives (from asynchronous file read)const startRadiusConst = MAXPOS *0.8;// distance from centre to start the camera atconst skyboxConst = MAXPOS *100;// where to put skybox const maxRadiusConst = MAXPOS *100;// maximum distance from camera we will render things const show3d =true;// Switch between 3d and 2d view (both using Three.js) functionWorld(){var THEARMY =newArray( ARMYSIZE );var textureArray =newArray( FILE_ARRAY.length );function initSkybox(){// x,y,z positive and negative faces have to be in certain order in the array var materialArray =[(new THREE.MeshBasicMaterial({ map: THREE.ImageUtils.loadTexture("/uploads/kikisanni/pexels-posx.jpg"), side: THREE.BackSide})),(new THREE.MeshBasicMaterial({ map: THREE.ImageUtils.loadTexture("/uploads/kikisanni/pexels-negx.jpg"), side: THREE.BackSide})),(new THREE.MeshBasicMaterial({ map: THREE.ImageUtils.loadTexture("/uploads/kikisanni/pexels-posy.jpg"),side: THREE.BackSide})),(new THREE.MeshBasicMaterial({ map: THREE.ImageUtils.loadTexture("/uploads/kikisanni/pexels-negy.jpg"), side: THREE.BackSide})),(new THREE.MeshBasicMaterial({ map: THREE.ImageUtils.loadTexture("/uploads/kikisanni/pexels-posz.jpg"), side: THREE.BackSide})),(new THREE.MeshBasicMaterial({ map: THREE.ImageUtils.loadTexture("/uploads/kikisanni/pexels-negz.jpg"),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 );}function initThreeLights(){//this acts like a sunvar dirLight =new THREE.DirectionalLight(0xffffff,1);//white light
dirLight.position.set((gridsize*squaresize)*2,(gridsize*squaresize)*3,(gridsize*squaresize));//this will put our light in the bottom corner
dirLight.CameraLightHelper=true;
threeworld.scene.add(dirLight);//give us some light everywhere to make sure we have no 100% blackvar ambiLight =new THREE.AmbientLight(0x1a1a1a);
threeworld.scene.add(ambiLight);//THIS GIVES US BEAUTIFUL SHADOWS//SHADOWS ARE A BIT PIXELATED BUT THIS IS AS GOOD AS YOU'LL GET WITH JUST THE ONE LIGHT COVERING EVERYTHINGvar spotLight =new THREE.SpotLight(0xffffff,0,(gridsize*squaresize)*3,75,10);
spotLight.position.set((gridsize*squaresize),(gridsize*squaresize),(gridsize*squaresize));
spotLight.castShadow =true;var spotTarget =new THREE.Object3D();
threeworld.scene.add(spotLight);
spotTarget.position.set(0,0,0);
spotLight.target = spotTarget;
threeworld.scene.add(spotLight);}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();});}function asynchFinished()// all file loads returned {for(var i =0; i < FILE_ARRAY.length; i++)if(! textureArray[i])returnfalse;returntrue;}function initArmy()// called when all textures ready {var t =0;for(var c=1; c <= ARMYSIZE ; c++){// var shape = new THREE.SphereGeometry ( objectsize, 30, 30 ); var shape =new THREE.BoxGeometry( objectsize, objectsize, objectsize );var theobject =new THREE.Mesh( shape );
theobject.position.x = AB.randomIntAtoB (-MAXPOS, MAXPOS );
theobject.position.z = AB.randomIntAtoB (-MAXPOS, MAXPOS );
theobject.position.y =0;// var r = AB.randomIntAtoB ( 0, textureArray.length - 1 ); // random texture var r = AB.randomIntAtoB (0,4);// random one of the earths
theobject.material =new THREE.MeshBasicMaterial({ map: textureArray[r]});ABWorld.scene.add(theobject);
THEARMY[t]= theobject;// save it for later
t++;}}ABWorld.render();
AB.removeLoading();
AB.runReady =true;
let listElement = document.createElement("li");
listElement.innerHTML
AB.msg (`<hr><p>Multiplayer game.Click buttons to change boxes on all users' machines.Drag the camera.<p>\n \t
<button onclick='red();'class=ab-largenormbutton >Red</button>\n
<button onclick='yellow();'class=ab-largenormbutton >Yellow</button>\n
<button onclick='blue();'class=ab-largenormbutton >Blue</button>\n
<button onclick='green();'class=ab-largenormbutton >Green</button><p>\n
`);function moveArmy()// move all the objects {for(var i =0; i < THEARMY.length; i++){if( THEARMY[i])// in case initArmy() not called yet {
THEARMY[i].position.x = THEARMY[i].position.x + AB.randomIntAtoB(-WALKSTEP,WALKSTEP);
THEARMY[i].position.z = THEARMY[i].position.z + AB.randomIntAtoB(-WALKSTEP,WALKSTEP);
THEARMY[i].position.y = THEARMY[i].position.y + AB.randomIntAtoB(-WALKSTEP,WALKSTEP);ABWorld.scene.add( THEARMY[i]);}}this.newRun =function(){// if Three.js graphical representation:if(true){if( show3d ){
BOXHEIGHT = squaresize;
threeworld.init3d ( startRadiusConst, maxRadiusConst, SKYCOLOR );}else{
BOXHEIGHT =1;
threeworld.init2d ( startRadiusConst, maxRadiusConst, SKYCOLOR );}
initSkybox();// Set up blank objects first:
threeworld.renderer.shadowMap.enabled =true;
threeworld.renderer.shadowMapSoft =false;//soft shadows is nice in theory but their anti-aliasing is shite so don't bother//console.log(threeworld.renderer);
initThreeLights();// Then paint them with textures - asynchronous load of textures from files. // The texture file loads return at some unknown future time in some unknown order.// Because of the unknown order, it is probably best to make objects first and later paint them, rather than have the objects made when the file reads return.// It is safe to paint objects in random order, but might not be safe to create objects in random order.
loadTextures();// will return sometime later, but can go ahead and render now }};
AB.world.nextStep =function(){
moveArmy();};//--- Socket functionality -----------------------------------------------------// start socket
AB.socketStart();// functions called by buttons// baby and skull are textures 5 and 6 in the array:function red(){ changeBox(5); AB.socketOut (5);}function yellow(){ changeBox(6); AB.socketOut (6);}function blue(){ changeBox(7); AB.socketOut (7);}function green(){ changeBox(8); AB.socketOut (8);}function changeBox(n)// change a random box to texture n (5 or 6) {var i = AB.randomIntAtoB (0, THEARMY.length -1);// pick a random box to change
THEARMY[i].material =new THREE.MeshBasicMaterial({ map: textureArray[n]});}
AB.socketIn =function(n)// incoming data on socket, i.e. clicks of other player {
changeBox(n);};}}