monsterplex/src/scenes/LevelSelectScene.js

78 lines
2.6 KiB
JavaScript

import Phaser from 'phaser';
import { GAME_WIDTH, GAME_HEIGHT, WORLD_SCALE } from '../config.js';
import { LEVELS } from '../data/levels/index.js';
import { getLevelResult } from '../util/progress.js';
import { playMenuMusic } from '../util/music.js';
export default class LevelSelectScene extends Phaser.Scene {
constructor() {
super('LevelSelect');
}
create() {
this.cameras.main.setBackgroundColor('#8fc7e8');
playMenuMusic(this);
this.add.text(GAME_WIDTH / 2, 60 * WORLD_SCALE, 'SELECT LEVEL', {
fontFamily: 'monospace',
fontSize: `${32 * WORLD_SCALE}px`,
color: '#1a1f29',
fontStyle: 'bold',
}).setOrigin(0.5);
const cardWidth = 260 * WORLD_SCALE;
const cardHeight = 300 * WORLD_SCALE;
const gap = 30 * WORLD_SCALE;
const totalWidth = LEVELS.length * cardWidth + (LEVELS.length - 1) * gap;
const startX = GAME_WIDTH / 2 - totalWidth / 2 + cardWidth / 2;
const y = GAME_HEIGHT / 2 + 30 * WORLD_SCALE;
LEVELS.forEach((level, i) => {
const x = startX + i * (cardWidth + gap);
this._createCard(x, y, cardWidth, cardHeight, level);
});
const back = this.add.text(40 * WORLD_SCALE, GAME_HEIGHT - 40 * WORLD_SCALE, '< Menu', {
fontFamily: 'monospace',
fontSize: `${16 * WORLD_SCALE}px`,
color: '#1a1f29',
}).setInteractive({ useHandCursor: true });
back.on('pointerdown', () => this.scene.start('MainMenu'));
}
_createCard(x, y, width, height, level) {
const result = getLevelResult(level.id);
const bg = this.add.rectangle(x, y, width, height, 0x2255aa).setStrokeStyle(2 * WORLD_SCALE, 0x1a1f29);
bg.setInteractive({ useHandCursor: true });
bg.on('pointerover', () => bg.setFillStyle(0x2f6ac0));
bg.on('pointerout', () => bg.setFillStyle(0x2255aa));
bg.on('pointerdown', () => this.scene.start('Play', { levelId: level.id }));
this.add.text(x, y - height / 2 + 34 * WORLD_SCALE, level.name, {
fontFamily: 'monospace',
fontSize: `${20 * WORLD_SCALE}px`,
color: '#ffffff',
fontStyle: 'bold',
}).setOrigin(0.5);
this.add.text(x, y, level.description, {
fontFamily: 'monospace',
fontSize: `${13 * WORLD_SCALE}px`,
color: '#e8eef7',
align: 'center',
wordWrap: { width: width - 30 * WORLD_SCALE },
}).setOrigin(0.5);
const statusText = result
? `Best: ${result.kidsSaved}/${result.kidsTotal} kids saved`
: 'Not completed';
this.add.text(x, y + height / 2 - 30 * WORLD_SCALE, statusText, {
fontFamily: 'monospace',
fontSize: `${13 * WORLD_SCALE}px`,
color: result ? '#f2c14e' : '#c8d3e0',
}).setOrigin(0.5);
}
}