space-game/src/ui/screens/preloader.ts
Michael Mainguy dfa46c85a6
All checks were successful
Build / build (push) Successful in 1m0s
Hide canvas until XR camera positioned in ship cockpit
- Hide #gameCanvas by default in CSS (display: none)
- Show canvas in setupXRCamera() after camera is parented to ship
- Show canvas in flat mode fallback paths
- Fix preloader to append to document.body (was hidden with #levelSelect)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 05:42:53 -06:00

132 lines
4.0 KiB
TypeScript

/**
* 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 = `
<div class="preloader-content">
<h1 class="preloader-title">
🚀 Space Combat VR
</h1>
<div id="preloaderStatus" class="preloader-status">
Initializing...
</div>
<div class="preloader-progress-container">
<div id="preloaderProgress" class="preloader-progress"></div>
</div>
<button id="preloaderStartBtn" class="preloader-button">
Start Game
</button>
<div class="preloader-info">
<p>Initializing game engine... Assets will load when you select a level.</p>
</div>
</div>
`;
// 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;
}
}