BattleComponent.tsx
Обзор
Файл BattleComponent.tsx реализует ключевой React-компонент, управляющий интерфейсом выбора и подготовки к пошаговой битве в игре с элементалями. Он отвечает за последовательные этапы:
выбор локации для боя,
выбор боевого элемента (стихии),
выбор конкретного элементаля из коллекции игрока.
Компонент обеспечивает удобную навигацию как с помощью мыши, так и клавиатуры, поддерживает отображение подсказок и статусов (например, кулдаун элементалей), а также интегрируется с системой обучения (туториалом).
Основная задача компонента — предоставить игроку интуитивно понятный и доступный UI для подготовки к бою, с учетом ограничений по ресурсам (мана) и состоянию персонажей.
Описание и разбор компонентов
BattleComponentProps
Интерфейс пропсов компонента:
Свойство | Тип | Описание |
|---|---|---|
|
| Текущее состояние игры, включая данные игрока, текущую фазу и коллекции элементалей. |
|
| Обработчик выбора локации боя. |
| Обработчик выбора элемента (стихии). | |
| [(elemental: ElementalRarity \ | null) => void](/projects/320/74719) |
| Возврат к выбору локации (этап назад). | |
| Возврат к выбору элемента (этап назад). | |
|
| Запуск поиска соперника (используется для совместимости). |
|
| Запуск боя после выбора элементаля. |
|
| Возврат в главное меню. |
BattleComponent (React.FC)
Основной React-функциональный компонент, управляющий всеми тремя фазами выбора: локации, элемента, элементаля.
Локальное состояние (useState)
focusedIndex: number— индекс текущего фокуса для навигации клавиатурой.showTooltip: string | null— ключ элемента/локации для отображения всплывающей подсказки.cooldownUpdateTrigger: number— счетчик для принудительного обновления компонента каждую секунду (для обновления кулдаунов).showFocusOutlines: boolean— флаг отображения визуальных фокусов, отключается после прохождения туториала.staticCooldownSnapshot: Record<string, boolean>— статический снимок статусов кулдауна элементалей во время фазы выбора элементаля, чтобы избежать лишних перерисовок.
Важные эффекты (useEffect)
Обновление кулдаунов: каждую секунду обновляет
cooldownUpdateTrigger, если не в фазе выбора элементаля.Снимок кулдаунов: при входе в фазу выбора элементаля создаёт снимок текущих кулдаунов для предотвращения мерцания UI.
Отслеживание состояния туториала: читает локальные настройки туториала, отключает визуальные акценты после его завершения.
Обработка событий туториала: слушает глобальные события
battleTutorialCompletedиtutorialStartBattleдля синхронизации состояния UI с обучением.Уведомление туториала о готовности выбора элементаля: при входе в фазу выбора элементаля и наличии подходящих элементалей отправляет событие
elementalSelectionReady.
Функция handleKeyDown
Универсальный обработчик клавиатурной навигации для списков с поддержкой стрелок, выбора, возврата и отмены. Обеспечивает:
Перемещение фокуса стрелками вверх/вниз/влево/вправо.
Выбор элемента по Enter/пробелу.
Возврат на предыдущий этап по Backspace.
Сброс подсказок по Escape.
Опционально блокирует смену фокуса во время туториала.
Основные методы рендера фаз
1. renderLocationSelection()
Отображает выбор локации боя:
Показывает доступные локации из константы
LOCATIONS.Кнопки блокируются, если у игрока недостаточно маны.
При наведении и фокусе отображаются подсказки.
Имеется индикатор текущего шага (1 из 3).
Поддерживается клавиатурная навигация через useEffect.
Использование:
{gamePhase === 'menu' && renderLocationSelection()}
2. renderElementSelection()
Отображает выбор элемента (стихии):
Показывает три элемента: земля, вода, огонь (из
ELEMENTS).Кнопки запускают
onSelectElementиonStartMatchmaking.Подсказки с описаниями элементов.
Индикатор шага (2 из 3).
Клавиатурная навигация с фокусом по умолчанию на огонь.
Кнопка "Назад" возвращает к выбору локации.
Использование:
{gamePhase === 'elementSelection' && renderElementSelection()}
3. renderElementalSelection()
Отображает выбор конкретного элементаля из коллекции игрока с учетом выбранного элемента:
Получает коллекцию элементалей игрока, принадлежащих выбранной стихии.
Показывает кнопку "Без элементаля" (бой без защиты).
Для каждого элементаля отображается карточка с информацией о редкости, уровне, защите, кулдауне.
Кулдаун отображается в режиме обратного отсчёта.
Кнопки блокируются, если элементаль на кулдауне, кроме случая туториала.
Индикатор шага (3 из 3).
Поддержка клавиатурной навигации с фиксацией фокуса во время туториала.
Если элементалей нет, показывается сообщение с подсказкой и кнопкой возврата к выбору элемента.
Использование:
{gamePhase === 'elementalSelection' && renderElementalSelection()}
Важные детали реализации
Статический снимок кулдаунов во время выбора элементаля предотвращает повторные перерисовки и мерцание UI, что особенно важно для корректной работы туториала.
Использование
cooldownUpdateTriggerдля обновления таймера кулдаунов каждую секунду без излишних ререндеров.События глобального окна (
window.addEventListener) используются для интеграции с системой обучения.Поддержка accessibility (ARIA-атрибутов) для улучшенного взаимодействия с ассистивными технологиями.
Кнопки имеют детальные описания и подсказки для лучшего UX.
При загрузке изображений элементалей реализован fallback на эмодзи, если картинка не загрузилась.
Используются CSS-переменные и стили для визуализации редкостей и состояний (например, подсветка, масштабирование при фокусе).
Навигация клавиатурой учитывает блокировку смены фокуса во время туториала для предотвращения случайных действий.
Взаимодействие с другими частями системы
Использует бизнес-логику и константы из модуля
gameLogic.ts:ELEMENTS,LOCATIONS— данные стихий и локаций.Функции
canAffordLocation,isElementalOnCooldown,getElementalCooldownRemaining,getElementalData— для проверки доступности, состояний кулдаунов и получения характеристик элементалей.
Передает выбранные данные в родительский компонент или глобальный менеджер состояния через обработчики
onSelectLocation,onSelectElement,onSelectElemental,onStartBattle, и т.д.После выбора элементаля и запуска боя управление переходит в компонент анимации боя (
BattleAnimationPixi.tsx).Интегрируется с системой обучения через глобальные события.
Обеспечивает плавный переход между фазами подготовки боя, синхронизируя UI с состоянием игры (
gamePhase).
Примеры использования
Пример выбора локации
<button
disabled={!canAffordLocation(player.mana, key as Location)}
onClick={() => canAffordLocation(player.mana, key as Location) && onSelectLocation(key as Location)}
aria-label={`${location.name} location, ${location.mana} mana cost${!isAffordable ? ', insufficient mana' : ''}`}
>
{location.emoji} {location.name} — {location.mana} Маны
{!isAffordable && <small>Нужно {location.mana - player.mana} маны</small>}
</button>
Пример выбора элементаля с учётом кулдауна
<button
disabled={isOnCooldown && !showFocusOutlines}
onClick={() => {
if (!isOnCooldown || showFocusOutlines) {
onSelectElemental(elemental.rarity);
setTimeout(() => onStartBattle(), 100);
}
}}
aria-label={`${elementalData.name}, ${elementalData.rarity} редкости, уровень ${elemental.level}, защита ${protection}%, ${isOnCooldown ? `на кулдауне ${cooldownText}` : 'нажмите для начала боя'}`}
>
{/* Содержание карточки элементаля */}
</button>
Mermaid диаграмма — структура компонента
classDiagram
class BattleComponent {
- gameState: GameState
- focusedIndex: number
- showTooltip: string | null
- cooldownUpdateTrigger: number
- showFocusOutlines: boolean
- staticCooldownSnapshot: Record<string, boolean>
+ renderLocationSelection()
+ renderElementSelection()
+ renderElementalSelection()
+ handleKeyDown(e: KeyboardEvent, items: T[], onSelect: (item: T) => void, onBack?: () => void)
+ getElementDescription(element: Element): string
+ getLocationTooltip(location: Location): string
+ useEffect() — несколько эффектов для управления состоянием и событиями
+ JSX.Render()
}
Итог
BattleComponent.tsx — центральный элемент пользовательского интерфейса подготовки к пошаговой битве. Он объединяет бизнес-логику, UX-решения и взаимодействие с пользователем, обеспечивая последовательный и понятный процесс выбора локации, элемента и элементаля. Благодаря продуманной архитектуре и поддержке клавиатурной навигации, а также интеграции с системой обучения, компонент способствует удобству и вовлечённости игроков, плавно передавая управление в визуализацию боя и последующий результат.