// Cloned by Yiming Fu on 2 Dec 2022 from World "Websockets boxes" by Starter user // Please leave this clone trail here.// ==== Starter World =================================================================================================// This code is designed for use on the Ancient Brain site.// This code may be freely copied and edited by anyone on the Ancient Brain site.// To include a working run of this program on another site, see the "Embed code" links provided on Ancient Brain.// ====================================================================================================================// Demo of Websockets functionality added to a 3D World// Run with two or more users// Click button to change a random box's texture on all clients running this World// Pick a side and compete against an opponent! // You can annoy the other player by reloading the page!
AB.clockTick =200;// Speed of run: Step every n milliseconds. Default 100.
AB.maxSteps =100000;// 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.const mixers =[];const clock =new THREE.Clock();const FILE_ARRAY =["/uploads/fuy3/solar4.jpeg",// the white solar"/uploads/fuy3/solar1.jpeg",// array 5"/uploads/fuy3/solar8.png",// array 6 ];
SKYBOX_ARRAY=["/uploads/fuy3/img3.png","/uploads/fuy3/img4.png","/uploads/fuy3/img5.png","/uploads/fuy3/img1.png","/uploads/fuy3/img.png","/uploads/fuy3/img2.png"];const ARMYSIZE =35;// an "army" of objectsconst objectsize =450;const WALKSTEP =0;// bounds of the random move per timestep // try 50 (vibrating sheet) versus 1000 (cloud)const MAXPOS =300;// start things within these bounds const startRadiusConst = MAXPOS *5;// distance from centre to start the camera atconst maxRadiusConst = MAXPOS *50;// maximum distance from camera we will render things ABHandler.MAXCAMERAPOS = MAXPOS *30;// allow camera go far away ABWorld.drawCameraControls =false;
AB.drawRunControls =false;var THEARMY =newArray( ARMYSIZE );var textureArray =newArray( FILE_ARRAY.length );function loadModels(){const loader =new THREE.GLTFLoader();const onLoad =( gltf, position )=>{const model = gltf.scene.children[0];
model.position.copy( position );
model.rotation.z =100;ABWorld.scene.add( model );};const rockPosition =new THREE.Vector3(0,-300,0);// can load 3D models of other user:
loader.load ('/uploads/fuy3/rock.glb', gltf => onLoad ( gltf, rockPosition ));}function initLights(){const ambientLight =new THREE.AmbientLight(0xffffff,1);ABWorld.scene.add( ambientLight );const frontLight =new THREE.DirectionalLight(0xffffff,1);
frontLight.position.set(10,10,10);const backLight =new THREE.DirectionalLight(0xffffff,1);
backLight.position.set(-10,10,-10);ABWorld.scene.add( frontLight, backLight );}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()) initArmy();});}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,10,10);var theobject =new THREE.Mesh( shape );
theobject.position.x = AB.randomIntAtoB (-9000,9000);
theobject.position.z = AB.randomIntAtoB (-9000,9000);
theobject.position.y = AB.randomIntAtoB (-9000,9000);
theobject.material =new THREE.MeshBasicMaterial({ map: textureArray[0]});ABWorld.scene.add(theobject);
THEARMY[t]= theobject;// save it for later
t++;}// can start the run loopABWorld.render();
AB.removeLoading();
AB.runReady =true;
AB.msg (`<hr><p>This is a multi-user game.<br><br>Try dragging the camera to en-<br>joy the cosmic landscape.<br><br>Would you rather the planet be <br> pink or blue?<br><br>Click here to pick your side.<p><button onclick='pink();'class=ab-largenormbutton >Pink</button><button onclick='blue();'class=ab-largenormbutton >Blue</button><p>`);}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].rotation.x += AB.randomIntAtoB(0,1);
THEARMY[i].rotation.y += AB.randomIntAtoB(0,1);ABWorld.scene.add( THEARMY[i]);}}}
AB.world.newRun =function(){
AB.loadingScreen();
AB.runReady =false;ABWorld.init3d ( startRadiusConst, maxRadiusConst);ABWorld.scene.background=(new THREE.CubeTextureLoader).load(SKYBOX_ARRAY)
loadResources();// aynch file loads // calls initArmy() when it returns
initLights();
loadModels();};
AB.world.nextStep =function(){
moveArmy();const delta = clock.getDelta();
mixers.forEach(( mixer )=>{ mixer.update( delta );});};const MUSICFILE ='/uploads/fuy3/space.mp3';
AB.backgroundMusic ( MUSICFILE );//--- Socket functionality -----------------------------------------------------// start socket
AB.socketStart();// functions called by buttons// baby and skull are textures 5 and 6 in the array:function pink(){ changeBox(1); AB.socketOut (1);}function blue(){ changeBox(2); AB.socketOut (2);}function changeBox(n)// change a random box to texture n (1 or 2) {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 {if(! AB.runReady )return;
changeBox(n);};