mafia / frontend /README.md
Alfaxad's picture
Migrate Mafia game to ZeroGPU Gradio Space
c670567 verified
|
Raw
History Blame Contribute Delete
8.65 kB
# Phaser 3 Game Template
A standardized Phaser 3 game template for rapid 2D web game development. This template provides a consistent architecture and pre-built components that AI coding agents can use to generate games efficiently.
## Quick Start
```bash
# Install dependencies
npm install
# Start development server
npm run dev
# Build for production
npm run build
```
## Project Structure
```
src/
├── main.ts # Game entry point & Phaser configuration
├── gameConfig.json # All game parameters (health, speed, damage, etc.)
├── LevelManager.ts # Level flow management
├── utils.ts # CRITICAL utility functions (DO NOT MODIFY)
├── characters/ # Player and enemy classes
│ ├── ExamplePlayer.ts # Template - copy then delete/rename
│ └── ExampleEnemy.ts # Template - copy then delete/rename
├── scenes/
│ ├── Preloader.ts # Asset loading (STANDARD - minimal changes)
│ ├── TitleScreen.ts # Start screen (customize UI only)
│ ├── BaseLevelScene.ts # Optional level base class
│ ├── UIScene.ts # In-game HUD
│ ├── VictoryUIScene.ts # Level complete screen
│ ├── GameOverUIScene.ts # Death/failure screen
│ └── GameCompleteUIScene.ts # All levels complete screen
├── styles/
│ └── tailwind.css # Tailwind CSS for UI styling
└── test/
└── setup.ts # Test configuration
public/assets/
├── asset-pack.json # Asset manifest for Preloader
└── animations.json # Animation definitions with origin data
```
## Key Files Reference
### main.ts
- Configures Phaser game instance
- Imports and registers all scenes in order:
1. Preloader (auto-start)
2. TitleScreen
3. Level scenes
4. UI scenes
### gameConfig.json
All game parameters use **`{ "value": X }` wrapper format** (self-documenting):
```json
{
"configGroup": {
"parameterName": {
"value": 100,
"type": "number",
"description": "What this does"
}
}
}
```
Access in code: `configGroup.parameterName.value`
### utils.ts - CRITICAL FUNCTIONS
**DO NOT MODIFY these functions. They solve Phaser quirks.**
| Function | Usage |
| -------------------------------- | ------------------------------------------------------------------- |
| `initScale()` | **ALWAYS use** for sprite scaling. Never use `setScale()` directly. |
| `resetOriginAndOffset()` | **ALWAYS call** after `play()` animation. |
| `initUIDom()` | **ALWAYS use** for UI scene DOM elements. |
| `addCollider()` / `addOverlap()` | **ALWAYS use** instead of `scene.physics.add.collider/overlap`. |
| `createTrigger()` | Create attack/detection zones. |
| `updateMeleeTrigger()` | Update melee attack zone position. |
| `createDecoration()` | Create decorative elements. |
| `computeRotation()` | Calculate projectile rotation. |
### LevelManager.ts
Manages level progression:
```typescript
// Add your level scene keys here
static readonly LEVEL_ORDER: string[] = [
"Level1Scene",
"Level2Scene",
// ...
];
```
## Animation Format (animations.json)
```json
{
"anims": [
{
"key": "player_idle_anim",
"type": "frame",
"frames": [
{ "key": "player_idle_01", "duration": 400 } // idle: 1 frame only
],
"repeat": -1,
"originX": 0.5,
"originY": 1.0
},
{
"key": "player_run_anim",
"type": "frame",
"frames": [
{ "key": "player_run_01", "duration": 400 }, // run: 2 frames
{ "key": "player_run_02", "duration": 400 }
],
"repeat": -1,
"originX": 0.5,
"originY": 1.0
}
]
}
```
**Important**: `originX` and `originY` are REQUIRED for `utils.resetOriginAndOffset()` to work correctly. Different animations may have different origins (e.g., attack animations often shift left/right).
## Asset Pack Format (asset-pack.json)
```json
{
"assetPack": {
"files": [
{ "type": "json", "key": "animations", "url": "assets/animations.json" },
{
"type": "image",
"key": "player_idle_01",
"url": "assets/player_idle_01.png"
},
{
"type": "image",
"key": "player_run_01",
"url": "assets/player_run_01.png"
},
{
"type": "image",
"key": "player_run_02",
"url": "assets/player_run_02.png"
},
{
"type": "tilemapTiledJSON",
"key": "level1_map",
"url": "assets/level1_map.json"
}
]
}
}
```
## Creating a New Game
### 1. Define Game Config
Edit `gameConfig.json` to add your game's parameters.
### 2. Create Player Class
Copy `ExamplePlayer.ts` to create your player (e.g., `Player.ts`), then delete `ExamplePlayer.ts`:
- Load config values
- Implement movement in `update()`
- Implement `takeDamage()` and `die()`
- Add animations
### 3. Create Enemy Classes
Copy `ExampleEnemy.ts` for each enemy type (e.g., `EnemySoldier.ts`), then delete `ExampleEnemy.ts`:
- Configure stats
- Implement AI in `executeAI()`
- Add unique behaviors
### 4. Create Level Scenes
Either extend `BaseLevelScene` or create from scratch:
```typescript
export class Level1Scene extends BaseLevelScene {
constructor() {
super({ key: 'Level1Scene' });
}
create() {
this.createBaseElements();
// Level-specific setup
}
update(time, delta) {
this.baseUpdate(time, delta);
// Level-specific updates
}
// Implement abstract methods...
}
```
### 5. Register Levels
1. Import in `main.ts`
2. Add to `game.scene.add()`
3. Add key to `LevelManager.LEVEL_ORDER`
### 6. Customize UI
Modify the `createDOMUI()` methods in:
- `TitleScreen.ts` - Start screen design
- `UIScene.ts` - In-game HUD
- Victory/GameOver scenes - End screens
## Standard Dimensions
| Element | Standard Height | Notes |
| ---------------- | --------------- | ------------------------------ |
| Player | 128px | Standard human-sized character |
| Small enemy | 48-64px | Knee to waist height |
| Medium enemy | 80-100px | Slightly smaller than player |
| Large enemy/Boss | 150-256px | 1.5x to 2x player size |
| Tile size | 64px | Standard tile dimension |
## UI Styling
UI uses Tailwind CSS with custom pixel-art styled components:
- `game-pixel-container-*` - Pixel-styled containers
- `game-pixel-container-slot-*` - Progress bar backgrounds
- `game-pixel-container-progress-fill-*` - Progress bar fills
- `game-pixel-container-clickable-*` - Clickable buttons
## Scene Lifecycle
1. **Preloader** → Loads all assets
2. **TitleScreen** → Press Enter to start
3. **Level1Scene** + **UIScene** (parallel) → Gameplay
4. On victory: **VictoryUIScene** → Next level OR **GameCompleteUIScene** → Title
5. On death: **GameOverUIScene** → Restart level
## Common Patterns
### Playing Animations
```typescript
// CORRECT - always use this pattern
playAnimation(animKey: string): void {
this.play(animKey, true);
utils.resetOriginAndOffset(this, this.facingDirection);
}
```
### Scaling Sprites
```typescript
// CORRECT - always use initScale
utils.initScale(
sprite,
{ x: 0.5, y: 1.0 }, // origin
undefined, // maxWidth (optional)
128, // maxHeight
0.6, // body width factor
0.85, // body height factor
);
// WRONG - never do this
sprite.setScale(2);
sprite.setDisplaySize(100, 100);
```
### Adding Collisions
```typescript
// CORRECT - guaranteed parameter order
utils.addCollider(this, player, enemies, (player, enemy) => {
player.takeDamage(enemy.damage);
});
// WRONG - parameter order may be swapped
this.physics.add.collider(player, enemies, callback);
```
## Development Tips
1. **Always test animations** - Make sure `originX/Y` in animations.json are correct
2. **Use groups** - Add enemies/decorations to groups for easy management
3. **Check health** - Use `getHealthPercentage()` for UI updates
4. **Clean up events** - Always remove event listeners in `cleanupEventListeners()`
5. **Prevent double-triggers** - Use flags like `isStarting`, `isRestarting`
## License
MIT