# Platformer Game

Browser-based platformer game built with Phaser 3 and TypeScript.

## Tech Stack

- **Engine:** Phaser 3
- **Language:** TypeScript
- **Build:** Vite
- **Package Manager:** npm

## Project Structure

```
src/
├── scenes/       # Game scenes (Boot, Menu, Game, etc.)
├── entities/     # Game objects (Player, Enemies, Items)
├── systems/      # Core systems (Physics, Input, Audio)
├── config/       # Game configuration
└── assets/       # Sprites, sounds, tilemaps
```

## Quick Start

```bash
npm install
npm run dev
```

## Documentation

- [Game Design](./docs/DESIGN.md) - gameplay mechanics, levels
- [Architecture](./docs/ARCHITECTURE.md) - code structure, patterns
- [Assets](./docs/ASSETS.md) - sprites, audio, tilemaps

## Commands

- `npm run dev` - development server
- `npm run build` - production build
- `npm run preview` - preview build
- `npm run check` - **запускать перед коммитом** (typecheck + lint)
- `npm run lint` - проверка ESLint
- `npm run lint:fix` - автоисправление ESLint/Prettier
- `npm run typecheck` - проверка TypeScript
- `npm run format` - форматирование Prettier

## Phaser 3 — Правила разработки

### 1. Обработчики событий накапливаются при рестарте

Keyboard Keys в Phaser переиспользуются между рестартами сцены. **Всегда удаляй старые обработчики:**

```typescript
// ПРАВИЛЬНО
key.removeAllListeners('down');
key.on('down', () => this.shoot());

// Для событий сцены
this.events.off('shoot', this.handleShoot, this);
this.events.on('shoot', this.handleShoot, this);
```

### 2. scene.start() НЕ останавливает текущую сцену

Оверлеи (GameOver, Pause) остаются видимыми. **Явно останавливай сцены:**

```typescript
const sceneManager = this.game.scene;  // Используй глобальный менеджер!
sceneManager.stop('UIScene');
sceneManager.stop('GameOverScene');
sceneManager.start('GameScene');
```

### 3. Null reference при рестарте UI-сцены

`update()` может вызваться до `create()`. **Сбрасывай массивы и добавляй проверки:**

```typescript
create(): void {
  this.indicators = [];  // Сбрасывай в начале create()
}

update(): void {
  if (!this.runState || !this.scoreText) return;  // Guard-проверка
}
```

### 4. Чеклист при работе со сценами

- [ ] Очищать обработчики клавиш в `setupControls()`
- [ ] Очищать `this.events` обработчики в `create()` или `shutdown()`
- [ ] Сбрасывать массивы/объекты в начале `create()`
- [ ] Добавлять null-проверки в `update()` для UI
- [ ] Использовать `this.game.scene` для остановки текущей сцены
