feat: initial commit with M1-M4 implementation
This commit is contained in:
146
docs/plans/2026-05-08-physics-dynamics.md
Normal file
146
docs/plans/2026-05-08-physics-dynamics.md
Normal file
@@ -0,0 +1,146 @@
|
||||
# План: Физика и динамика шайбы (M2)
|
||||
|
||||
**Цель:** Реализовать трение, потерю энергии при отскоках и порог остановки для шайбы.
|
||||
|
||||
**Архитектура:** Внедрение коэффициентов трения (`Friction`) и упругости (`Restitution`) в логику обновления мира. Использование простого множительного затухания скорости.
|
||||
|
||||
**Стек:** Go, Ebitengine (для контекста мира).
|
||||
|
||||
**Спека:** [docs/specs/2026-05-08-physics-dynamics-design.md](../specs/2026-05-08-physics-dynamics-design.md)
|
||||
|
||||
---
|
||||
|
||||
## Файловая структура
|
||||
|
||||
- `internal/game/world.go` — добавление констант физики и обновление логики `Update`.
|
||||
- `internal/game/world_test.go` — новые unit-тесты для проверки затухания скорости и потерь при отскоках.
|
||||
|
||||
---
|
||||
|
||||
## Задачи
|
||||
|
||||
### Задача 1: Константы физики
|
||||
|
||||
**Файлы:**
|
||||
- Изменить: `internal/game/world.go`
|
||||
|
||||
- [ ] **Шаг 1: Добавить константы в начало файла**
|
||||
|
||||
```go
|
||||
const (
|
||||
PuckFriction = 0.99 // Коэффициент трения (каждый кадр)
|
||||
PuckRestitution = 0.8 // Коэффициент упругости (при ударе о борт)
|
||||
PuckStopThreshold = 0.1 // Порог остановки
|
||||
)
|
||||
```
|
||||
|
||||
- [ ] **Шаг 2: Коммит**
|
||||
|
||||
```bash
|
||||
git add internal/game/world.go
|
||||
git commit -m "phys: add physics constants"
|
||||
```
|
||||
|
||||
### Задача 2: Реализация трения и порога остановки
|
||||
|
||||
**Файлы:**
|
||||
- Изменить: `internal/game/world.go`
|
||||
|
||||
- [ ] **Шаг 1: Обновить `World.Update` для применения трения**
|
||||
|
||||
В начале `Update` добавить:
|
||||
```go
|
||||
w.puck.Velocity.X *= PuckFriction
|
||||
w.puck.Velocity.Y *= PuckFriction
|
||||
|
||||
if math.Abs(w.puck.Velocity.X) < PuckStopThreshold {
|
||||
w.puck.Velocity.X = 0
|
||||
}
|
||||
if math.Abs(w.puck.Velocity.Y) < PuckStopThreshold {
|
||||
w.puck.Velocity.Y = 0
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Шаг 2: Коммит**
|
||||
|
||||
```bash
|
||||
git add internal/game/world.go
|
||||
git commit -m "phys: implement puck friction and stop threshold"
|
||||
```
|
||||
|
||||
### Задача 3: Реализация потерь при отскоках
|
||||
|
||||
**Файлы:**
|
||||
- Изменить: `internal/game/world.go`
|
||||
|
||||
- [ ] **Шаг 1: Обновить логику отскоков в `World.Update`**
|
||||
|
||||
Заменить инверсию скорости на инверсию с множителем `PuckRestitution`.
|
||||
Пример для X:
|
||||
```go
|
||||
if w.puck.X - w.puck.Radius <= 0 || w.puck.X + w.puck.Radius >= float64(screenWidth) {
|
||||
w.puck.Velocity.X = -w.puck.Velocity.X * PuckRestitution
|
||||
// Добавить коррекцию позиции, чтобы не застрять в стене
|
||||
if w.puck.X - w.puck.Radius < 0 {
|
||||
w.puck.X = w.puck.Radius
|
||||
} else if w.puck.X + w.puck.Radius > float64(screenWidth) {
|
||||
w.puck.X = float64(screenWidth) - w.puck.Radius
|
||||
}
|
||||
}
|
||||
```
|
||||
Аналогично для Y.
|
||||
|
||||
- [ ] **Шаг 2: Коммит**
|
||||
|
||||
```bash
|
||||
git add internal/game/world.go
|
||||
git commit -m "phys: implement energy loss on bounce"
|
||||
```
|
||||
|
||||
### Задача 4: Тестирование физики
|
||||
|
||||
**Файлы:**
|
||||
- Создать: `internal/game/world_test.go`
|
||||
|
||||
- [ ] **Шаг 1: Написать тест на затухание скорости**
|
||||
|
||||
```go
|
||||
func TestPuckFriction(t *testing.T) {
|
||||
w := NewWorld()
|
||||
w.puck.Velocity = Vector2{X: 10, Y: 0}
|
||||
|
||||
w.Update()
|
||||
|
||||
if w.puck.Velocity.X >= 10 {
|
||||
t.Errorf("Expected velocity to decrease due to friction, got %f", w.puck.Velocity.X)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Шаг 2: Написать тест на отскок с потерей энергии**
|
||||
|
||||
```go
|
||||
func TestPuckBounceLoss(t *testing.T) {
|
||||
w := NewWorld()
|
||||
w.puck.X = 1 // Почти у левого края
|
||||
w.puck.Velocity = Vector2{X: -10, Y: 0}
|
||||
|
||||
w.Update()
|
||||
|
||||
expected := 10 * PuckRestitution
|
||||
if math.Abs(w.puck.Velocity.X - expected) > 0.001 {
|
||||
t.Errorf("Expected velocity after bounce to be %f, got %f", expected, w.puck.Velocity.X)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Шаг 3: Запустить тесты**
|
||||
|
||||
`go test ./internal/game/ -v`
|
||||
|
||||
- [ ] **Шаг 4: Коммит**
|
||||
|
||||
```bash
|
||||
git add internal/game/world_test.go
|
||||
git commit -m "test: add physics tests"
|
||||
```
|
||||
Reference in New Issue
Block a user