// Cloned by Effa Al Bulushi on 27 Nov 2022 from World "Infinite World Ground + Sun" by Enhanced // Please leave this clone trail here.//==============================================================================// Welcome to the Infinite world with only grounds !//==============================================================================// This program was made by Nathan Bonnard.// In this world, you can generate an infinite world ! // But this isn't really infinite, it would be impossible, // the world do a simple loop when the player reach the border. Like in real life !// This is a little version of the real infinite world that you can find aswell on the enhanced page//------------------------------ TWEAKER BOX ------------------------------//const squaresize =7;// The world is like a infinite grid of square. squaresize is the size of a squarevar MOVESPEED =7;// Speed of the playervar viewDistance =2;// determinate the maximum distance to see ground (viewDistance * squaresize * groundMultiplier)var groundMultiplier =551;// The world is divided by zone (grounds) that size groundMultiplier*squaresizevar worldSize =13;// dimension of the world, it is not really infinite but big and can loop. There is worldSize * worldSize Grounds const SKYDISTANCE =3000;// Distance of stars and sunconst NBSTARS =500;//number of stars//Where all textures and objects areconst PATHTEXTURES ="/uploads/issafae2/"//------------------------------ END OF TWEAKER BOX ------------------------------//var newviewDistance = viewDistance;// letiables to re-generate the world with new letiables var newGroundMultiplier = groundMultiplier;var newworldSize = worldSize;const MAXPOS =4000;const startRadiusConst = MAXPOS *0.5;// distance from centre to start the camera atconst maxRadiusConst = MAXPOS *5;// maximum distance from camera we will render things const SKYCOLOR =0x6495ED;const LIGHTCOLOR =0xffffff;//used to manage the click and give back control to the user when you click on a button/text box //and don't want to enter into first person modevar HUDEVENT =false;var mouse;// vector2 : position of the mouse on the screen
threehandler.MAXCAMERAPOS = MAXPOS *10;// allow camera go far away
threeworld.drawCameraControls =false;
AB.clockTick =20;// Speed of run: Step every n milliseconds. Default 100.
AB.maxSteps =1000000;// Length of run: Maximum length of run in steps. Default 1000.
AB.screenshotStep =50;// Take screenshot on this step. (All resources should have finished loading.) Default 50./**
* A linear interpolator for hexadecimal colors
* @param {Int} a
* @param {Int} b
* @param {Number} amount
* @example
* // returns 0x7F7F7F
* lerpColor(0x000000, 0xffffff, 0.5)
* @returns {Int}
*/function lerpColor(a, b, amount){
let ah = a;
ar = ah >>16, ag = ah >>8&0xff, ab = ah &0xff,
bh = b;
br = bh >>16, bg = bh >>8&0xff, bb = bh &0xff,
rr = ar + amount *(br - ar),
rg = ag + amount *(bg - ag),
rb = ab + amount *(bb - ab);return((1<<24)+(rr <<16)+(rg <<8)+ rb |0);}/**/function map(n, start1, stop1, start2, stop2){return((n-start1)/(stop1-start1))*(stop2-start2)+start2;}//==============================================================================// World Definition//==============================================================================functionWorld(){//==============================================================================// All variables//==============================================================================var groundTexture;// Texture of the groundvar grounds;// Array2d : Stock all ground of the worldvar ai, aj;// position in grounds of the playervar pai, paj;// past position in grounds of the playervar timeRunning =0;// time updated var raycaster;// to determine direction of a clickvar camera, controls;var moveForward =false;var moveBackward =false;var moveLeft =false;var moveRight =false;var canJump =false;var prevTime = performance.now();var velocity =new THREE.Vector3();var direction =new THREE.Vector3();var vertex =new THREE.Vector3();var color =new THREE.Color();var sun;//sun and all functions with it (also stars)var loadingManager;//loading manager to load everything and thenrun the programthis.endCondition =false;//==============================================================================//==============================================================================//==============================================================================// All Class//==============================================================================//==============================================================================// Defines the THREE.PointerLockControls class, source at https://threejs.org///==============================================================================
THREE.PointerLockControls=function(camera){
let scope =this;
camera.rotation.set(0,0,0);
let pitchObject =new THREE.Object3D();
pitchObject.add( camera );
let yawObject =new THREE.Object3D();
yawObject.position.y =10;
yawObject.add( pitchObject );
let attachedObject =new THREE.Object3D();
yawObject.add(attachedObject);
attachedObject.position.set(0,-yawObject.position.y,-150);
let PI_2 =Math.PI /2;
let onMouseMove =function( event ){if( scope.enabled ===false)return;
let movementX = event.movementX || event.mozMovementX || event.webkitMovementX ||0;
let movementY = event.movementY || event.mozMovementY || event.webkitMovementY ||0;
yawObject.rotation.y -= movementX *0.002;
pitchObject.rotation.x -= movementY *0.002;
pitchObject.rotation.x =Math.max(- PI_2,Math.min( PI_2, pitchObject.rotation.x ));};this.getAttachedObject =function(){return attachedObject;};this.dispose =function(){
document.removeEventListener('mousemove', onMouseMove,false);};
document.addEventListener('mousemove', onMouseMove,false);this.enabled =false;this.getObject =function(){return yawObject;};this.getDirection =function(){// assumes the camera itself is not rotated
let direction =new THREE.Vector3(0,0,-1);
let rotation =new THREE.Euler(0,0,0,'YXZ');returnfunction( v ){
rotation.set( pitchObject.rotation.x, yawObject.rotation.y,0);
v.copy( direction ).applyEuler( rotation );return v;};}();};//==============================================================================// Class to stock Each Objects that were loaded // with their combobox size to place them in space// and to avoid collision ( objects at same place)classObj{
constructor(nameDoc, sX, sY, sZ){this.path = nameDoc;this.sizeX = sX;this.sizeY = sY;this.sizeZ = sZ;this.obj;}}//==============================================================================// Sun Class//==============================================================================// Here is the Sun Object. Explanation of parameters :// target (Object3D) : the player, or camera if you are in first person view. The sun need to be relative to a point// size (number): the size of the sun & stars// speed (number): the speed of the rotation of the sun// skyDistance (number): the distance of the sky from the target.functionSun(target, size, speed, skyDistance){this.angle =0;this.object =new THREE.DirectionalLight(0xffffff,0.1);this.object.position.set(0,Math.cos(this.angle)*skyDistance,Math.sin(this.angle)*skyDistance);this.object.castShadow =true;this.object.shadow.mapSize.width =1024;this.object.shadow.mapSize.height =1024;this.object.shadow.camera.near =10;this.object.shadow.camera.far =4000;
let d =1000;this.object.shadow.camera.left =-d;this.object.shadow.camera.right = d;this.object.shadow.camera.top = d;this.object.shadow.camera.bottom =-d;this.object.shadow.bias =-0.0001;
threeworld.scene.add(this.object);this.stars =[];this.starMaterial =new THREE.MeshBasicMaterial({color :"white", fog:false});this.starMaterial.transparent =true;this.starMaterial.opacity =0;
let sunball =new THREE.Mesh(new THREE.SphereGeometry(size,32,32),new THREE.MeshBasicMaterial({color :"yellow", fog:false}));this.object.add( sunball );this.starGyroscope =new THREE.Mesh();
target.add(this.starGyroscope);//Create all starsfor(let i =0; i<NBSTARS; i++){
let radius = AB.randomFloatAtoB ( size/25, size/8);
let star =new THREE.Mesh(new THREE.SphereGeometry(radius,8,8),this.starMaterial);
let s = AB.randomFloatAtoB (0,Math.PI*2);
let t = AB.randomFloatAtoB (0,Math.PI/2);
star.position.set(SKYDISTANCE*Math.cos(s)*Math.sin(t), skyDistance*Math.cos(t), skyDistance*Math.sin(s)*Math.sin(t));this.stars.push(star);this.starGyroscope.add(star);}//Use this in nextStep to make the sun movethis.animate =function(){this.angle+=0.001* speed;//normalize angle between -PI and PIwhile(this.angle <=-Math.PI)this.angle +=Math.PI*2;while(this.angle >Math.PI)this.angle -=Math.PI*2;this.object.position.set(target.position.x,Math.cos(this.angle)*skyDistance,Math.sin(this.angle)*skyDistance + target.position.z);this.object.intensity =this.getSunIntensity();
let c =new THREE.Color(this.getSkyColor());
threeworld.scene.background = c;this.setStarsOpacity();this.starGyroscope.rotation.set(-target.rotation.x,-target.rotation.y,-target.rotation.z);}//change star opacity and fog depending of the position of the sunthis.setStarsOpacity =function(){if(this.angle >Math.PI/2&&this.angle <Math.PI*3/4){this.starMaterial.opacity = map(this.angle,Math.PI/2,Math.PI*3/4,0,0.8);}elseif(this.angle >-Math.PI*3/4&&this.angle <-Math.PI/2){this.starMaterial.opacity = map(this.angle,-Math.PI*3/4,-Math.PI/2,0.8,0);}}//return the color of the sky depending of the position of the sun (to get the sunrise)this.getSkyColor =function(){if(this.angle >-Math.PI*3/8&&this.angle <Math.PI*3/8){// console.log("day");return0x7ec0ee;}elseif(this.angle >Math.PI*3/8&&this.angle <Math.PI/2){// console.log("Sunset 1");return lerpColor(0x7ec0ee,0xfd5e53, map(this.angle,Math.PI*3/8,Math.PI/2,0,1));}elseif(this.angle >Math.PI/2&&this.angle <Math.PI*5/8){// console.log("Sunset 2");return lerpColor(0xfd5e53,0x0c3166, map(this.angle,Math.PI/2,Math.PI*5/8,0,1));}elseif(this.angle >Math.PI*5/8||this.angle <-Math.PI*3/4){// console.log("night");return0x0c3166;}elseif(this.angle >-Math.PI*3/4&&this.angle <-Math.PI/2){// console.log("Sunrise 1");return lerpColor(0x0c3166,0xfd5e53, map(this.angle,-Math.PI*3/4,-Math.PI/2,0,1));}elseif(this.angle >-Math.PI/2&&this.angle <-Math.PI*3/8){// console.log("Sunrise 2");return lerpColor(0xfd5e53,0x7ec0ee, map(this.angle,-Math.PI/2,-Math.PI*3/8,0,1));}}//return intensity of the sunthis.getSunIntensity =function(){if(this.angle >-Math.PI*3/8&&this.angle <Math.PI*3/8){return2;}elseif(this.angle >Math.PI*3/8&&this.angle <Math.PI/2){return map(this.angle,Math.PI*3/8,Math.PI/2,2,1);}elseif(this.angle >Math.PI/2&&this.angle <Math.PI*3/4){return map(this.angle,Math.PI/2,Math.PI*3/4,1,0);}elseif(this.angle >Math.PI*3/4||this.angle <-Math.PI*3/4){return0;}elseif(this.angle >-Math.PI*3/4&&this.angle <-Math.PI/2){return map(this.angle,-Math.PI*3/4,-Math.PI/2,0,1);}elseif(this.angle >-Math.PI/2&&this.angle <-Math.PI*3/8){return map(this.angle,-Math.PI/2,-Math.PI*3/8,1,2);}}}//==============================================================================//==============================================================================//Just return a ground Elements that receive shadowfunction createGround(){
let texture = groundTexture;
let gr =new THREE.Mesh(new THREE.PlaneGeometry( squaresize*groundMultiplier, squaresize*groundMultiplier ),
texture );
gr.receiveShadow =true;
gr.rotation.x =(Math.PI /2)*3;return gr;}//initialize the ground of the world, to determine all type nd create fake grounds//around the world to fake a loopfunction initGround(){for(let i =0; i < worldSize; i++){for(let j =0; j < worldSize; j++){
grounds[i][j]= createGround();
grounds[i][j].position.set((i-Math.trunc(worldSize/2))* squaresize * groundMultiplier,0,(j-Math.trunc(worldSize/2))* squaresize*groundMultiplier);
threeworld.scene.add(grounds[i][j]);}}for(let i =- viewDistance; i < worldSize + viewDistance; i++){for(let j =- viewDistance; j < worldSize + viewDistance; j++){
let b =(worldSize + viewDistance);if(i <0|| j <0|| i >= worldSize || j >= worldSize){
let tmp;if( i <0){if(j <0){
tmp = grounds[worldSize + i][worldSize + j].clone();}elseif(j >= worldSize){
tmp = grounds[worldSize + i][j - worldSize].clone();}else{
tmp = grounds[worldSize + i][j].clone();}}elseif(i >= worldSize){if(j <0){
tmp = grounds[i - worldSize][worldSize + j].clone();}elseif(j >= worldSize){
tmp = grounds[i - worldSize][j - worldSize].clone();}else{
tmp = grounds[i - worldSize][j].clone();}}elseif(i >= worldSize){if(j <0){
tmp = grounds[i - worldSize][worldSize + j].clone();}elseif(j >= worldSize){
tmp = grounds[i - worldSize][j - worldSize].clone();}else{
tmp = grounds[i - worldSize][j].clone();}}elseif( j <0){
tmp = grounds[i][worldSize + j].clone();}elseif(j >= worldSize){
tmp = grounds[i][j - worldSize].clone();}
tmp.position.set((i -Math.trunc(worldSize/2))* squaresize * groundMultiplier,0,(j -Math.trunc(worldSize/2))* squaresize*groundMultiplier);
threeworld.scene.add(tmp);}}}}//==============================================================================//==============================================================================//==============================================================================// Functions link to an event//==============================================================================//Create a new infinite world. First destroy the previous one and then recreate one.function createNewInfiniteWorld(){
viewDistance = newviewDistance;
worldSize = newworldSize;
groundMultiplier = newGroundMultiplier;while(threeworld.scene.children.length){
threeworld.scene.remove(threeworld.scene.children[0]);}
threeworld.scene.add(controls.getObject());
init();}function onDocumentTouchStart( event ){
console.log("onDocumentTouchStart");
event.preventDefault();
event.clientX = event.touches[0].clientX;
event.clientY = event.touches[0].clientY;
onDocumentMouseDown( event );}//Called when a key is upfunction handleKeyUp (e){if((e.keyCode ==38)||(e.keyCode ==40)){
velocity =0;}if(e.keyCode ==37|| e.keyCode ==39){
speedRotation =0;}if(e.keyCode ==37|| e.keyCode ==39){
speedRotation =0;}}//==============================================================================//==============================================================================//Load all you needfunction loader(){
planeTex = THREE.ImageUtils.loadTexture("/uploads/meak/grass.jpg");
planeTex.wrapS = planeTex.wrapT = THREE.RepeatWrapping;
planeTex.repeat.set(8,8);
groundTexture =new THREE.MeshPhongMaterial({map: planeTex, dithering:true});
groundTexture.wrapAround =true;
groundTexture.castShadow =true;
groundTexture.receiveShadow =true;}//Initalization before running the worldfunction init(){
grounds =newArray(worldSize);for(let i =0; i < worldSize; i++){
grounds[i]=newArray(worldSize);for(let j =0; j < worldSize; j++){
grounds[i][j]=null;}}
ai = parseInt(worldSize/2+ camera.getWorldPosition().x/(squaresize*groundMultiplier));
aj = parseInt(worldSize/2+ camera.getWorldPosition().z/(squaresize*groundMultiplier));
pai = ai;
paj = aj;
initGround();// LIGHTS
let hemiLight =new THREE.HemisphereLight( SKYCOLOR, SKYCOLOR,0.4);
hemiLight.position.set(0,50,0);
threeworld.scene.add( hemiLight );}function checkPositionPlayer(){//Update the position of the payer in the world so that it can generate ground around the player, depending on the viewDistanceif(worldSize/2+ camera.getWorldPosition().x/(squaresize*groundMultiplier)<0){
ai =-Math.ceil(-(worldSize/2+ camera.getWorldPosition().x/(squaresize*groundMultiplier)));}else{
ai =Math.trunc(worldSize/2+ camera.getWorldPosition().x/(squaresize*groundMultiplier));}if(worldSize/2+ camera.getWorldPosition().z/(squaresize*groundMultiplier)<0){
aj =-Math.ceil(-(worldSize/2+ camera.getWorldPosition().z/(squaresize*groundMultiplier)));}else{
aj =Math.trunc(worldSize/2+ camera.getWorldPosition().z/(squaresize*groundMultiplier));}if(ai <0){
controls.getObject().position.x =(worldSize/2)* groundMultiplier * squaresize -0.01;}if(ai >= worldSize){
controls.getObject().position.x =- worldSize/2* groundMultiplier * squaresize;}if(aj >= worldSize){
controls.getObject().position.z =- worldSize/2* groundMultiplier * squaresize;}if(aj <0){
controls.getObject().position.z =(worldSize/2)* groundMultiplier * squaresize -0.01;}if(ai != pai || aj != paj){
pai = ai;
paj = aj;}}//==============================================================================//==============================================================================//==============================================================================// Function newRun ,init and endRun//==============================================================================this.newRun =function(){
camera =new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight,1, SKYDISTANCE );
threeworld.camera = camera;
threeworld.init3d (0,0, SKYCOLOR );// can adjust renderer:
threeworld.renderer.shadowMap.enabled =true;
threeworld.renderer.shadowMap.type = THREE.PCFSoftShadowMap;//load ground texture
loader();//position of mouse in the canvas
mouse =new THREE.Vector2();//First person controller
controls =new THREE.PointerLockControls( camera );//This will handle key presses
let onKeyDown =function( event ){switch( event.keyCode ){case38:// upcase87:// w
moveForward =true;break;case37:// leftcase65:// a
moveLeft =true;break;case40:// downcase83:// s
moveBackward =true;break;case39:// rightcase68:// d
moveRight =true;break;case32:// spaceif( canJump ===true||true) velocity.y +=350;
canJump =false;break;case82://Re-generateTheworld (R)
createNewInfiniteWorld();
threeworld.scene.add(sun.object);break;}};
let onKeyUp =function( event ){switch( event.keyCode ){case38:// upcase87:// w
moveForward =false;break;case37:// leftcase65:// a
moveLeft =false;break;case40:// downcase83:// s
moveBackward =false;break;case39:// rightcase68:// d
moveRight =false;break;}};
document.addEventListener('keydown', onKeyDown,false);
document.addEventListener('keyup', onKeyUp,false);
raycaster =new THREE.Raycaster(new THREE.Vector3(),new THREE.Vector3(0,-1,0),0,10);//The following handles pointer locking when clicking the window
let havePointerLock ='pointerLockElement' in document ||'mozPointerLockElement' in document ||'webkitPointerLockElement' in document;
console.log(havePointerLock);if( havePointerLock ){
let element = document.body;
let pointerlockchange =function( event ){if( document.pointerLockElement === element || document.mozPointerLockElement === element || document.webkitPointerLockElement === element ){if(HUDEVENT){
document.exitPointerLock();
HUDEVENT =false;}else{if(!controls.enabled && controls.getAttachedObject().children.length !==0){
controls.getAttachedObject().remove(controls.getAttachedObject().children[1]);
controls.getAttachedObject().remove(controls.getAttachedObject().children[0]);}if(!controls.enabled){
controls.enabled =true;
$("#user_span10").html("");}}}else{
controls.enabled =false;
$("#user_span10").html("<p><b>Click screen to enable mouse controls</b></p>");}};
let pointerlockerror =function( event ){
console.error("pointerlockerror");};// Hook pointer lock state change events
document.addEventListener('pointerlockchange', pointerlockchange,false);
document.addEventListener('mozpointerlockchange', pointerlockchange,false);
document.addEventListener('webkitpointerlockchange', pointerlockchange,false);
document.addEventListener('pointerlockerror', pointerlockerror,false);
document.addEventListener('mozpointerlockerror', pointerlockerror,false);
document.addEventListener('webkitpointerlockerror', pointerlockerror,false);
document.addEventListener('click',function( event ){// Ask the browser to lock the pointer
element.requestPointerLock = element.requestPointerLock || element.mozRequestPointerLock || element.webkitRequestPointerLock;
element.requestPointerLock();},false);}else{
$("#user_span1").html('<p>Your browser doesn\'t seem to support Pointer Lock API</p>');}if( AB.onDesktop()){
$("#user_span1").html("<p>Use WASD or Arrows to move, mouse to look around and space to jump.</p>"+"<p> If you want to re-generate the world, you can press R !</p>");
$("#user_span10").html("<p><b>Click screen to enable mouse controls</b></p>");
$("#user_span4").html("<p> Size of each parcel of the world (1 to 1000) <input type=\"number\" min=\"1\" max=\"1000\" value=\""+ newGroundMultiplier +"\" class=\"slider\" id=\"groundMultiplierHtml\"></p>");
document.getElementById("groundMultiplierHtml").onchange =function(){
newGroundMultiplier =+this.value ;
console.log("groundMultiplierHtml "+ newGroundMultiplier);
HUDEVENT =true;}
document.getElementById("groundMultiplierHtml").onkeypress =function(){
newGroundMultiplier =+this.value ;
console.log("groundMultiplierHtml "+ newGroundMultiplier);
HUDEVENT =true;}
$("#user_span5").html("<p> Size of the world (1 to 50) <input type=\"number\" min=\"1\" max=\"50\" value=\""+ newworldSize +"\" class=\"slider\" id=\"worldSizeHtml\"></p>");
document.getElementById("worldSizeHtml").onchange =function(){
newworldSize =+this.value;if((newworldSize -1)/2< newviewDistance){
newviewDistance =0;
document.getElementById("viewDistanceHtml").value =0;}
HUDEVENT =true;
console.log("worldSizeHtml "+ newworldSize);}
document.getElementById("worldSizeHtml").onkeypress =function(){
newworldSize =+this.value;if((newworldSize -1)/2< newviewDistance){
newviewDistance =0;
document.getElementById("viewDistanceHtml").value =0;}
HUDEVENT =true;
console.log("worldSizeHtml "+ newworldSize);}
$("#user_span6").html("<p> viewDistance in term of parcel (0 to 10) <input type=\"number\" min=\"0\" max=\"10\" value=\""+ newviewDistance +"\" class=\"slider\" id=\"viewDistanceHtml\"></p>");
document.getElementById("viewDistanceHtml").onchange =function(){if(newworldSize/2>=+this.value){
newviewDistance =+this.value ;}
console.log("viewDistanceHtml "+ newviewDistance);
HUDEVENT =true;}
document.getElementById("viewDistanceHtml").onkeypress =function(){if(newworldSize/2>=+this.value){
newviewDistance =+this.value ;}
console.log("viewDistanceHtml "+ newviewDistance);
HUDEVENT =true;}}else{
$("#user_span1").html("<p> <b> This World currently only works on desktop. </b> </p>");}
createNewInfiniteWorld();//add sun
sun =newSun(controls.getObject(),100,3,SKYDISTANCE);};this.nextStep =function(){//======================================================================//This will handle moving the player and the camera//======================================================================
sun.animate();
raycaster.ray.origin.copy( controls.getObject().position );
raycaster.ray.origin.y -=10;
let time = performance.now();
let delta =( time - prevTime )/1000;
velocity.x -= velocity.x *10.0* delta;
velocity.z -= velocity.z *10.0* delta;
velocity.y -=9.8*100.0* delta;// 100.0 = mass
direction.z =Number( moveForward )-Number( moveBackward );
direction.x =Number( moveLeft )-Number( moveRight );
direction.normalize();// this ensures consistent movements in all directionsif( moveForward || moveBackward ) velocity.z -= direction.z *400.0* MOVESPEED * delta;if( moveLeft || moveRight ) velocity.x -= direction.x *400.0* MOVESPEED * delta;
controls.getObject().translateX( velocity.x * delta );
controls.getObject().translateY( velocity.y * delta );
controls.getObject().translateZ( velocity.z * delta );if( controls.getObject().position.y <10){
velocity.y =0;
controls.getObject().position.y =10;
canJump =true;}
prevTime = time;//Function to do the loop if the player is at the edge of the world
checkPositionPlayer();};//==============================================================================//==============================================================================}