feat: initial commit with M1-M4 implementation

This commit is contained in:
Vladimir V Maksimov
2026-05-12 10:54:09 +03:00
commit aece34fe73
24 changed files with 1770 additions and 0 deletions

View File

@@ -0,0 +1,102 @@
# План: Game Rules & Match Logic (M5)
**Цель:** Реализовать систему судейства, подсчёт голов, таймер матча и управление состояниями игры (Playing, GoalPause, MatchEnded).
**Архитектура:** Введение `MatchManager` в качестве верхнего уровня управления. Он владеет `World` и контролирует, когда физика и ИИ мира должны обновляться, а когда игра должна быть заморожена.
**Стек:** Go.
**Спека:** [docs/specs/2026-05-12-match-logic-design.md](../specs/2026-05-12-match-logic-design.md)
---
## Файловая структура
- `internal/game/world.go` — добавление методов для проверки гола и сброса позиций.
- `internal/game/match_manager.go` — новый файл с логикой управления матчем, счетом и таймерами.
- `cmd/game/main.go` — замена `World` на `MatchManager` в основном цикле игры.
---
## Задачи
### Задача 1: Методы управления состоянием мира
**Файлы:**
- Изменить: `internal/game/world.go`
- [ ] **Шаг 1: Реализовать `CheckGoal()`**
- Метод должен проверять `Puck.Position.X`.
- Если `X < 0` $\rightarrow$ возвращает `(entities.TeamBlue, true)`.
- Если `X > WorldWidth` $\rightarrow$ возвращает `(entities.TeamRed, true)`.
- Иначе $\rightarrow$ `(entities.TeamRed, false)`.
- [ ] **Шаг 2: Реализовать `ResetPositions()`**
- Установить `Puck.Position` в центр поля, `Puck.Velocity = 0`.
- Для каждого игрока в `Players` установить `Position = HomePosition` и `Velocity = 0`.
- [ ] **Шаг 3: Коммит**
`git add internal/game/world.go && git commit -m "feat(game): add CheckGoal and ResetPositions to World"`
### Задача 2: Реализация MatchManager
**Файлы:**
- Создать: `internal/game/match_manager.go`
- [ ] **Шаг 1: Определить типы и структуру**
- `GameState` (enum: `Playing`, `GoalPause`, `MatchEnded`).
- `MatchManager` структура:
- `World *World`
- `State GameState`
- `ScoreRed, ScoreBlue int`
- `MatchDuration float64` (в секундах)
- `CurrentTime float64`
- `PauseDuration float64`
- `PauseTimer float64`
- [ ] **Шаг 2: Реализовать `Update(dt float64)`**
- Логика переключения состояний:
- Если `Playing`:
- Проверить `World.CheckGoal()`. Если гол $\rightarrow$ `State = GoalPause`, обновить счет, `PauseTimer = PauseDuration`.
- Если не гол $\rightarrow$ вызвать `World.Update(dt)`.
- Обновить `CurrentTime += dt`. Если `CurrentTime >= MatchDuration` $\rightarrow$ `State = MatchEnded`.
- Если `GoalPause`:
- `PauseTimer -= dt`.
- Если `PauseTimer <= 0` $\rightarrow$ вызвать `World.ResetPositions()`, `State = Playing`.
- Если `MatchEnded`:
- Ничего не делать.
- [ ] **Шаг 3: Коммит**
`git add internal/game/match_manager.go && git commit -m "feat(game): implement MatchManager for game rules"`
### Задача 3: Интеграция в Main Loop
**Файлы:**
- Изменить: `cmd/game/main.go`
- [ ] **Шаг 1: Обновить структуру `Game`**
- Заменить `world *game.World` на `matchManager *game.MatchManager`.
- [ ] **Шаг 2: Обновить инициализацию в `NewGame()`**
- Создать `world := game.NewWorld()`.
- Создать `matchManager := game.NewMatchManager(world)`.
- [ ] **Шаг 3: Обновить `Update()` и `Draw()`**
- В `Update()` вызывать `g.matchManager.Update(dt)`.
- В `Draw()` передавать `g.matchManager.World` в функцию отрисовки.
- [ ] **Шаг 4: Коммит**
`git add cmd/game/main.go && git commit -m "feat(game): integrate MatchManager into main loop"`
### Задача 4: Тестирование и верификация
- [ ] **Шаг 1: Проверка сценария "Гол"**
- Запустить игру, забить гол.
- Ожидание: Игра замирает, через несколько секунд все возвращаются в центр.
- [ ] **Шаг 2: Проверка сценария "Конец матча"**
- Установить короткий `MatchDuration` (например, 10 сек).
- Ожидание: Через 10 секунд игра замирает навсегда.
- [ ] **Шаг 3: Коммит**
`git commit -m "test(game): verify match logic flow"`