// Cloned by Przemyslaw Majda on 29 Nov 2022 from World "Pig Shooter" by Przemyslaw Majda // Please leave this clone trail here.// Cloned by Przemyslaw Majda on 28 Nov 2022 from World "Password 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// You have to tell the users the password you will be using// Click button to change a random box's texture on all clients running this World// Pick a side and compete against an opponent!
AB.clockTick =40;// Speed of run: Step every n milliseconds. Default 100.
AB.maxSteps =1200;// run for ~48 seconds// Length of run: Maximum length of run in steps. Default 1000.
AB.screenshotStep =100;// ABHandler.GROUNDZERO = true; // Take screenshot on this step. (All resources should have finished loading.) Default 50.// wolf 3D model credit// https://free3d.com/3d-model/wolf-rigged-and-game-ready-42808.html// cannot get MTL to laod, getting "m.setTexturePath is not a function" error// so we are going with an all black lego modelconst OBJPATH ="/uploads/przemyslawmajda/";const OBJNAME ="Wolf_obj.obj";//const MTLNAME = "legoobj.mtl";const FILE_ARRAY =["/uploads/przemyslawmajda/pig.png",// array 0 to 4 are the earths"/uploads/przemyslawmajda/grassHD.jpg","/uploads/przemyslawmajda/fence_texture2.png"];const SKYCOLOR =0x7dd6ff;// very light blue // a number, not a string// 0xFFB6C1; // light pink // 0xccffcc; // light green const MAXPOS =29000;// start things within these bounds const ARMYSIZE =200;// an "army" of objects const skyboxConst = MAXPOS *2;const objectsize =700;const WALKSTEP =20;// bounds of the random move per timestep // try 50 (vibrating sheet) versus 1000 (cloud)const startRadiusConst = MAXPOS ;// distance from centre to start the camera atconst maxRadiusConst = MAXPOS *10;// maximum distance from camera we will render things ABHandler.MAXCAMERAPOS = MAXPOS *2;// allow camera go far away ABWorld.drawCameraControls =false;
AB.drawRunControls =false;var THEARMY =newArray( ARMYSIZE );var textureArray =newArray( FILE_ARRAY.length );var puss;var CONFIRMED_KILLS =[];var score =0;// player movement// this code was taken from "User-controlled Model World" by Starter User// https://ancientbrain.com/world.php?world=4606438712var pussRotation =0;const PUSS_STEP =350;const rotateConstant =Math.PI /20;const KEY_UP ="ArrowUp";const KEY_LEFT ="ArrowLeft";const KEY_RIGHT ="ArrowRight";const KEY_DOWN ="ArrowDown";var OURKEYS =[KEY_UP, KEY_LEFT, KEY_RIGHT, KEY_DOWN];function ourKeys(event){
console.log(event.key);return OURKEYS.includes(event.key);}function keyHandler(event){if(!AB.runReady)returntrue;// not ready yet// if not handling this key, send it to default:if(!ourKeys(event))returntrue;// else handle it and prevent default:if(event.key == KEY_UP){// move a bit along angle we are facing
puss.position.x =
puss.position.x + PUSS_STEP *Math.sin(pussRotation);
puss.position.z =
puss.position.z + PUSS_STEP *Math.cos(pussRotation);}if(event.key == KEY_DOWN){// move a bit along angle we are facing
puss.position.x =
puss.position.x - PUSS_STEP *Math.sin(pussRotation);
puss.position.z =
puss.position.z - PUSS_STEP *Math.cos(pussRotation);}if(event.key == KEY_LEFT){// rotate in place
pussRotation = pussRotation + rotateConstant;
puss.rotation.set(0, pussRotation,0);}if(event.key == KEY_RIGHT){
pussRotation = pussRotation - rotateConstant;
puss.rotation.set(0, pussRotation,0);}// lookat/follow depend on change in agent position/rotation:// setLookatFollow();
event.stopPropagation();
event.preventDefault();returnfalse;}// skyboxfunction loadSkybox(){var geometry =new THREE.BoxGeometry(maxRadiusConst, maxRadiusConst, maxRadiusConst);//image credit for skybox: http://www.humus.name/index.php?page=Textures&ID=138var cubeMaterials =[new THREE.MeshBasicMaterial({ map:new THREE.TextureLoader().load("/uploads/kellyt46/negz.jpg"), side: THREE.DoubleSide}),new THREE.MeshBasicMaterial({ map:new THREE.TextureLoader().load("/uploads/kellyt46/posz.jpg"), side: THREE.DoubleSide}),new THREE.MeshBasicMaterial({ map:new THREE.TextureLoader().load("/uploads/kellyt46/posy.jpg"), side: THREE.DoubleSide}),new THREE.MeshBasicMaterial({ map:new THREE.TextureLoader().load("/uploads/kellyt46/negy.jpg"), side: THREE.DoubleSide}),new THREE.MeshBasicMaterial({ map:new THREE.TextureLoader().load("/uploads/kellyt46/posx.jpg"), side: THREE.DoubleSide}),new THREE.MeshBasicMaterial({ map:new THREE.TextureLoader().load("/uploads/kellyt46/negx.jpg"), side: THREE.DoubleSide})];var cubeMaterial =new THREE.MeshFaceMaterial( cubeMaterials );var cube =new THREE.Mesh( geometry, cubeMaterial );ABWorld.scene.add(cube);}function loadPlayer(){var manager =new THREE.LoadingManager();var loader =new THREE.OBJLoader( manager );
loader.load(OBJPATH + OBJNAME, buildpuss);}function buildpuss( object ){
object.scale.multiplyScalar(4000);
console.log(object.children);
puss = object;
puss.position.x = AB.randomIntAtoB (-MAXPOS, MAXPOS );
puss.position.z = AB.randomIntAtoB (-MAXPOS, MAXPOS );
puss.position.y =-350;
threeworld.scene.add(puss);}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()){
loadSkybox();
setFloor();
initArmy();
loadPlayer();
buildFence();}});}function asynchFinished()// all file loads returned {for(var i =0; i < FILE_ARRAY.length; i++)if(! textureArray[i])returnfalse;returntrue;}function setFloor(){var floor =new THREE.BoxGeometry(60000,1,60000);var material =new THREE.MeshBasicMaterial({color:0x00ff00});var mesh =new THREE.Mesh(floor);
mesh.position.x =0;
mesh.position.y =-350;
mesh.position.z =0;
mesh.material =new THREE.MeshBasicMaterial({map: textureArray[1]});ABWorld.scene.add(mesh);}function buildFence(){// z axis fencefor(let i =0; i <30; i++){
let fence =new THREE.BoxGeometry(2000,2000,1);
let fence_mesh =new THREE.Mesh(fence);
fence_mesh.position.x =(-29000+(2000* i));
fence_mesh.position.y =650;
fence_mesh.position.z =30000;
fence_mesh.material =new THREE.MeshBasicMaterial({map: textureArray[2]});ABWorld.scene.add(fence_mesh);}for(let i =0; i <30; i++){
let fence =new THREE.BoxGeometry(2000,2000,1);
let fence_mesh =new THREE.Mesh(fence);
fence_mesh.position.x =(-29000+(2000* i));
fence_mesh.position.y =650;
fence_mesh.position.z =-30000;
fence_mesh.material =new THREE.MeshBasicMaterial({map: textureArray[2]});ABWorld.scene.add(fence_mesh);}for(let i =0; i <30; i++){
let fence =new THREE.BoxGeometry(1,2000,2000);
let fence_mesh =new THREE.Mesh(fence);
fence_mesh.position.x =30000;
fence_mesh.position.y =650;
fence_mesh.position.z =(-29000+(2000* i));
fence_mesh.material =new THREE.MeshBasicMaterial({map: textureArray[2]});ABWorld.scene.add(fence_mesh);}for(var i =0; i <30; i++){var fence =new THREE.BoxGeometry(1,2000,2000);var fence_mesh =new THREE.Mesh(fence);
fence_mesh.position.x =-30000;
fence_mesh.position.y =650;
fence_mesh.position.z =(-29000+(2000* i));
fence_mesh.material =new THREE.MeshBasicMaterial({map: textureArray[2]});ABWorld.scene.add(fence_mesh);}}// pig sound source https://www.youtube.com/watch?v=Bg2BlPy1I30var oink =newAudio("/uploads/przemyslawmajda/pig.mp3");// based on Password Websocket boxes by Starter User// https://ancientbrain.com/world.php?world=9623346805function 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;// pig image credit http://clipart-library.com/clipart/344716.htmvar r = AB.randomIntAtoB (0,4);// random one of the earths
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.runReady =true;
AB.msg (`<hr><p>Multi-user game.Kill as many pigs as you can before they escape!Playerwith the most pig kills in 40 seconds wins.<p id="score">Score:0<p><p id="highest_score">HighestScore(All players):0</p><p id="final_score"></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].position.x = THEARMY[i].position.x + AB.randomIntAtoB(-WALKSTEP *10,WALKSTEP*10);
THEARMY[i].position.z = THEARMY[i].position.z + AB.randomIntAtoB(-WALKSTEP*10,WALKSTEP*10);// dont allow pigs outside the zoneABWorld.scene.add( THEARMY[i]);}}}function checkArmy(){for(var i =0; i < THEARMY.length; i++){if(THEARMY[i]){if( THEARMY[i].position.x >29000|| THEARMY[i].position.x <-29000|| THEARMY[i].position.z >29000|| THEARMY[i].position.z <-29000){
console.log(THEARMY[i].position.x);
console.log(THEARMY[i].position.z);// experimental: ABWorld.scene.remove(THEARMY[i]);delete THEARMY[i];
console.log("BOUNDARY CROSSED: ELIMINATE PIG");}}}}function killPig(){var pussx = puss.position.x;var pussz = puss.position.z;for(var i =0; i < THEARMY.length; i++){if(THEARMY[i]){
let pigx = THEARMY[i].position.x;
let pigz = THEARMY[i].position.z;if(pigx <=(pussx +900)&& pigx >=(pussx -900)){if(pigz <=(pussz +900)&& pigz >=(pussz -900)){
console.log(THEARMY[i].position.x);
console.log(THEARMY[i].position.z);
score = score +1;
updateScore(score);ABWorld.scene.remove(THEARMY[i]);delete THEARMY[i];
CONFIRMED_KILLS.push(i);
console.log("PIG LOCATED AND ELIMINATED");
oink.play();}}}}}// makign sure our hero cannot escape the RANCHfunction checkPussPosition(){if(puss.position.x >29000){
puss.position.x =29000;}elseif(puss.position.x <-29000){
puss.position.x =-29000;}elseif(puss.position.z >29000){
puss.position.z =29000;}elseif(puss.position.z <-29000){
puss.position.z =-29000;}}function updateScore(n){
pContent = document.getElementById("score");
pContent.innerHTML ="Score: "+ n;}function finalScore(){if(AB.step >=1200){
pContent = document.getElementById("final_score");if(high <= score){
pContent.innerHTML ="You won! Your score was "+ score;}else{
pContent.innerHTML ="You were NOT the winner :( The highest score was "+ high +". Better luck next time!";}}}
AB.world.newRun =function(){
AB.newSplash();
AB.splashHtml (`<h1>Password only Websocket boxes </h1>
A version of Websocket boxes that only certain users can join.<br>You enter a password.You only join with users who enter the same password (not with all users of the World).<br>The first user to run the World can enter any password!But other users must know what password they will use.<p>Enter password:<input style='width:25vw;' maxlength='2000' NAME="p" id="p" VALUE=''><button onclick='start();'class=ab-normbutton >Start</button><p><div id=errordiv name=errordiv></div>`);
AB.runReady =false;ABWorld.init3d ( startRadiusConst, maxRadiusConst, SKYCOLOR );// var ambient = new THREE.AmbientLight();// ABWorld.scene.add(ambient);var stageLight =new THREE.DirectionalLight(0xa2a2a2,1.5);
stageLight.position.set(startRadiusConst, startRadiusConst, startRadiusConst);ABWorld.scene.add(stageLight);
loadResources();// aynch file loads
document.onkeydown = keyHandler;// calls initArmy() when it returns};
AB.world.nextStep =function(){
moveArmy();
checkArmy();
killPig();
checkPussPosition();
sendScore();
highestScore();
finalScore();};//--- start Socket -----------------------------------------------------function start()// user has entered a password {var password = jQuery("input#p").val();
password = password.trim();if(! alphanumeric ( password )){
$("#errordiv").html("<font color=red> <B> Error: Password must be alphanumeric. </b></font> ");return;}// else we have a password, start the socket run with this password
AB.socketStart ( password );
AB.removeSplash();}function alphanumeric ( str )// return if string is just alphanumeric {var rc = str.match(/^[0-9a-zA-Z]+$/);// start of line "[0-9a-zA-Z]+" end of line if( rc )returntrue;elsereturnfalse;}//--- Socket functionality -----------------------------------------------------// functions called by buttons// baby and skull are textures 5 and 6 in the array:var high =0;function highestScore(){
pContent = document.getElementById("highest_score");if(high > score){
pContent.innerHTML ="Highest Score (All players): "+ high;}else{
pContent.innerHTML ="Highest Score (All players): "+ score +" (you)";}}function sendScore(){
AB.socketOut(score);}
AB.socketIn =function(n)// incoming data on socket, i.e. clicks of other player {if(! AB.runReady )return;
high = n;};