миграция на pixi
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
import { autorun } from 'mobx';
|
||||
import type { GameStore } from '../game/GameStore';
|
||||
import type { Mounted } from './Topbar';
|
||||
|
||||
/** Russian plural agreement for "день" (day) after a count. */
|
||||
function dayWord(n: number): string {
|
||||
const mod10 = n % 10;
|
||||
const mod100 = n % 100;
|
||||
if (mod10 === 1 && mod100 !== 11)
|
||||
return 'день';
|
||||
if (mod10 >= 2 && mod10 <= 4 && (mod100 < 12 || mod100 > 14))
|
||||
return 'дня';
|
||||
return 'дней';
|
||||
}
|
||||
|
||||
/** Builds the "КРОВАВАЯ ЛУНА!" banner and the death screen, both absolutely positioned over the
|
||||
* game map (siblings of the Pixi canvas — see App.ts) — the DOM-side replacement for the
|
||||
* corresponding pieces of GameMap.tsx. Both stay hidden/empty until the store says otherwise, kept
|
||||
* in sync via a single mobx autorun. */
|
||||
export function createGameOverlays(store: GameStore, onDeath: () => void): Mounted {
|
||||
const root = document.createElement('div');
|
||||
root.className = 'game-overlays';
|
||||
|
||||
const banner = document.createElement('div');
|
||||
banner.className = 'blood-moon-banner';
|
||||
banner.textContent = 'КРОВАВАЯ ЛУНА!';
|
||||
banner.hidden = true;
|
||||
|
||||
const gameOver = document.createElement('div');
|
||||
gameOver.className = 'game-over-overlay';
|
||||
gameOver.hidden = true;
|
||||
|
||||
const message = document.createElement('div');
|
||||
message.className = 'game-over-overlay__message';
|
||||
|
||||
const stats = document.createElement('div');
|
||||
stats.className = 'game-over-overlay__stats';
|
||||
const distance = document.createElement('div');
|
||||
const chopped = document.createElement('div');
|
||||
const caught = document.createElement('div');
|
||||
const coins = document.createElement('div');
|
||||
stats.append(distance, chopped, caught, coins);
|
||||
|
||||
const menuBtn = document.createElement('button');
|
||||
menuBtn.type = 'button';
|
||||
menuBtn.className = 'menu-btn';
|
||||
// The whole map underneath (including this overlay) has a pointerdown handler that captures the
|
||||
// pointer and drives character movement — without stopping it here, that handler fires first on
|
||||
// bubble-up and swallows the tap before it becomes a click (see GameCanvas).
|
||||
menuBtn.addEventListener('pointerdown', (e) => e.stopPropagation());
|
||||
menuBtn.addEventListener('click', onDeath);
|
||||
menuBtn.textContent = 'В меню';
|
||||
|
||||
gameOver.append(message, stats, menuBtn);
|
||||
root.append(banner, gameOver);
|
||||
|
||||
const dispose = autorun(() => {
|
||||
banner.hidden = !store.bloodMoonBannerVisible;
|
||||
|
||||
gameOver.hidden = !store.isDead;
|
||||
if (!store.isDead)
|
||||
return;
|
||||
message.textContent = `Вы прожили ${store.day} ${dayWord(store.day)}, но вас поймали кролики`;
|
||||
distance.textContent = `Пройдено: ${Math.round(store.character.distanceTraveled)} px`;
|
||||
chopped.textContent = `Срублено: ${store.treesChoppedCount} деревьев, ${store.bushesChoppedCount} кустов`;
|
||||
caught.textContent = `Поймано кроликов: ${store.rabbitsCaughtCount}`;
|
||||
coins.textContent = `Заработано монет: ${store.totalCoinsEarned.toFixed(1)}`;
|
||||
});
|
||||
|
||||
return { el: root, dispose };
|
||||
}
|
||||
Reference in New Issue
Block a user