/**
* Initializes the flight school scene
*/
async function init() {
// check if the user was redirected from the flight simulator
const urlParams = new URLSearchParams(window.location.search);
const redirect = urlParams.get("redirect-from");
if (redirect === "flight-simulator") redirectFromFlightSimulator = true;
window.addEventListener("keydown", event => { if (event.key === "f" || event.key === "F") window.location.href = "/flight-simulator" });
// config for three.js
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
renderer = new THREE.WebGLRenderer();
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFShadowMap;
// resize the renderer when the window is resized
window.addEventListener("resize", () => {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
});
renderer.setSize(window.innerWidth, window.innerHeight);
// enable THREEx dom events
domEvents = new THREEx.DomEvents(camera, renderer.domElement);
// add a clock
clock = new THREE.Clock();
// place all objects/lights and enable its interactions
await placeObjects();
await placeLights();
initInteractions();
// enable walking with the keyboard and orientation controls
initWalk();
initMouseClickMove();
// init stats and developer controls / keyboard shortcuts
initStats();
initDevControls();
// if the user was redirected from the flight simulator look at the monitor
if (redirectFromFlightSimulator) {
redirectFromFlightSimulator = true;
sceneObjects.player.position.set(3.6, sceneObjects.player.position.y, 1.5);
camera.position.set(sceneObjects.player.position.x, headHeight, sceneObjects.player.position.z);
camera.lookAt(sceneObjects.monitor.position.x, -10, 100);
camera.updateProjectionMatrix()
window.history.replaceState({}, document.title, "/");
}
const startImmediately = putStartScreenOnReady();
if (startImmediately) {
startScene();
document.getElementById("start-button").addEventListener("click", () => { startScene() });
window.addEventListener("keydown", (event) => { if (event.key === "Enter") startScene() });
return;
}
// wait till the user clicks on the start button or presses enter
await new Promise((resolve) => {
document.getElementById("start-button").addEventListener("click", () => {
startScene();
resolve();
});
window.addEventListener("keydown", (event) => {
if (event.key === "Enter") {
startScene();
resolve();
}
});
});
}
/**
* Initialize the FPS stats
*/
function initStats() {
stats = new Stats();
stats.setMode(0);
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '10px';
stats.domElement.style.top = '80px';
stats.domElement.id = "stats";
stats.domElement.style.display = "none";
document.body.appendChild(stats.domElement);
}
/**
* Initialize developer controls / keyboard shortcuts and experimental features
* such as the ability to turn on/off all lights by pressing l
* or the ability to turn on/off shadows of the chairs by pressing c
*/
function initDevControls() {
window.addEventListener("keydown", event => {
switch (event.key) {
case "l":
case "L":
sceneObjects.bulbLights.forEach(light => light.visible = !light.visible);
break;
case "c":
case "C":
// toggle shadows of the chairs
[...sceneObjects.chairs, sceneObjects.profChair].forEach((chair) => {
chair.traverse((child) => { child.castShadow = !child.castShadow; });
});
break;
case "t":
case "T":
// toggle shadows of the table
[...sceneObjects.tables, sceneObjects.profTable].forEach(table => {
table.traverse((child) => {
child.castShadow = !child.castShadow;
if (child.name == "Tischplatte_Top") {
child.receiveShadow = true;
child.castShadow = false;
}
});
});
break;
case "h":
case "H":
// toggle help screen visibility
document.getElementById("start-screen").style.display = document.getElementById("start-screen").style.display === "none" ? "block" : "none";
break;
case "j":
case "J":
// toggle stats visibility
stats.domElement.style.display = stats.domElement.style.display === "none" ? "block" : "none";
break;
case "u":
case "U":
// toggle collision detection
collisionDetectionEnabled = !collisionDetectionEnabled;
break;
}
});
}
/**
* Hides the start screen and starts the scene
*/
function startScene() {
document.body.appendChild(renderer.domElement);
document.getElementById("start-screen").style.display = "none";
}
/**
* Sets the button from "Loading..." to "Start" and enables it
* @returns {boolean} true if the start button should be clicked immediately (if the user was redirected from the flight simulator)
*/
function putStartScreenOnReady() {
// remove the loading icon
document.getElementById("loading-icon").style.display = "none";
// change button text to "Start" and enable the button
document.getElementById("start-button").innerText = "Start";
document.getElementById("start-button").removeAttribute("disabled");
if (redirectFromFlightSimulator) return true;
return false;
}