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 pixels
const 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 at
const 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)
function World(){
var THEARMY = new Array( ARMYSIZE );
var textureArray = new Array ( 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 sun
var 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% black
var 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 EVERYTHING
var 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] )
return false;
return true;
}
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);
};
}
}