Пошаговые битвы элементалей
Общее описание
Модуль "Пошаговые битвы элементалей" реализует основную игровую механику, где игрок выбирает локацию, элемент и конкретного элементаля для сражения, после чего проходит пошаговый бой с визуальными анимациями и отображением результатов. Эта часть отвечает за управление фазами игры, взаимодействие с пользователем при подготовке к бою и демонстрацию анимаций и итогов поединка.
Данный модуль решает задачи:
Организации пошагового процесса подготовки и начала битвы;
Отображения анимаций сражения с элементалями;
Отображения подробных результатов боя;
Обеспечения удобной навигации как через UI, так и с клавиатуры;
Интеграции с бизнес-логикой, реализованной в
gameLogic.ts.
Структура и взаимодействие компонентов
Пошаговые битвы реализованы через три основных React-компонента:
BattleComponent.tsx — отвечает за этапы выбора: локации, элемента, элементаля, навигацию между ними и обработку пользовательских действий.
BattleAnimationPixi.tsx — визуализирует сам бой с помощью анимаций, построенных на базе PixiJS.
BattleResultPage.tsx — отображает итоговый результат боя с подробной статистикой.
Все эти компоненты получают и передают данные через пропсы, взаимодействуя с состоянием игры (gameState), а бизнес-логика и игровые правила сосредоточены в gameLogic.ts.
Взаимодействие можно представить так:
flowchart LR
A[BattleComponent] -->|Выбор локации, элемента, элементаля| B[gameLogic.ts]
A -->|Запуск боя| C[BattleAnimationPixi]
C -->|Окончание анимации| D[BattleResultPage]
D -->|Возврат в меню| A
B -->|Расчёт результатов боя| D
Этапы и ключевая функциональность
1. Выбор и подготовка боя (BattleComponent.tsx)
Компонент BattleComponent управляет несколькими фазами игры:
menu (выбор локации) — пользователь выбирает арену для боя из доступных локаций с учетом маны; кнопки имеют подсказки и индикацию доступности.
elementSelection (выбор элемента) — выбор стихии (земля, вода, огонь), которая определит характеристики боя.
elementalSelection (выбор элементаля) — выбор конкретного персонажа-элементаля из коллекции игрока для защиты в бою; учитываются кулдауны (временные ограничения на использование).
Компонент поддерживает удобную навигацию с клавиатуры (стрелки, Enter, Backspace, Escape), а также управляет состояниями фокуса и подсказок для повышения UX.
Важные особенности:
Во время выбора элементаля создаётся «статический снимок» кулдаунов, чтобы не вызывать лишних ререндеров и не ломать туториал.
Обработка событий туториала через глобальные события для синхронизации прогресса обучения.
Поддержка ARIA-атрибутов для доступности интерфейса.
Фрагмент для выбора локации иллюстрирует работу с кнопками и подсказками:
{locations.map(([key, location], index) => {
const isAffordable = canAffordLocation(player.mana, key as Location);
return (
<button
key={key}
disabled={!isAffordable}
onClick={() => isAffordable && onSelectLocation(key as Location)}
aria-label={`${location.name} location, ${location.mana} mana cost${!isAffordable ? ', insufficient mana' : ''}`}
...
>
{location.emoji} {location.name} - {location.mana} Mana
{!isAffordable && <small>Need {location.mana - player.mana} more mana</small>}
</button>
);
})}
2. Анимация и эффекты боя (BattleAnimationPixi.tsx и BattleEffects.tsx)
BattleAnimationPixi отвечает за визуализацию битвы, реализованную с использованием PixiJS, что позволяет создавать плавные и эффектные 2D-анимации.
Основные этапы анимации:
intro — вступительный экран с заголовком и настройкой композиции.
cards — показ карт игроков с их стихиями.
elementals — появление и бой элементалей (если выбраны).
result — показ результата боя с соответствующими эффектами и сообщениями.
Внутри фазы elementals выделены подфазы — поочередное появление игрока и оппонента, бой и объявление победителя.
Компонент также адаптируется под мобильные устройства, снижая количество частиц и упрощая эффекты для производительности.
Компонент BattleEffects добавляет элементно-специфичные визуальные эффекты (огонь, вода, земля) поверх анимации битвы:
Энергетические волны, искры, частицы и кристаллы.
Оптимизация под разные размеры экрана и устройства.
Пример создания эффекта искр для огня в BattleEffects:
const createSparkle = () => {
const sparkle = new PIXI.Graphics();
sparkle.beginFill(colors.secondary);
// Форма звезды или ромба в зависимости от устройства
sparkle.drawPolygon(points);
sparkle.endFill();
...
const animate = () => {
sparkle.y -= moveSpeed;
sparkle.alpha -= alphaSpeed;
sparkle.rotation += rotationSpeed;
if (sparkle.alpha <= 0 || sparkle.y < -20) {
app.stage.removeChild(sparkle);
sparkle.destroy();
} else {
requestAnimationFrame(animate);
}
};
animate();
};
3. Отображение результатов (BattleResultPage.tsx)
После завершения анимаций вызывается BattleResultPage, отображающий:
Итог боя: победа, поражение или ничья с соответствующим визуальным оформлением.
Изменение ресурсов игрока (мана, серия побед и т.п.).
Подробный боевой журнал с элементами и использованными элементалями.
Итоговые расчёты изменения маны с учётом защиты элементалей.
Компонент использует данные из gameState.battleLog и gameState.currentOpponent, получая подробности боя из бизнес-логики.
Пример отображения изменения маны:
<span className={`results-stat-value ${isVictory ? 'victory' : isDefeat ? 'defeat' : 'primary'}`}>
{battleLog.baseWager === 0 ? 'No change (free)' : `${battleLog.finalChange > 0 ? '+' : ''}${battleLog.finalChange}`}
</span>
Взаимодействие с бизнес-логикой (gameLogic.ts)
Вся логика определения правил боя и результатов сосредоточена в модуле gameLogic.ts. Он включает:
Константы с элементами, локациями, типами и редкостями элементалей.
Функции генерации противников (
generateOpponent).Функции расчёта победителя по стихиям (
getWinner).Логику вычисления итогового изменения ресурсов с учётом защиты элементалей (
calculateBattleResult).
Например, функция определения победителя по стихиям реализована так:
export const getWinner = (element1: Element, element2: Element): BattleResult => {
if (element1 === element2) return 'draw';
const winConditions: Record<Element, Element> = {
earth: 'water', // Земля поглощает воду
water: 'fire', // Вода тушит огонь
fire: 'earth', // Огонь сжигает землю
};
return winConditions[element1] === element2 ? 'player' : 'opponent';
};
Расчёт результата с учётом защиты элементалей:
export const calculateBattleResult = (
baseWager: number,
playerElement: Element,
playerElemental: ElementalRarity | null,
opponentElement: Element,
opponentElemental: ElementalRarity | null,
playerCollection?: ElementalCollection
): {
playerManaChange: number;
opponentManaChange: number;
winner: BattleResult;
protectionSaved: number;
} => {
...
// Логика вычисления итогов с учётом защиты
};
Таким образом, компоненты пользовательского интерфейса делегируют ключевые вычисления и принятие решений этому модулю, обеспечивая разделение ответственности и удобство поддержки.
Визуальная структура взаимодействия компонентов битвы
sequenceDiagram
participant User as Игрок
participant BattleComp as BattleComponent
participant GameLogic as gameLogic.ts
participant BattleAnim as BattleAnimationPixi
participant BattleResult as BattleResultPage
User->>BattleComp: Выбрать локацию
BattleComp->>GameLogic: Проверить доступность локации
BattleComp->>User: Показать выбор элемента
User->>BattleComp: Выбрать элемент
BattleComp->>User: Показать выбор элементаля
User->>BattleComp: Выбрать элементаля
BattleComp->>BattleAnim: Запустить анимацию боя
BattleAnim->>GameLogic: Запросить данные боя
BattleAnim->>User: Показать анимацию сражения
BattleAnim->>BattleComp: Сообщить о завершении анимации
BattleComp->>BattleResult: Показать результаты боя
User->>BattleResult: Нажать "Бой снова" или "В меню"
BattleResult->>BattleComp: Возврат к выбору
Итог
Модуль "Пошаговые битвы элементалей" объединяет пользовательский интерфейс и визуализацию с бизнес-логикой игры, формируя интерактивный процесс подготовки, проведения и отображения битв. Его архитектура обеспечивает плавный пользовательский опыт, доступность, поддержку туториалов и адаптацию под разные устройства. Взаимодействие между BattleComponent, BattleAnimationPixi, BattleEffects, BattleResultPage и gameLogic.ts позволяет создать цельный и расширяемый функционал пошаговых боёв.