111 lines
3.4 KiB
JavaScript
111 lines
3.4 KiB
JavaScript
/**
|
|
* Einstiegspunkt des Frontends: liest die Server-URLs aus dem HTML, baut die
|
|
* gemeinsamen Dienste (Einstellungen, Audio, API) und startet Phaser.
|
|
* @module main
|
|
*/
|
|
|
|
import { GAME } from './config.js';
|
|
import { ERRORS } from './content/texts.js';
|
|
import { BootScene } from './scenes/BootScene.js';
|
|
import { BriefingScene } from './scenes/BriefingScene.js';
|
|
import { DisclaimerScene } from './scenes/DisclaimerScene.js';
|
|
import { GameOverScene } from './scenes/GameOverScene.js';
|
|
import { GameScene } from './scenes/GameScene.js';
|
|
import { HudScene } from './scenes/HudScene.js';
|
|
import { ControlsScene, CreditsScene, HighscoresScene } from './scenes/InfoScenes.js';
|
|
import { MenuScene } from './scenes/MenuScene.js';
|
|
import { PauseScene } from './scenes/PauseScene.js';
|
|
import { ApiClient } from './systems/ApiClient.js';
|
|
import { AudioManager } from './systems/AudioManager.js';
|
|
import { SafeStorage, Settings } from './systems/Settings.js';
|
|
|
|
|
|
/** @param {string} message */
|
|
function showBootError(message) {
|
|
const target = document.getElementById('boot-message');
|
|
if (target) {
|
|
target.textContent = message;
|
|
target.classList.add('boot-message--error');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Liest die vom Server gerenderten URLs (funktioniert auch unter einer Unter-URL).
|
|
* @param {HTMLElement} shell
|
|
*/
|
|
function readContext(shell) {
|
|
return {
|
|
staticBase: shell.dataset.staticBase ?? '/static/',
|
|
api: {
|
|
highscores: shell.dataset.apiHighscores ?? '/api/highscores',
|
|
runs: shell.dataset.apiRuns ?? '/api/runs',
|
|
},
|
|
disclaimerUrl: shell.dataset.disclaimerUrl ?? '/disclaimer',
|
|
};
|
|
}
|
|
|
|
function start() {
|
|
const shell = document.getElementById('game-shell');
|
|
if (!shell) return;
|
|
if (typeof window.Phaser === 'undefined') {
|
|
showBootError(ERRORS.phaserMissing);
|
|
return;
|
|
}
|
|
|
|
const context = readContext(shell);
|
|
const settings = new Settings(SafeStorage.forBrowser());
|
|
const services = {
|
|
settings,
|
|
audio: new AudioManager(settings, { staticBase: context.staticBase }),
|
|
api: new ApiClient(context.api),
|
|
};
|
|
// Klangdateien schon jetzt als Bytes laden; dekodiert wird nach der ersten Interaktion.
|
|
services.audio.preload();
|
|
|
|
const game = new Phaser.Game({
|
|
type: Phaser.AUTO,
|
|
parent: 'game',
|
|
width: GAME.width,
|
|
height: GAME.height,
|
|
backgroundColor: GAME.backgroundColor,
|
|
banner: false,
|
|
// Rechtsklick soll kein Browser-Kontextmenü über dem Spiel öffnen.
|
|
disableContextMenu: true,
|
|
scale: { mode: Phaser.Scale.FIT, autoCenter: Phaser.Scale.CENTER_BOTH },
|
|
physics: { default: 'arcade', arcade: { debug: false } },
|
|
// Ton übernimmt der eigene AudioManager (Kanäle, Synthesizer, Musik). Ohne diese
|
|
// Einstellung würde Phaser zusätzlich einen eigenen AudioContext anlegen.
|
|
audio: { noAudio: true },
|
|
// Reihenfolge = Zeichenreihenfolge: HUD und Pause liegen über dem Spiel.
|
|
scene: [
|
|
BootScene,
|
|
MenuScene,
|
|
DisclaimerScene,
|
|
BriefingScene,
|
|
GameScene,
|
|
HudScene,
|
|
PauseScene,
|
|
GameOverScene,
|
|
HighscoresScene,
|
|
ControlsScene,
|
|
CreditsScene,
|
|
],
|
|
callbacks: {
|
|
preBoot: (g) => {
|
|
g.registry.set('context', context);
|
|
g.registry.set('services', services);
|
|
},
|
|
},
|
|
});
|
|
|
|
// Für End-to-End-Tests und Fehlersuche in der Browser-Konsole.
|
|
window.gloryDefense = game;
|
|
}
|
|
|
|
try {
|
|
start();
|
|
} catch (error) {
|
|
console.error(error);
|
|
showBootError(ERRORS.generic);
|
|
}
|