Files
retro-flight-sim/js/ui.js
T
mac-container-dev 76bad46d09 Initial commit: Retro 90s flight simulator MVP
Loading screen, main menu, 3D flight sim with CRT post-processing,
procedural terrain, airport with buildings, low-poly aircraft,
flight physics, HUD instruments, and sound.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-05 10:43:22 +00:00

143 lines
4.3 KiB
JavaScript

export class UI {
constructor() {
this.loadingScreen = document.getElementById('loading-screen');
this.mainMenu = document.getElementById('main-menu');
this.pauseMenu = document.getElementById('pause-menu');
this.controlsScreen = document.getElementById('controls-screen');
this.quitScreen = document.getElementById('quit-screen');
this.progressBar = document.getElementById('progress-bar');
this.loadingMessage = document.getElementById('loading-message');
this.menuItems = document.querySelectorAll('#menu-items .menu-item');
this.pauseItems = document.querySelectorAll('#pause-items .menu-item');
this.currentMenuItem = 0;
this.currentPauseItem = 0;
this.onNewFlight = null;
this.onResume = null;
this.onMainMenu = null;
this.onQuit = null;
this.menuActive = false;
this.controlsActive = false;
}
delay(ms) {
return new Promise(r => setTimeout(r, ms));
}
async showLoading(onStep) {
const steps = [
{ label: 'GENERATING TERRAIN...', duration: 600 },
{ label: 'BUILDING AIRPORT...', duration: 500 },
{ label: 'LOADING AIRCRAFT...', duration: 400 },
{ label: 'CALIBRATING INSTRUMENTS...', duration: 400 },
{ label: 'READY', duration: 300 },
];
for (let i = 0; i < steps.length; i++) {
const step = steps[i];
this.loadingMessage.textContent = step.label;
this.progressBar.style.width = `${((i + 1) / steps.length) * 100}%`;
if (onStep) onStep(i);
await this.delay(step.duration);
}
this.loadingScreen.style.display = 'none';
this.showMainMenu();
}
showMainMenu() {
this.mainMenu.style.display = 'flex';
this.currentMenuItem = 0;
this.updateMenuHighlight();
this.menuActive = true;
}
hideMainMenu() {
this.mainMenu.style.display = 'none';
this.menuActive = false;
}
handleMenuInput(key) {
if (!this.menuActive) return false;
if (key === 'ArrowUp' || key === 'ArrowDown') {
const items = this.menuItems;
if (key === 'ArrowUp') {
this.currentMenuItem = (this.currentMenuItem - 1 + items.length) % items.length;
} else {
this.currentMenuItem = (this.currentMenuItem + 1) % items.length;
}
this.updateMenuHighlight();
return true;
} else if (key === 'Enter' || key === ' ') {
const action = this.menuItems[this.currentMenuItem].dataset.action;
if (action === 'new-flight' && this.onNewFlight) this.onNewFlight();
else if (action === 'controls') this.showControls();
else if (action === 'quit' && this.onQuit) this.onQuit();
return true;
}
return false;
}
updateMenuHighlight() {
this.menuItems.forEach((item, i) => {
item.classList.toggle('selected', i === this.currentMenuItem);
});
}
showControls() {
this.controlsScreen.style.display = 'flex';
this.controlsActive = true;
}
hideControls() {
this.controlsScreen.style.display = 'none';
this.controlsActive = false;
}
handleControlsInput() {
if (!this.controlsActive) return false;
this.hideControls();
return true;
}
showPauseMenu() {
this.pauseMenu.style.display = 'flex';
this.currentPauseItem = 0;
this.updatePauseHighlight();
}
hidePauseMenu() {
this.pauseMenu.style.display = 'none';
}
handlePauseInput(key) {
if (this.pauseMenu.style.display === 'none') return false;
if (key === 'ArrowUp' || key === 'ArrowDown') {
const items = this.pauseItems;
if (key === 'ArrowUp') {
this.currentPauseItem = (this.currentPauseItem - 1 + items.length) % items.length;
} else {
this.currentPauseItem = (this.currentPauseItem + 1) % items.length;
}
this.updatePauseHighlight();
return true;
} else if (key === 'Enter' || key === ' ') {
const action = this.pauseItems[this.currentPauseItem].dataset.action;
if (action === 'resume' && this.onResume) this.onResume();
else if (action === 'main-menu' && this.onMainMenu) this.onMainMenu();
return true;
}
return false;
}
updatePauseHighlight() {
this.pauseItems.forEach((item, i) => {
item.classList.toggle('selected', i === this.currentPauseItem);
});
}
showQuitScreen() {
this.quitScreen.style.display = 'flex';
this.mainMenu.style.display = 'none';
}
}