/**
* Preloader UI - Shows loading progress and start button
*/
export class Preloader {
private container: HTMLElement | null = null;
private progressBar: HTMLElement | null = null;
private statusText: HTMLElement | null = null;
private startButton: HTMLElement | null = null;
private onStartCallback: (() => void) | null = null;
constructor() {
this.createUI();
}
private createUI(): void {
// Create preloader container
this.container = document.createElement('div');
this.container.className = 'preloader';
this.container.innerHTML = `
🚀 Space Combat VR
Initializing...
Initializing game engine... Assets will load when you select a level.
`;
// Append to body so it's visible even when other UI elements are hidden
document.body.appendChild(this.container);
// Get references
this.progressBar = document.getElementById('preloaderProgress');
this.statusText = document.getElementById('preloaderStatus');
this.startButton = document.getElementById('preloaderStartBtn');
// Add start button click handler
if (this.startButton) {
this.startButton.addEventListener('click', () => {
if (this.onStartCallback) {
this.onStartCallback();
}
});
}
}
/**
* Update loading progress
* @param percent - Progress from 0 to 100
* @param message - Status message to display
*/
public updateProgress(percent: number, message: string): void {
if (this.progressBar) {
this.progressBar.style.width = `${Math.min(100, Math.max(0, percent))}%`;
}
if (this.statusText) {
this.statusText.textContent = message;
}
}
/**
* Show the start button when loading is complete
* @param onStart - Callback to invoke when user clicks start
*/
public showStartButton(onStart: () => void): void {
this.onStartCallback = onStart;
if (this.statusText) {
this.statusText.textContent = 'All systems ready!';
}
if (this.progressBar) {
this.progressBar.style.width = '100%';
}
if (this.startButton) {
this.startButton.style.display = 'block';
// Animate button appearance
this.startButton.style.opacity = '0';
this.startButton.style.transform = 'translateY(20px)';
setTimeout(() => {
if (this.startButton) {
this.startButton.style.transition = 'opacity 0.5s ease, transform 0.5s ease';
this.startButton.style.opacity = '1';
this.startButton.style.transform = 'translateY(0)';
}
}, 100);
}
}
/**
* Hide and remove the preloader
*/
public hide(): void {
if (this.container) {
this.container.style.transition = 'opacity 0.5s ease';
this.container.style.opacity = '0';
setTimeout(() => {
if (this.container && this.container.parentElement) {
this.container.remove();
}
}, 500);
}
}
/**
* Check if preloader exists
*/
public isVisible(): boolean {
return this.container !== null && this.container.parentElement !== null;
}
}