sea-battle/DOCUMENTATION.md
2026-01-09 08:45:22 +03:00

854 lines
22 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Документация игры "Морской бой"
## Оглавление
1. [Обзор проекта](#обзор-проекта)
2. [Архитектура игры](#архитектура-игры)
3. [Игровые режимы](#игровые-режимы)
4. [Основные системы](#основные-системы)
5. [Управление и ввод](#управление-и-ввод)
6. [Искусственный интеллект](#искусственный-интеллект)
7. [Система призов](#система-призов)
8. [Настройки](#настройки)
9. [Звук и визуальные эффекты](#звук-и-визуальные-эффекты)
10. [Структура проекта](#структура-проекта)
---
## Обзор проекта
**Sea Battle** - это аркадная игра "Морской бой" для Unity, разработанная для работы с аппаратным обеспечением через COM-порт. Игра поддерживает как одиночный режим против AI, так и многопользовательский режим (два игрока).
### Ключевые особенности:
- ? Два режима игры: против бота и против другого игрока
- ? 6 уровней сложности AI с прогрессивной системой
- ? Интегрированная система выдачи призов (монеты, билеты, спецпризы)
- ? Динамическая смена окружения (день/ночь)
- ? Уникальные голосовые профили для каждого противника
- ? Монетная система через COM-порт
- ?? Расширенная система настроек
- ? Генерация QR-кодов для связи (Telegram/WhatsApp)
---
## Архитектура игры
### Основные состояния (GameState)
```csharp
public enum GameState
{
MainMenu, // Главное меню
ShipPlacement, // Расстановка кораблей
BotPlacement, // Расстановка кораблей ботом
Playing, // Игровой процесс
GameOver, // Конец игры
Setting, // Настройки
Invite, // Приглашение игрока
Input, // Ввод данных
Prize, // Экран приза
CharacterSetting // Настройка персонажа
}
```
### Режимы управления (InputMode)
```csharp
public enum InputMode
{
UI, // Интерфейс меню
Settings, // Навигация в настройках
ShipPlacement, // Расстановка кораблей
Battle // Боевой режим
}
```
### Центральный менеджер - GameManager
`GameManager` - главный управляющий класс игры, отвечает за:
- Переключение состояний игры
- Управление ходами игроков
- Контроль победных условий
- Инициализацию AI
- Взаимодействие с противником
- Управление камерой
- Таймер бездействия (360 секунд по умолчанию)
**События:**
```csharp
public static event Action<int, int> OnInviteSent; // Приглашение отправлено
public static event Action<int, bool, GameMode> OnReady; // Игрок готов
public event Action<InputMode> OnInputModeChanged; // Режим ввода изменен
```
---
## Игровые режимы
### 1. Режим "Игрок против Бота" (PlayerVsBot)
**Процесс игры:**
1. Игрок вносит оплату (`ComWrapper.Pay()`)
2. Расстановка кораблей игроком
3. Автоматическая расстановка кораблей ботом
4. Пошаговая битва
5. Выдача приза при победе (если настройка включена)
**Прогрессия сложности:**
- Level 1-4: Последовательное повышение
- Level 5: Активируется система шансов (DifficultyManager)
- Level 6: "Непобедимый" режим
### 2. Режим "Игрок против Игрока" (PlayerVsPlayer)
**Процесс игры:**
1. Первый игрок отправляет приглашение
2. Второй игрок принимает приглашение
3. Оба игрока расставляют корабли
4. Поочередная битва
5. Возврат средств при выходе в меню
---
## Основные системы
### Система игрового поля (GamePole)
**Ключевые функции:**
```csharp
public class GamePole : MonoBehaviour
{
public GameObject[,] Pole; // 10x10 сетка клеток
public int[,] PoleShot; // 0-не стреляли, 1-промах, 2-попал, 3-потоплен
public int[,] FreePole; // Для размещения кораблей
public bool Shot(int x, int y); // Выстрел по координатам
public void ArrangeShip(); // Авторасстановка кораблей
public void ClearPole(); // Очистка поля
public void CopyShipsFrom(GamePole source, bool hideShips); // Копирование кораблей
}
```
**Размещение кораблей:**
- 1x четырёхпалубный
- 2x трёхпалубных
- 3x двухпалубных
- 4x однопалубных
- **Всего: 10 кораблей**
### Система кораблей (Ship)
**Компоненты:**
```csharp
public class Ship : MonoBehaviour
{
public List<GameObject> decks; // Палубы корабля
public List<Vector2Int> deckCoords; // Координаты на поле
public ParticleSystem[] explosionPrefabs; // Эффекты взрыва
public GameObject[] debrisPrefabs; // Обломки
public Transform mastsContainer; // Мачты
public bool IsDestroyed(); // Проверка уничтожения
public void Destroy(); // Уничтожение корабля
}
```
**Эффекты при уничтожении:**
- Взрывы на каждой палубе
- Отлетающие обломки с физикой
- Падающие мачты (20% шанс)
- Затопление корабля (`ShipsMuved.Sink()`)
### Система стрельбы
**CannonBattery:**
```csharp
public void FireShot(GamePole targetPole, int x, int y,
Action<bool, bool> onShotComplete)
{
// Выстрел по координатам
// Callback: (wasHit, wasShipDestroyed)
}
```
**Механика:**
1. Выбор готового орудия из батареи
2. Физический выстрел снаряда
3. Попадание в цель
4. Обработка результата (попал/промах/потопил)
5. Визуальные и звуковые эффекты
### Курсор прицеливания (TargetCursor)
**Функционал:**
- Перемещение по полю (WASD/стрелки)
- Стрельба (действие)
- Поворот кораблей при расстановке
- Привязка к игроку (1 или 2)
- Автоматическая ротация камеры
---
## Управление и ввод
### Система ввода (In)
**Архитектура:**
```
In (Фасад)
??? InputSource (Абстракция)
? ??? KeyboardInput (Для тестирования)
? ??? COMinput (Работа с платой)
??? ButtonPinMapping (Маппинг пинов)
```
**Источники ввода:**
1. **Keyboard** - клавиатура для разработки
2. **COM** - физические кнопки через COM-порт
**Маппинг кнопок:**
```csharp
public static class ButtonPinMapping
{
// Игрок 1
public static int up1 = 2;
public static int down1 = 3;
public static int left1 = 4;
public static int right1 = 5;
public static int action1 = 6;
public static int turn1 = 7;
// Игрок 2
public static int up2 = 8;
public static int down2 = 9;
// ...и т.д.
}
```
### COM-система (ComWrapper)
**Основные функции:**
```csharp
public class ComWrapper
{
// Управление кредитами
public static void AddCredit(int coins = 1);
public static void Pay();
public static int GetPlayerCredits();
// Отправка команд
public static void Send(string command);
// События
public static UnityEvent<int> onCoinAdded;
public static UnityEvent<int> onCoinRemoved;
public static UnityEvent<string> onInputRecieved;
}
```
**Команды:**
- `"302"` - выключить мотор выдачи призов
- `"303"` - включить мотор выдачи призов
- `"91"` - запросить состояние пинов
- `"80XX"` - управление подсветкой
---
## Искусственный интеллект
### Уровни сложности
**Иерархия ботов:**
```
IBotAI (Интерфейс)
??? EasyBotAI (Уровень 1) - Случайные выстрелы
??? NormalBotAI (Уровень 2) - Базовая стратегия
??? HardBotAI (Уровень 3) - Умная стратегия
??? VeryHardBotAI (Уровень 4) - Продвинутая стратегия
??? CrazyBotAI (Уровень 5) - Очень сложный
??? UltimateBotAI (Уровень 6) - Почти непобедимый
```
### DifficultyManager - Система шансов
**Механизм:**
```csharp
public static class DifficultyManager
{
public static int GetChance(); // Получить текущий шанс (0-100)
public static void DecreaseChance(); // Уменьшить после игры
public static void ResetChance(); // Сброс на 100
}
```
**Логика:**
- Начальное значение: 100
- При каждой игре против Level 6: шанс уменьшается
- При шансе = 0: игрок получает Level 5 (победимый)
- После победы над Level 5: шанс сбрасывается
### Стратегии AI
**EasyBotAI:**
- Полностью случайные выстрелы
**NormalBotAI и выше:**
1. Ищет раненые корабли
2. Добивает найденные цели
3. Использует умную стрельбу (шахматный порядок)
---
## Система призов
### Типы призов (PrizeType)
```csharp
public enum PrizeType
{
None, // Нет приза
Hopper, // Монеты через хоппер
Ticket, // Билеты
Special, // Спецприз (QR-код)
Marbles // Шарики
}
```
### PrizeSystem
**Функционал:**
```csharp
public static void GivePrize(Prize prize)
{
// Выдача приза с проверкой настроек
// Поддержка разных типов призов
// Обработка ошибок выдачи
}
```
**Процесс выдачи Hopper-приза:**
1. Проверка настроек и ошибок
2. Отправка команды `"303"` (включить мотор)
3. Ожидание подтверждения (до 10 секунд)
4. Отправка команды `"302"` (выключить мотор)
5. Обновление счетчиков
**Статистика:**
```csharp
public static string key_starts = "STARTS"; // Всего запусков
public static string key_startsNul = "STARTSNUL"; // Запуски без приза
public static string key_prizesgiven = "PRIZESGIVEN"; // Выдано призов
public static string key_prizesgivenNul = "PRIZESGIVENNUL"; // Ошибок выдачи
```
### PrizeSerializer
**Загрузка призов:**
```csharp
public static Prize[] GetPrizes()
{
// Загрузка из JSON файла
// Возвращает массив призов для каждого уровня
}
```
**Пример конфигурации приза:**
```json
{
"PrizeType": "Hopper",
"Amount": 5
}
```
---
## Настройки
### SettingsManager
**Доступные настройки:**
| Настройка | Опции | По умолчанию |
|-----------|-------|--------------|
| Громкость музыки | 0-10 | 1 |
| Громкость эффектов | 0-10 | 8 |
| Громкость голоса | 0-10 | 8 |
| Выдача призов при игре с ботом | Выдавать/Не выдавать | Выдавать |
| Бесплатная игра | Вкл/Выкл | Выкл |
| Показывать контакты администрации | Вкл/Выкл | Вкл |
| QR-код для связи | Telegram/WhatsApp/Всё | Telegram |
| Игровая тема | День/Ночь | День |
| Быстрая проверка | Вкл/Выкл | Выкл |
| Быстрая проверка наличия приза | Вкл/Выкл | Выкл |
| Выдавать приз при ошибке | Вкл/Выкл | Выкл |
| Вывод ошибки выдачи в меню | Вкл/Выкл | Выкл |
**API:**
```csharp
// Получение значения
string value = SettingsManager.instance.GetSettingValue("Громкость музыки");
// Изменение настройки
SettingsManager.instance.ChangeSetting("Громкость музыки", 5);
// Событие изменения
SettingsManager.instance.OnSettingsChanged.AddListener(OnSettingsChanged);
```
### SettingsScreen
**Функции:**
- Прокрутка настроек (более 5 элементов)
- Выбор опций с визуальной обратной связью
- Сохранение/загрузка настроек
- Валидация и хеширование
---
## Звук и визуальные эффекты
### SoundManager
**Структура:**
```csharp
public class SoundManager : Singleton
{
// Источники звука для каждого игрока
public AudioSource player1VoiceSource;
public AudioSource player1EffectsSource;
public AudioSource player2VoiceSource;
public AudioSource player2EffectsSource;
// Фоновая музыка
public AudioSource musicSource;
public AudioClip[] backgroundMusic;
// Профили звуков
public List<SoundProfile> soundProfiles;
}
```
**Звуковые профили:**
- `player` / `player_2` - голоса игроков
- `bot_1` - `bot_5` - голоса ботов разной сложности
**Основные методы:**
```csharp
void SetActiveProfile(int playerId, string profileName);
void PlayPlayerVictory(int playerId);
void PlayBotVictory(int playerId);
void PlayBotHit(int playerId);
void PlayBotMiss(int playerId);
void PlayPlayerShipDestroyed(int playerId);
```
### EffectManager
**Визуальные эффекты:**
```csharp
public class EffectManager : Singleton
{
GameObject PlayMissText(Vector3 position); // Текст "МИМО"
GameObject PlayHitEffect(Vector3 position); // Эффект попадания
GameObject PlayExplosion(Vector3 position); // Взрыв
}
```
### EnvironmentManager
**Управление окружением:**
```csharp
public class EnvironmentManager
{
[Serializable]
public class EnvironmentPreset
{
public Material skybox; // Скайбокс
public Color lightColor; // Цвет света
public float lightIntensity; // Интенсивность
// Цвета воды (остров/океан)
public Color waterShallowColor;
public Color waterDeepColor;
public Color waterFresnelColor;
// UI
public Color cursorColor;
public Color cursorFrameColor;
}
}
```
**Пресеты:**
- Preset 0: День
- Preset 1: Ночь
---
## Структура проекта
```
Assets/
??? Scripts/
? ??? GameManager.cs # Главный менеджер игры
? ??? GamePole.cs # Игровое поле
? ??? Ship.cs # Корабль
? ??? Player.cs # Игрок
? ??? TargetCursor.cs # Курсор прицеливания
? ??? CannonBattery.cs # Батарея орудий
? ??? Cannon.cs # Орудие
? ??? Cell.cs # Клетка поля
? ??? Deck.cs # Палуба корабля
? ?
? ??? BotAI/ # Искусственный интеллект
? ? ??? IBotAI.cs # Интерфейс AI
? ? ??? EasyBotAI.cs # Легкий бот
? ? ??? NormalBotAI.cs # Средний бот
? ? ??? HardBotAI.cs # Сложный бот
? ? ??? VeryHardBotAI.cs # Очень сложный
? ? ??? CrazyBotAI.cs # Безумный
? ? ??? UltimateBotAI.cs # Непобедимый
? ? ??? DifficultyManager.cs # Управление сложностью
? ?
? ??? UI/ # Интерфейс
? ? ??? UIManager.cs # Менеджер UI
? ? ??? GameOver.cs # Экран окончания
? ? ??? AdminContactsController.cs
? ? ??? FastCheckController.cs
? ? ??? Coin.cs # Монета
? ? ??? CoinFlipUI.cs # Анимация монеты
? ? ??? EnemyCardController.cs # Карточка врага
? ? ??? EnemyManager.cs # Менеджер врагов
? ? ??? TurnTimerUI.cs # Таймер хода
? ?
? ??? Settings/ # Настройки
? ? ??? SettingsManager.cs # Менеджер настроек
? ? ??? SettingsScreen.cs # Экран настроек
? ? ??? SettingOption.cs # Опция настройки
? ? ??? GameSettings.cs # Игровые настройки
? ? ??? CharacterSettingPanel.cs
? ? ??? CountersView.cs # Отображение счетчиков
? ? ??? InitializeInput.cs # Инициализация ввода
? ?
? ??? Inputs/ # Система ввода
? ? ??? In.cs # Фасад ввода
? ? ??? InputSource.cs # Абстракция источника
? ? ??? KeyboardInput.cs # Клавиатура
? ? ??? COMinput.cs # COM-порт
? ? ??? ButtonPinMapping.cs # Маппинг кнопок
? ? ??? PlayerAction.cs # Действия игрока
? ? ??? ComSystem/ # COM-система
? ? ??? ComWrapper.cs # Обертка COM
? ? ??? ComNativeWrapper.cs # Нативные вызовы
? ? ??? PrizeSystem.cs # Система призов
? ? ??? PrizeSystem/
? ? ??? Prize.cs
? ? ??? PrizeType.cs
? ? ??? PrizeSerializer.cs
? ?
? ??? Qr/ # QR-коды
? ? ??? QrMaker.cs # Генератор QR
? ? ??? QR_viewer.cs # Просмотр QR
? ?
? ??? Pirate/ # Пиратская команда
? ? ??? Pirate.cs
? ? ??? FortInitializer.cs # Инициализатор фортов
? ? ??? PirateCommand.cs # Команда пиратов
? ? ??? EnemyCombat.cs
? ? ??? Gun.cs
? ? ??? BoxingMachine.cs
? ?
? ??? Enum/ # Перечисления
? ? ??? GameState.cs
? ? ??? GameMode.cs
? ? ??? Direction.cs
? ? ??? KeyVault.cs # Ключи PlayerPrefs
? ?
? ??? SoundManager.cs # Менеджер звука
? ??? SoundProfile.cs # Профиль звуков
? ??? EffectManager.cs # Менеджер эффектов
? ??? EnvironmentManager.cs # Менеджер окружения
? ??? CameraShake.cs # Тряска камеры
? ??? MultiDisplaySetup.cs # Мультидисплей
?
??? Prefabs/ # Префабы
??? Materials/ # Материалы
??? Models/ # 3D модели
??? Animations/ # Анимации
??? Audio/ # Звуки
??? Images/ # Изображения
??? Scenes/ # Сцены
```
---
## Особенности реализации
### Система таймера бездействия
```csharp
// В GameManager
[SerializeField] float inactionTimer = 360f; // 6 минут
public float timerBackToMenu = 0;
private void Update()
{
timerBackToMenu += Time.deltaTime;
if (timerBackToMenu >= inactionTimer)
{
ResetGameState(true);
timerBackToMenu = 0;
}
}
```
**Сброс таймера:**
- При любом нажатии кнопки (`In.ButtonEvent`)
- Автоматический возврат в меню при бездействии
### Система камеры
**Позиции камеры:**
- `mainMenuCameraPosition` - главное меню
- `shipPlacementCameraPosition` - расстановка кораблей
- `gameplayCameraPosition` - игровой процесс
**Плавное перемещение:**
```csharp
public void MoveCameraTo(Transform target)
{
StartCoroutine(MoveCameraSmoothly(target));
}
```
### QR-коды для связи
**QrMaker:**
```csharp
public static Texture2D MakeTexture(
string text,
int pixelsPerModule = 8,
bool drawQuietZones = true,
Color darkColor = default,
Color lightColor = default)
```
**Цветовая схема:**
- Telegram: синий QR-код
- WhatsApp: зеленый QR-код
### Быстрая проверка (Fast Check)
**FastCheckController:**
- Слушает комбинации клавиш (Fire + Turn, Up + Down)
- Показывает статистику игры
- Отображает ошибки выдачи призов
- Работает только при включенной настройке
---
## Поток игры
### 1. Запуск приложения
```
Инициализация:
??? In.Initialize() - Система ввода
??? ComWrapper.Initialize() - COM-порт
??? PrizeSystem.Initialize() - Система призов
??? SettingsManager.Awake() - Загрузка настроек
??? GameManager.Start() - Главное меню
```
### 2. Начало игры против бота
```
1. ComWrapper.Pay() - Списание кредита
2. ResetGameState() - Сброс состояния
3. SetState(ShipPlacement) - Расстановка кораблей
4. SetInputMode(ShipPlacement) - Режим расстановки
5. InitTargetCursor(true) - Курсор расстановки
6. InitBot() - Инициализация AI
7. [Игрок расставляет корабли]
8. StartBattle() - Начало боя
9. PrepareForBattle() - Подготовка
10. enemyField.ArrangeShip() - Расстановка кораблей бота
11. SetState(Playing) - Игровое состояние
12. StartPlayerTurn() - Ход игрока
```
### 3. Игровой цикл
```
Ход игрока:
??? Перемещение курсора
??? Выстрел (FireShot)
??? Обработка результата
??? Если промах ? EndPlayerTurn()
Ход бота:
??? bot.MakeMove()
??? enemyBattery.FireShot()
??? Обработка результата
??? Если промах ? StartPlayerTurn()
```
### 4. Окончание игры
```
CheckVictoryCondition():
??? Если playerShips <= 0 ? Поражение
??? Если enemyShips <= 0 ? Победа
??? EndGame()
EndGame():
??? SetState(GameOver)
??? Если победа и бот:
? ??? Получить приз для уровня
? ??? Если Special ? показать QR
? ??? Иначе ? PrizeSystem.GivePrize()
? ??? Увеличить уровень бота
??? ShowGameOverMenu()
```
---
## Технические детали
### PlayerPrefs ключи (KeyVault)
```csharp
// Система призов
"STARTS" - Общее количество запусков
"STARTSNUL" - Запуски без выдачи приза
"PRIZESGIVEN" - Выдано призов
"PRIZESGIVENNUL" - Ошибок при выдаче
"PRIZES_AVAILABLE" - Доступно призов
"PRIZING_ERROR_REGISTRED" - Зарегистрирована ошибка
"NeedSpecialPrize" - Нужен спецприз
// Игра
"Player_Coins" - Монеты игрока
"SETTINGS" - Настройки игры
"BotChance" - Шанс победы над ботом
"telephone_number" - Телефон администратора
```
### Многопользовательская игра
**Механизм приглашения:**
```csharp
// Отправка приглашения
OnInviteSent?.Invoke(fromPlayerId, toPlayerId);
// Обработка приглашения
GameManager.OnInviteSent += HandleInvite;
// Принятие
AcceptInvite() {
StartPlayerGame();
opponentManager.StartPlayerGame();
}
```
**Синхронизация:**
- Поля копируются между игроками
- Ходы чередуются через `opponentManager`
- Победа определяется локально
### Оптимизация
**Пулинг объектов:**
- Эффекты уничтожаются через заданное время
- Обломки кораблей удаляются автоматически
**Ленивая загрузка:**
- Форты создаются по требованию
- Курсор создается только при необходимости
---
## Отладка и разработка
### Быстрые клавиши (в режиме разработки)
```csharp
// Player.cs
[SerializeField] private KeyCode addKey = KeyCode.F2; // Добавить кредит
```
### Ручная настройка сложности
```csharp
// GameManager
public bool useManualDifficulty = false;
public BotDifficulty manualDifficulty = BotDifficulty.Level1;
```
### Логирование
```csharp
Debug.Log("Игрок победил!");
Debug.LogWarning("Боту нечего стрелять");
Debug.LogError("Ошибка выдачи приза");
```
---
## Известные особенности
1. **Система шансов DifficultyManager** - игрок не может бесконечно проигрывать на 5 уровне
2. **Таймер бездействия** - автоматический возврат в меню через 6 минут
3. **Монетная система** - интеграция с физическим оборудованием
4. **Призы** - поддержка различных типов выдачи (хоппер, билеты, спецпризы)
5. **Мультидисплей** - поддержка нескольких экранов для двух игроков
---
## Зависимости
### NuGet пакеты
- **QRCoder** - генерация QR-кодов
### Unity Assets
- **TextMeshPro** - текст UI
- **Particle Systems** - визуальные эффекты
- **Post Processing** (возможно, для эффектов камеры)
---
## Конфигурационные файлы
### prizes.json
```json
{
"prizes": [
{
"PrizeType": "Hopper",
"Amount": 1
},
{
"PrizeType": "Hopper",
"Amount": 2
},
// ...до 5 уровней
]
}
```
---
## Лицензия и авторские права
Проект использует сторонние ассеты:
- JMO Assets (Cartoon FX)
- Toony Colors Pro
- ProBuilder
- Skybox Cubemap Extended
---
## Контакты и поддержка
Для связи с администратором:
- QR-код генерируется автоматически
- Номер телефона хранится в PlayerPrefs по ключу `"telephone_number"`
- Отображается в UI при включенной настройке
---
**Версия документации:** 1.0
**Дата:** 2025-12-10
**Язык:** Русский
*Документация составлена на основе анализа исходного кода проекта Sea Battle.*