ABWorld;
AB.clockTick = 100;
AB.maxSteps = 10000;
AB.screenshotStep = 50;
AB.drawRunControls = true;
// default AB paramters
const show3d = true;
const OBJPATH = "/uploads/linr2/";
const PLAYER1OBJ = "Quigon.obj";
const PLAYER1MTL = "Quigon.mtl";
const WALLOBJ = "farm_type_wall.obj";
const WALLMTL = "farm_type_wall.mtl";
const WALL_TEXTURE = '/uploads/linr2/farm_type_wall_wall_Height.png' ; // constants for uploads
var cam;
var meshFloor;
var keyboard = {};
var updatedPosX;
var updatedPosZ;
var play;
var player = { height:2, speed:0.3, turnSpeed:0.09};
var playerspeed=0;
var scene = new THREE.Scene();
var sky_texture = new THREE.TextureLoader().load( 'uploads/linr2/milky.jpg' );
scene.background = sky_texture;
var startTime = performance.now();
var renderer = new THREE.WebGLRenderer(); //inialise WEBGL
startTime=performance.now(); // begins timing the user
var wall_texture;
function render()
{
renderer.setSize(window.innerWidth, window.innerHeight); // sets how big to render the game in browser window
document.body.appendChild(renderer.domElement);
}
function camera()
{
cam = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 0.1, 1000);
cam.position.set(0, 3.5, -90); // sets camera positioning (x,y,z)
cam.lookAt(scene.position);
}
function create_player()
{
THREE.DefaultLoadingManager.addHandler ( /\.tga$/i, new THREE.TGALoader() );
var m = new THREE.MTLLoader();
m.setResourcePath ( OBJPATH );
m.setPath ( OBJPATH );
m.load ( PLAYER1MTL, function ( materials )
{
materials.preload();
var o = new THREE.OBJLoader(); // imports the player uploaded to AB,
o.setMaterials ( materials ); // credit to tomi210 here: https://free3d.com/3d-model/lego-qui-gon-18960.html
o.setPath ( OBJPATH );
o.load ( PLAYER1OBJ, function ( object )
{
play = object;
play.scale.multiplyScalar(0.05); // sets the scale and location of where to place player model
play.position.set(0,player.height,-160);
scene.add(play);
}
);
}
);
}
function loadtextures()
{
var loader2 = new THREE.TextureLoader();
loader2.load ( WALL_TEXTURE, function ( thetexture )
{ // loads textures of the wall
thetexture.minFilter = THREE.LinearFilter;
wall_texture = thetexture;
}
);
}
function generateWall()
{
THREE.DefaultLoadingManager.addHandler ( /\.tga$/i, new THREE.TGALoader() );
var m = new THREE.MTLLoader();
m.setResourcePath ( OBJPATH );
m.setPath ( OBJPATH );
m.load ( WALLMTL, function ( materials )
{
materials.preload();
var o = new THREE.OBJLoader();
o.setMaterials ( materials ); // generates the wall obstacles using a 3D model
o.setPath ( OBJPATH ); // Credit to g3ordie, link here : https://free3d.com/3d-model/farm-type-wall-and-gate-47186.html
o.load ( WALLOBJ, function ( object )
{
Wall = object;
Wall.scale.multiplyScalar(0.1);
Wall.position.set(-10,0,100);
scene.add(Wall);
}
);
}
);
m.load ( WALLMTL, function ( materials )
{
materials.preload();
var o = new THREE.OBJLoader();
o.setMaterials ( materials );
o.setPath ( OBJPATH );
o.load ( WALLOBJ, function ( object )
{
Wall2 = object;
Wall2.scale.multiplyScalar(0.1);
Wall2.position.set(10,0,50);
Wall2.rotation.y = 330;
scene.add(Wall2);
}
);
}
);
m.load ( WALLMTL, function ( materials )
{
materials.preload();
var o = new THREE.OBJLoader();
o.setMaterials ( materials );
o.setPath ( OBJPATH );
o.load ( WALLOBJ, function ( object )
{
Wall3 = object;
Wall3.scale.multiplyScalar(0.1);
Wall3.position.set(-10,0,30);
Wall3.rotation.y = 0;
scene.add(Wall3);
}
);
}
);
m.load ( WALLMTL, function ( materials )
{
materials.preload();
var o = new THREE.OBJLoader();
o.setMaterials ( materials );
o.setPath ( OBJPATH );
o.load ( WALLOBJ, function ( object )
{
Wall4 = object;
Wall4.scale.multiplyScalar(0.15);
Wall4.position.set(10,0,-15);
Wall4.rotation.y = 330;
scene.add(Wall4);
}
);
}
);
m.load ( WALLMTL, function ( materials )
{
materials.preload();
var o = new THREE.OBJLoader();
o.setMaterials ( materials );
o.setPath ( OBJPATH );
o.load ( WALLOBJ, function ( object )
{
Wall5 = object;
Wall5.scale.multiplyScalar(0.1);
Wall5.position.set(-10,0,-60);
Wall5.rotation.y = 0;
scene.add(Wall5);
var light = new THREE.DirectionalLight( "#3fe293", 5 );
light.position.set( 0, 10, -180 );
scene.add( light );
}
);
}
);
m.load ( WALLMTL, function ( materials )
{
materials.preload();
var o = new THREE.OBJLoader();
o.setMaterials ( materials );
o.setPath ( OBJPATH );
o.load ( WALLOBJ, function ( object )
{
Wall6 = object;
Wall6.scale.multiplyScalar(0.1);
Wall6.position.set(10,0,-125);
Wall6.rotation.y = 330;
scene.add(Wall6);
}
);
}
);
}
function collisionCheck()
{
var firstObject = play;
var secondObject = Wall;
var thirdObject = Wall2;
var fourthObject = Wall3;
var fifthObject = Wall4;
var sixthObject = Wall5;
var seventhObject = Wall6;
firstBB = new THREE.Box3().setFromObject(firstObject, true);
secondBB = new THREE.Box3().setFromObject(secondObject, true);
thirdBB = new THREE.Box3().setFromObject(thirdObject, true);
fourthBB = new THREE.Box3().setFromObject(fourthObject, true);
fifthBB = new THREE.Box3().setFromObject(fifthObject, true);
sixthBB = new THREE.Box3().setFromObject(sixthObject, true);
seventBB = new THREE.Box3().setFromObject(seventhObject, true); //collision check using boundingBox on each wall and checking if their rays intersect
var collision = secondBB.intersectsBox(firstBB);
collision = fourthBB.intersectsBox(firstBB);
collision = fifthBB.intersectsBox(firstBB);
collision = sixthBB.intersectsBox(firstBB);
collision = seventBB.intersectsBox(firstBB);
if (collision)
{
play.position.set(0,player.height,-160);
collision = false;
}
}
function floor()
{
var texture = new THREE.TextureLoader().load( 'uploads/linr2/ground.jpeg' );
texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
texture.offset.set( 2, 2 );
texture.repeat.set( 10, 10 ); // loads in the jpeg image as floor texture and repeats it so it isn't stretched.
meshFloor = new THREE.Mesh(
new THREE.PlaneGeometry(100,400), // creates a plane/floor of 100x400
new THREE.MeshBasicMaterial({map:texture}));
meshFloor.rotation.x -= Math.PI / 2; // rotates floor so it's not vertical
scene.add(meshFloor);
}
function checkLocation()
{
if(play.position.z >= 160)
{
const e=Math.floor((performance.now()-startTime)/1e3); // checks for position of the player, if passes the point of the finish line
AB.newSplash() // sends out time to socketout and calls the game to be over.
AB.splashHtml(`<h1>It took you ${e} seconds to reach the end!</h1>`)
AB.socketOut({
data :
{
time: e,
}
})
AB.socket.destroy();
GameOver();
}
}
function AddFinishLine()
{
var finishL = new THREE.BoxGeometry( 100, 70, 25 );
var FinishLine = new THREE.Mesh( finishL );
FinishLine.material.color.setHex( 0xff2d00 ); // adds finish line mesh that can be clearly seen
FinishLine.position.x = 0;
FinishLine.position.z = 180;
FinishLine.position.y = 0;
scene.add( FinishLine );
var light = new THREE.DirectionalLight( "#7fe093", 4 );
light.position.set( 0, 1, 0 );
scene.add( light );
}
function movement()
{
requestAnimationFrame(movement);
if(keyboard[87] || keyboard[38])
{ // W or up arrow key in order to move forward and to update the position of the player amplified by the player speed
if (play.position.x<= 180 && play.position.x>= -180)
{
play.position.x -= Math.sin(play.rotation.y) * player.speed/1.5;
play.position.z -= -Math.cos(play.rotation.y) * player.speed/1.5;
collisionCheck(); // sends the user position to be checked for collisions
}
else
{
play.position.x += Math.sin(play.rotation.y) * player.speed/1.5;
collisionCheck();
}
if(play.position.z<= 180 && play.position.z>= -180)
{
play.position.x -= Math.sin(play.rotation.y) * player.speed/1.5;
play.position.z -= -Math.cos(play.rotation.y) * player.speed/1.5;
collisionCheck();
}
else
{
play.position.z += -Math.cos(play.rotation.y) * player.speed/1.5;
collisionCheck();
}
playerspeed++;
checkLocation();
collisionCheck();
}
if(keyboard[83] || keyboard[40])
{ // S or down arrow key, same as above but with S
if (play.position.x<= 160 && play.position.x>= -160)
{
play.position.x += Math.sin(play.rotation.y) * player.speed/1.5;
play.position.z += -Math.cos(play.rotation.y) * player.speed/1.5;
collisionCheck();
}
else
{
play.position.x -= Math.sin(play.rotation.y) * player.speed/1.5;
}
if(play.position.z<= 200 && play.position.z>= -160)
{
play.position.x += Math.sin(play.rotation.y) * player.speed/1.5;
play.position.z += -Math.cos(play.rotation.y) * player.speed/1.5;
collisionCheck();
}
else
{
play.position.z -= -Math.cos(play.rotation.y) * player.speed/1.5;
collisionCheck();
}
playerspeed++;
checkLocation();
collisionCheck();
}
if(keyboard[65] || keyboard[37])
{ // A or left arrow key, same as above however if player goes too far left off the platform, teleports them back to middle.
if (play.position.x <= 50 && play.position.x >= -50) // introduces horizonal movement to the left
{
play.position.x += Math.sin(play.rotation.y + Math.PI/2) * player.speed/1.5;
play.position.z += -Math.cos(play.rotation.y + Math.PI/2) * player.speed/1.5;
collisionCheck();
}
else
{
play.position.x = Math.sin(play.rotation.y - Math.PI/2) * player.speed/1.5;
collisionCheck();
}
if(play.position.z <= 200 && play.position.z >= -200)
{
play.position.x += Math.sin(play.rotation.y + Math.PI/2) * player.speed/1.5;
play.position.z += -Math.cos(play.rotation.y + Math.PI/2) * player.speed;
collisionCheck();
}
else
{
play.position.z = -Math.cos(play.rotation.y - Math.PI/2) * player.speed/1.5;
collisionCheck();
}
playerspeed++;
checkLocation(); // collision check and finish line check
collisionCheck();
}
if(keyboard[68] || keyboard[39])
{ // D or right arrow key, same as A key and but checks for right horizonal movement
if (play.position.x<= 50 && play.position.x>= -50)
{ // teleports user back to middle if too far right.
play.position.x += Math.sin(play.rotation.y - Math.PI/2) * player.speed/1.5;
play.position.z += -Math.cos(play.rotation.y - Math.PI/2) * player.speed/1.5;
collisionCheck();
}
else
{
play.position.x = Math.sin(play.rotation.y + Math.PI/2) * player.speed/1.5;
collisionCheck();
}
if(play.position.z<= 200 && play.position.z>= -200)
{
play.position.x += Math.sin(play.rotation.y - Math.PI/2) * player.speed/1.5;
play.position.z += -Math.cos(play.rotation.y - Math.PI/2) * player.speed;
collisionCheck();
}
else
{
play.position.z = -Math.cos(play.rotation.y + Math.PI/2) * player.speed/1.5;
collisionCheck();
}
playerspeed++;
checkLocation();
collisionCheck();
}
cam.position.x = play.position.x ;
cam.position.z = play.position.z -5;
cam.position.y = 4;
renderer.render(scene, cam);
}
function keyDown(event)
{
keyboard[event.keyCode] = true;
}
function keyUp(event)
{
keyboard[event.keyCode] = false;
}
window.addEventListener('keydown', keyDown); // checks for if key is held down or lifted up in order to implement smooth movement
window.addEventListener('keyup', keyUp);
AB.world.newRun = function()
{
AB.socketStart();
loadtextures();
render();
create_player();
camera();
floor();
AddFinishLine();
generateWall();
movement();
AB.showRunHeader();
welcome();
};
function welcome()
{
AB.newSplash(); // Welcome screen for all users, introducing game and controls.
AB.runReady = false
AB.splashHtml ( `
<h1> Welcome to 3D Platformer! </h1>
The Goal is to reach the Finish line in the fastest time. <br>
Press WASD to move, If you touch any of the obstacles you get reset to the beginning (not working)!
<p>
<button onclick='AB.removeSplash();' class=ab-largenormbutton >Start</button>
<p> `)
}
AB.socketIn = function(element)
{
AB.newSplash(); // socket to receive information, if information is received, it means player reached finish line
AB.splashHtml ( ` <h1> Game Over!<h1> <p>Other player finished in: `+ element.data.time + ` seconds. </p>`);
if (playonce != 1)
{
var congrats = new Audio("/uploads/linr2/congratulations.mp3");
backgroundM.volume = 0;
congrats.volume = 0.04;
congrats.play();
playonce += 1;
Object.freeze(play);
}
}
var playonce = 0; // variable to make sure congratulation sound is only played once.
function GameOver()
{
if (playonce != 1)
{ // gameover function to play sound and mute background music
var congrats = new Audio("/uploads/linr2/congratulations.mp3");
backgroundM.volume = 0;
congrats.volume = 0.04;
congrats.play();
playonce += 1;
Object.freeze(play);
}
}
welcome();
var backgroundM = new Audio("/uploads/linr2/background.mp3");
backgroundM.volume = 0.025;
backgroundM.play();