154 lines
4.7 KiB
JavaScript
154 lines
4.7 KiB
JavaScript
import { System } from '../core/System.js';
|
|
import { PixelFont } from '../core/PixelFont.js';
|
|
import { Palette } from '../core/Palette.js';
|
|
import { GameState, ComponentType, SystemName } from '../core/Constants.js';
|
|
|
|
/**
|
|
* System to handle game menus (start, pause)
|
|
*/
|
|
export class MenuSystem extends System {
|
|
constructor(engine) {
|
|
super(SystemName.MENU);
|
|
this.requiredComponents = []; // No required components
|
|
this.priority = 1; // Run early
|
|
this.engine = engine;
|
|
this.ctx = engine.ctx;
|
|
this.gameState = GameState.START;
|
|
this.paused = false;
|
|
}
|
|
|
|
init(engine) {
|
|
super.init(engine);
|
|
this.setupInput();
|
|
}
|
|
|
|
setupInput() {
|
|
window.addEventListener('keydown', (e) => {
|
|
if (e.key === 'Escape' || e.key === 'p' || e.key === 'P') {
|
|
if (this.gameState === GameState.PLAYING) {
|
|
this.togglePause();
|
|
}
|
|
}
|
|
if (e.key === 'Enter' || e.key === ' ') {
|
|
if (this.gameState === GameState.START) {
|
|
this.startGame();
|
|
} else if (this.gameState === GameState.PAUSED) {
|
|
this.resumeGame();
|
|
} else if (this.gameState === GameState.GAME_OVER) {
|
|
this.restartGame();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
showGameOver() {
|
|
this.gameState = GameState.GAME_OVER;
|
|
this.paused = true;
|
|
}
|
|
|
|
restartGame() {
|
|
window.location.reload(); // Simple and effective for this project
|
|
}
|
|
|
|
startGame() {
|
|
this.gameState = GameState.PLAYING;
|
|
this.paused = false;
|
|
if (!this.engine.running) {
|
|
this.engine.start();
|
|
}
|
|
}
|
|
|
|
togglePause() {
|
|
if (this.gameState === GameState.PLAYING) {
|
|
this.gameState = GameState.PAUSED;
|
|
this.paused = true;
|
|
} else if (this.gameState === GameState.PAUSED) {
|
|
this.resumeGame();
|
|
}
|
|
}
|
|
|
|
resumeGame() {
|
|
this.gameState = GameState.PLAYING;
|
|
this.paused = false;
|
|
}
|
|
|
|
process(_deltaTime, _entities) {
|
|
// Don't update game systems if paused or at start menu
|
|
if (this.gameState === GameState.PAUSED || this.gameState === GameState.START) {
|
|
// Logic for system handling is moved to the update loop in Engine
|
|
}
|
|
}
|
|
|
|
drawMenu() {
|
|
const ctx = this.ctx;
|
|
const width = this.engine.canvas.width;
|
|
const height = this.engine.canvas.height;
|
|
|
|
// Darker overlay matching palette
|
|
ctx.fillStyle = 'rgba(32, 21, 51, 0.8)'; // Semi-transparent VOID
|
|
ctx.fillRect(0, 0, width, height);
|
|
|
|
if (this.gameState === GameState.START) {
|
|
const title = 'SLIME GENESIS';
|
|
const titleW = PixelFont.getTextWidth(title, 2);
|
|
PixelFont.drawText(ctx, title, (width - titleW) / 2, height / 2 - 40, Palette.CYAN, 2);
|
|
|
|
const start = 'PRESS ENTER TO START';
|
|
const startW = PixelFont.getTextWidth(start, 1);
|
|
PixelFont.drawText(ctx, start, (width - startW) / 2, height / 2, Palette.WHITE, 1);
|
|
|
|
const instructions = [
|
|
'WASD: MOVE | CLICK: ATTACK',
|
|
'NUMS: SKILLS | ESC: PAUSE',
|
|
'COLLECT DNA TO EVOLVE'
|
|
];
|
|
|
|
instructions.forEach((line, i) => {
|
|
const lineW = PixelFont.getTextWidth(line, 1);
|
|
PixelFont.drawText(ctx, line, (width - lineW) / 2, height / 2 + 25 + i * 10, Palette.ROYAL_BLUE, 1);
|
|
});
|
|
|
|
} else if (this.gameState === GameState.PAUSED) {
|
|
const paused = 'PAUSED';
|
|
const pausedW = PixelFont.getTextWidth(paused, 2);
|
|
PixelFont.drawText(ctx, paused, (width - pausedW) / 2, 20, Palette.SKY_BLUE, 2);
|
|
|
|
const resume = 'PRESS ENTER TO RESUME';
|
|
const resumeW = PixelFont.getTextWidth(resume, 1);
|
|
PixelFont.drawText(ctx, resume, (width - resumeW) / 2, 45, Palette.WHITE, 1);
|
|
|
|
// Draw Stats and Knowledge (Moved from HUD)
|
|
const player = this.engine.getEntities().find(e => e.hasComponent(ComponentType.EVOLUTION));
|
|
const uiSystem = this.engine.systems.find(s => s.name === SystemName.UI);
|
|
|
|
if (player && uiSystem) {
|
|
// Draw Stats on the left
|
|
uiSystem.drawStats(player, 20, 80);
|
|
|
|
// Draw Learning Progress on the right
|
|
uiSystem.drawSkillProgress(player, width - 110, 80);
|
|
}
|
|
} else if (this.gameState === GameState.GAME_OVER) {
|
|
const dead = 'YOU PERISHED';
|
|
const deadW = PixelFont.getTextWidth(dead, 2);
|
|
PixelFont.drawText(ctx, dead, (width - deadW) / 2, height / 2 - 30, Palette.WHITE, 2);
|
|
|
|
const sub = 'YOUR DNA SUSTAINS THE CYCLE';
|
|
const subW = PixelFont.getTextWidth(sub, 1);
|
|
PixelFont.drawText(ctx, sub, (width - subW) / 2, height / 2 - 5, Palette.ROYAL_BLUE, 1);
|
|
|
|
const restart = 'PRESS ENTER TO REBORN';
|
|
const restartW = PixelFont.getTextWidth(restart, 1);
|
|
PixelFont.drawText(ctx, restart, (width - restartW) / 2, height / 2 + 30, Palette.CYAN, 1);
|
|
}
|
|
}
|
|
|
|
getGameState() {
|
|
return this.gameState;
|
|
}
|
|
|
|
isPaused() {
|
|
return this.paused || this.gameState === GameState.START;
|
|
}
|
|
}
|
|
|