22 KiB
Документация игры "Морской бой"
Оглавление
- Обзор проекта
- Архитектура игры
- Игровые режимы
- Основные системы
- Управление и ввод
- Искусственный интеллект
- Система призов
- Настройки
- Звук и визуальные эффекты
- Структура проекта
Обзор проекта
Sea Battle - это аркадная игра "Морской бой" для Unity, разработанная для работы с аппаратным обеспечением через COM-порт. Игра поддерживает как одиночный режим против AI, так и многопользовательский режим (два игрока).
Ключевые особенности:
- ? Два режима игры: против бота и против другого игрока
- ? 6 уровней сложности AI с прогрессивной системой
- ? Интегрированная система выдачи призов (монеты, билеты, спецпризы)
- ? Динамическая смена окружения (день/ночь)
- ? Уникальные голосовые профили для каждого противника
- ? Монетная система через COM-порт
- ?? Расширенная система настроек
- ? Генерация QR-кодов для связи (Telegram/WhatsApp)
Архитектура игры
Основные состояния (GameState)
public enum GameState
{
MainMenu, // Главное меню
ShipPlacement, // Расстановка кораблей
BotPlacement, // Расстановка кораблей ботом
Playing, // Игровой процесс
GameOver, // Конец игры
Setting, // Настройки
Invite, // Приглашение игрока
Input, // Ввод данных
Prize, // Экран приза
CharacterSetting // Настройка персонажа
}
Режимы управления (InputMode)
public enum InputMode
{
UI, // Интерфейс меню
Settings, // Навигация в настройках
ShipPlacement, // Расстановка кораблей
Battle // Боевой режим
}
Центральный менеджер - GameManager
GameManager - главный управляющий класс игры, отвечает за:
- Переключение состояний игры
- Управление ходами игроков
- Контроль победных условий
- Инициализацию AI
- Взаимодействие с противником
- Управление камерой
- Таймер бездействия (360 секунд по умолчанию)
События:
public static event Action<int, int> OnInviteSent; // Приглашение отправлено
public static event Action<int, bool, GameMode> OnReady; // Игрок готов
public event Action<InputMode> OnInputModeChanged; // Режим ввода изменен
Игровые режимы
1. Режим "Игрок против Бота" (PlayerVsBot)
Процесс игры:
- Игрок вносит оплату (
ComWrapper.Pay()) - Расстановка кораблей игроком
- Автоматическая расстановка кораблей ботом
- Пошаговая битва
- Выдача приза при победе (если настройка включена)
Прогрессия сложности:
- Level 1-4: Последовательное повышение
- Level 5: Активируется система шансов (DifficultyManager)
- Level 6: "Непобедимый" режим
2. Режим "Игрок против Игрока" (PlayerVsPlayer)
Процесс игры:
- Первый игрок отправляет приглашение
- Второй игрок принимает приглашение
- Оба игрока расставляют корабли
- Поочередная битва
- Возврат средств при выходе в меню
Основные системы
Система игрового поля (GamePole)
Ключевые функции:
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)
Компоненты:
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:
public void FireShot(GamePole targetPole, int x, int y,
Action<bool, bool> onShotComplete)
{
// Выстрел по координатам
// Callback: (wasHit, wasShipDestroyed)
}
Механика:
- Выбор готового орудия из батареи
- Физический выстрел снаряда
- Попадание в цель
- Обработка результата (попал/промах/потопил)
- Визуальные и звуковые эффекты
Курсор прицеливания (TargetCursor)
Функционал:
- Перемещение по полю (WASD/стрелки)
- Стрельба (действие)
- Поворот кораблей при расстановке
- Привязка к игроку (1 или 2)
- Автоматическая ротация камеры
Управление и ввод
Система ввода (In)
Архитектура:
In (Фасад)
??? InputSource (Абстракция)
? ??? KeyboardInput (Для тестирования)
? ??? COMinput (Работа с платой)
??? ButtonPinMapping (Маппинг пинов)
Источники ввода:
- Keyboard - клавиатура для разработки
- COM - физические кнопки через COM-порт
Маппинг кнопок:
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)
Основные функции:
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 - Система шансов
Механизм:
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 и выше:
- Ищет раненые корабли
- Добивает найденные цели
- Использует умную стрельбу (шахматный порядок)
Система призов
Типы призов (PrizeType)
public enum PrizeType
{
None, // Нет приза
Hopper, // Монеты через хоппер
Ticket, // Билеты
Special, // Спецприз (QR-код)
Marbles // Шарики
}
PrizeSystem
Функционал:
public static void GivePrize(Prize prize)
{
// Выдача приза с проверкой настроек
// Поддержка разных типов призов
// Обработка ошибок выдачи
}
Процесс выдачи Hopper-приза:
- Проверка настроек и ошибок
- Отправка команды
"303"(включить мотор) - Ожидание подтверждения (до 10 секунд)
- Отправка команды
"302"(выключить мотор) - Обновление счетчиков
Статистика:
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
Загрузка призов:
public static Prize[] GetPrizes()
{
// Загрузка из JSON файла
// Возвращает массив призов для каждого уровня
}
Пример конфигурации приза:
{
"PrizeType": "Hopper",
"Amount": 5
}
Настройки
SettingsManager
Доступные настройки:
| Настройка | Опции | По умолчанию |
|---|---|---|
| Громкость музыки | 0-10 | 1 |
| Громкость эффектов | 0-10 | 8 |
| Громкость голоса | 0-10 | 8 |
| Выдача призов при игре с ботом | Выдавать/Не выдавать | Выдавать |
| Бесплатная игра | Вкл/Выкл | Выкл |
| Показывать контакты администрации | Вкл/Выкл | Вкл |
| QR-код для связи | Telegram/WhatsApp/Всё | Telegram |
| Игровая тема | День/Ночь | День |
| Быстрая проверка | Вкл/Выкл | Выкл |
| Быстрая проверка наличия приза | Вкл/Выкл | Выкл |
| Выдавать приз при ошибке | Вкл/Выкл | Выкл |
| Вывод ошибки выдачи в меню | Вкл/Выкл | Выкл |
API:
// Получение значения
string value = SettingsManager.instance.GetSettingValue("Громкость музыки");
// Изменение настройки
SettingsManager.instance.ChangeSetting("Громкость музыки", 5);
// Событие изменения
SettingsManager.instance.OnSettingsChanged.AddListener(OnSettingsChanged);
SettingsScreen
Функции:
- Прокрутка настроек (более 5 элементов)
- Выбор опций с визуальной обратной связью
- Сохранение/загрузка настроек
- Валидация и хеширование
Звук и визуальные эффекты
SoundManager
Структура:
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- голоса ботов разной сложности
Основные методы:
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
Визуальные эффекты:
public class EffectManager : Singleton
{
GameObject PlayMissText(Vector3 position); // Текст "МИМО"
GameObject PlayHitEffect(Vector3 position); // Эффект попадания
GameObject PlayExplosion(Vector3 position); // Взрыв
}
EnvironmentManager
Управление окружением:
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/ # Сцены
Особенности реализации
Система таймера бездействия
// В 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- игровой процесс
Плавное перемещение:
public void MoveCameraTo(Transform target)
{
StartCoroutine(MoveCameraSmoothly(target));
}
QR-коды для связи
QrMaker:
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)
// Система призов
"STARTS" - Общее количество запусков
"STARTSNUL" - Запуски без выдачи приза
"PRIZESGIVEN" - Выдано призов
"PRIZESGIVENNUL" - Ошибок при выдаче
"PRIZES_AVAILABLE" - Доступно призов
"PRIZING_ERROR_REGISTRED" - Зарегистрирована ошибка
"NeedSpecialPrize" - Нужен спецприз
// Игра
"Player_Coins" - Монеты игрока
"SETTINGS" - Настройки игры
"BotChance" - Шанс победы над ботом
"telephone_number" - Телефон администратора
Многопользовательская игра
Механизм приглашения:
// Отправка приглашения
OnInviteSent?.Invoke(fromPlayerId, toPlayerId);
// Обработка приглашения
GameManager.OnInviteSent += HandleInvite;
// Принятие
AcceptInvite() {
StartPlayerGame();
opponentManager.StartPlayerGame();
}
Синхронизация:
- Поля копируются между игроками
- Ходы чередуются через
opponentManager - Победа определяется локально
Оптимизация
Пулинг объектов:
- Эффекты уничтожаются через заданное время
- Обломки кораблей удаляются автоматически
Ленивая загрузка:
- Форты создаются по требованию
- Курсор создается только при необходимости
Отладка и разработка
Быстрые клавиши (в режиме разработки)
// Player.cs
[SerializeField] private KeyCode addKey = KeyCode.F2; // Добавить кредит
Ручная настройка сложности
// GameManager
public bool useManualDifficulty = false;
public BotDifficulty manualDifficulty = BotDifficulty.Level1;
Логирование
Debug.Log("Игрок победил!");
Debug.LogWarning("Боту нечего стрелять");
Debug.LogError("Ошибка выдачи приза");
Известные особенности
- Система шансов DifficultyManager - игрок не может бесконечно проигрывать на 5 уровне
- Таймер бездействия - автоматический возврат в меню через 6 минут
- Монетная система - интеграция с физическим оборудованием
- Призы - поддержка различных типов выдачи (хоппер, билеты, спецпризы)
- Мультидисплей - поддержка нескольких экранов для двух игроков
Зависимости
NuGet пакеты
- QRCoder - генерация QR-кодов
Unity Assets
- TextMeshPro - текст UI
- Particle Systems - визуальные эффекты
- Post Processing (возможно, для эффектов камеры)
Конфигурационные файлы
prizes.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.