/** Global variables */
var scene, camera, target, renderer, clock;
var bullets = [];
var mouse = { x: 0, y: 0 }, hit = 0;
var WIDTH = window.innerWidth, HEIGHT = window.innerHeight
var keyboard = {};
var player = { height:1.8, turnSpeed:Math.PI*0.02, canShoot:0 };
var blocker = document.getElementById( 'blocker' );
var instructions = document.getElementById( 'instructions' );
var havePointerLock = 'pointerLockElement' in document || 'mozPointerLockElement' in document || 'webkitPointerLockElement' in document;
/**
* Checks browser to see if cursor can be locked, locks cursor
* if so otherwise present error message.
* @param {boolean} havePointerLock - The boolean determining whether browser is capable of pointer lock.
* @return {None}
*/
function lockCursor(havePointerLock) {
if (havePointerLock) {
var element = document.body;
var pointerlockchange = function ( event ) {
if ( document.pointerLockElement === element
|| document.mozPointerLockElement === element
|| document.webkitPointerLockElement === element ) {
controls.enabled = true;
blocker.style.display = 'none';
} else {
controls.enabled = false;
blocker.style.display = '-webkit-box';
blocker.style.display = '-moz-box';
blocker.style.display = 'box';
instructions.style.display = '';
}
}
var pointerlockerror = function ( event ) {
instructions.style.display = '';
}
// 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 );
instructions.addEventListener( 'click', function ( event ) {
instructions.style.display = 'none';
// Ask the browser to lock the pointer
element.requestPointerLock = element.requestPointerLock || element.mozRequestPointerLock || element.webkitRequestPointerLock;
if ( /Firefox/i.test( navigator.userAgent ) ) {
var fullscreenchange = function ( event ) {
if ( document.fullscreenElement === element || document.mozFullscreenElement === element || document.mozFullScreenElement === element ) {
document.removeEventListener( 'fullscreenchange', fullscreenchange );
document.removeEventListener( 'mozfullscreenchange', fullscreenchange );
element.requestPointerLock();
}
}
document.addEventListener( 'fullscreenchange', fullscreenchange, false );
document.addEventListener( 'mozfullscreenchange', fullscreenchange, false );
element.requestFullscreen = element.requestFullscreen || element.mozRequestFullscreen || element.mozRequestFullScreen || element.webkitRequestFullscreen;
element.requestFullscreen();
} else {
element.requestPointerLock();
}
}, false );
} else {
instructions.innerHTML = 'Your browser doesn\'t seem to support Pointer Lock API';
}
}
lockCursor(havePointerLock)
/**
* Randomizes location of target to click
* @param {int} min - The int specifying the min -- lower bound.
* @param {int} max - The int specifying the max -- lower bound.
* @return {number} Location of target
*/
function getRandomLoc(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min) + min); //The maximum is exclusive and the minimum is inclusive
}
/**
* Randomizes size of target to click
* @param {int} min - The int specifying the min -- lower bound.
* @param {int} max - The int specifying the max -- lower bound.
* @return {number} Size of target
*/
function getRandomSize(min, max) {
return Math.random() * (max - min) + min;
}
/**
* Spawns THREE.js geometric target with position and size determined from
* getRandomLoc() and getRandomSize()
* @param {THREE} scene - The world instance of the game
* @return {None}
*/
function spawnTarget(scene) {
const geometry = new THREE.SphereGeometry(getRandomSize(0.2, 0.9), 32, 32);
const material = new THREE.MeshBasicMaterial( {color: 0xffbf00} );
target = new THREE.Mesh( geometry, material );
scene.add( target );
target.position.x += getRandomLoc(-10,10);
target.position.y += getRandomLoc(1,5);
target.position.z += getRandomLoc(0,10);
scene.add(target);
}
/**
* Creates THREE.js geometric floor, walls, and ceiling to create scene
* of playing area
* @param {THREE} scene - The world instance of the game
* @return {None}
*/
function createSpace(scene) {
floor = new THREE.Mesh(
new THREE.PlaneGeometry(150,150,150,150),
new THREE.MeshBasicMaterial({color:0xa9a9a9})
);
floor.rotation.x -= Math.PI / 2; // Rotate the floor 90 degrees
scene.add(floor);
wall1 = new THREE.Mesh(
new THREE.BoxGeometry(200, 40, 20),
new THREE.MeshBasicMaterial({color:0x282828})
);
wall1.position.y -= 1;
wall1.position.z += 20;
scene.add(wall1);
wall2 = new THREE.Mesh(
new THREE.BoxGeometry(20, 40, 200),
new THREE.MeshBasicMaterial({color:0x282828})
);
wall2.position.y -= 1;
wall2.position.x += 30;
scene.add(wall2);
wall3 = new THREE.Mesh(
new THREE.BoxGeometry(20, 40, 200),
new THREE.MeshBasicMaterial({color:0x282828})
);
wall3.position.y -= 1;
wall3.position.x -= 30;
scene.add(wall3);
wall4 = new THREE.Mesh(
new THREE.BoxGeometry(200, 40, 20),
new THREE.MeshBasicMaterial({color:0x606060})
);
wall4.position.y -= 1;
wall4.position.z -= 40;
scene.add(wall4);
ceiling = new THREE.Mesh(
new THREE.BoxGeometry(200, 1, 200),
new THREE.MeshBasicMaterial({color:0x484848})
);
ceiling.position.y += 40;
scene.add(ceiling);
}
/**
* Creates THREE.js player with THREE.js camera perspective and predetermined controls
* @param {THREE} scene - The world instance of the game
* @return {None}
*/
function createPlayer(scene) {
camera.position.set(0, player.height, -5);
camera.lookAt(new THREE.Vector3(0,player.height,0));
controls = new THREE.PointerLockControls(camera, document.body)
scene.add(controls.getObject())
}
/**
* Renders THREE.js WebGL scene
* @param {THREE} scene - The world instance of the game
* @return {None}
*/
function render(scene) {
renderer = new THREE.WebGLRenderer();
renderer.setSize(WIDTH, HEIGHT);
document.body.appendChild(renderer.domElement);
}
/**
* Initializes the world, game, player, and targets
* @return {None}
*/
function init(){
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(90, window.innerWidth/window.innerHeight, 0.1, 1000);
clock = new THREE.Clock();
createSpace(scene)
spawnTarget(scene)
createPlayer(scene)
/*var reticle = new THREE.Mesh(
new THREE.RingBufferGeometry( 0.85 * 500, 500, 32),
new THREE.MeshBasicMaterial( {color: 0x000000, side: THREE.DoubleSide })
);
reticle.position.z = -4;
reticle.lookAt(camera.position);
camera.add(reticle);
scene.add(camera)*/
render(scene)
animate()
}
/**
* Animates the scene
* @return {None}
*/
function animate(){
requestAnimationFrame(animate);
target.rotation.x += 0.01;
target.rotation.y += 0.02;
renderer.render(scene, camera);
}
/**
* Detects when a key has been pressed down
* @param {event} event - Keyboard event
* @return {None}
*/
function keyDown(event){
keyboard[event.keyCode] = true;
}
/**
* Detects when a key has been pressed down
* @param {event} event - Keyboard event
* @return {None}
*/
function keyUp(event){
keyboard[event.keyCode] = false;
}
window.addEventListener('keydown', keyDown);
window.addEventListener('keyup', keyUp);
window.onload = init;
/**
* Handles window resizing
* @return {None}
*/
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
window.addEventListener( 'resize', onWindowResize, false )