# Space Shooter Plugin Specification

## Overview

The Space Shooter Plugin creates a retro 80s arcade-style demo with ships flying through a starfield, dodging and shooting enemies. Demonstrates full-screen plugin capabilities with interactive gameplay.

**Location:** `plugins/fullscreen/space_shooter_plugin.py`

**Version:** 1.0.0

## Features

### Visual Effects

- **Starfield**: Moving stars creating depth effect
- **Player ship**: Responsive ship that banks when turning
- **Enemy ships**: Procedurally generated enemies
- **Laser bolts**: Player and enemy projectiles
- **Explosions**: Particle-based explosion effects

### Gameplay

- **Movement**: Arrow keys for ship movement
- **Shooting**: Space bar to fire lasers
- **Collision detection**: Ship vs enemies, lasers vs enemies
- **Score tracking**: Points for destroying enemies
- **Lives system**: Multiple lives with respawn

### Performance

- **Smooth animation**: Frame-independent movement
- **Particle system**: Efficient explosion effects
- **Procedural generation**: Infinite enemy waves
- **Responsive controls**: Low-latency input handling

## Architecture

### Plugin Structure

```python
class SpaceShooterPlugin(FullScreenPlugin):
    - initialize(renderer) -> bool
    - on_start() -> None
    - render_frame(delta_time: float) -> bool
    - handle_key(key_press: KeyPress) -> None
    - on_end() -> None
```

### Component System

Uses `SpaceShooterRenderer` from `core.fullscreen.components.space_shooter_components`:

```python
class SpaceShooterRenderer:
    - __init__(width: int, height: int)
    - reset() -> None
    - update(delta_time: float) -> None
    - render() -> str
    - _update_starfield(delta_time: float) -> None
    - _update_player(delta_time: float) -> None
    - _update_enemies(delta_time: float) -> None
    - _update_lasers(delta_time: float) -> None
    - _update_particles(delta_time: float) -> None
    - _check_collisions() -> None
    - _spawn_enemy() -> None
```

## Configuration

### Configuration Options

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `player_speed` | float | `20.0` | Player ship movement speed (chars/sec) |
| `laser_speed` | float | `30.0` | Laser bolt speed (chars/sec) |
| `enemy_speed` | float | `5.0` | Enemy ship speed (chars/sec) |
| `spawn_rate` | float | `2.0` | Enemy spawn rate (enemies/sec) |
| `max_enemies` | int | `10` | Maximum enemies on screen |
| `lives` | int | `3` | Starting lives |
| `score_per_enemy` | int | `100` | Points per enemy destroyed |
| `particle_count` | int | `20` | Particles per explosion |

### Configuration File

Edit `~/.kollabor-cli/config.json`:

```json
{
  "plugins": {
    "space_shooter": {
      "player_speed": 20.0,
      "laser_speed": 30.0,
      "enemy_speed": 5.0,
      "spawn_rate": 2.0,
      "max_enemies": 10,
      "lives": 3,
      "score_per_enemy": 100,
      "particle_count": 20
    }
  }
}
```

## Game Objects

### Star

```python
@dataclass
class Star:
    x: float               # Horizontal position
    y: float               # Vertical position
    z: float               # Depth (parallax speed)
    char: str              # Character (., *, +)
```

### Player

```python
@dataclass
class Player:
    x: float               # Horizontal position
    y: float               # Vertical position
    velocity_x: float      # Horizontal velocity
    bank: float            # Banking angle (-1.0 to 1.0)
    char: str              # Ship character
    lives: int             # Remaining lives
    invulnerable: float    # Invulnerability timer
```

### Enemy

```python
@dataclass
class Enemy:
    x: float               # Horizontal position
    y: float               # Vertical position
    velocity_x: float      # Horizontal velocity
    velocity_y: float      # Vertical velocity
    char: str              # Enemy character
    type: str             # Enemy type (fighter, bomber, etc.)
    shoot_timer: float      # Time until next shot
```

### Laser

```python
@dataclass
class Laser:
    x: float               # Horizontal position
    y: float               # Vertical position
    velocity_y: float      # Vertical velocity (negative = up, positive = down)
    char: str              # Laser character
    owner: str             # "player" or "enemy"
```

### Particle

```python
@dataclass
class Particle:
    x: float               # Horizontal position
    y: float               # Vertical position
    velocity_x: float      # Horizontal velocity
    velocity_y: float      # Vertical velocity
    life: float           # Remaining lifetime (seconds)
    char: str              # Particle character
    color: str             # Particle color
```

## Game Logic

### Movement

```python
def update(delta_time: float):
    # Update starfield (parallax)
    for star in stars:
        star.y += star.z * 10.0 * delta_time
        if star.y > height:
            star.y = 0
            star.x = random.random() * width
    
    # Update player
    player.x += player.velocity_x * player_speed * delta_time
    player.x = clamp(player.x, 0, width - 1)
    
    # Update enemies
    for enemy in enemies:
        enemy.x += enemy.velocity_x * delta_time
        enemy.y += enemy.velocity_y * delta_time
    
    # Update lasers
    for laser in lasers:
        laser.y += laser.velocity_y * delta_time
    
    # Update particles
    for particle in particles:
        particle.x += particle.velocity_x * delta_time
        particle.y += particle.velocity_y * delta_time
        particle.life -= delta_time
```

### Collision Detection

```python
def _check_collisions():
    # Player lasers vs enemies
    for laser in player_lasers[:]:
        for enemy in enemies[:]:
            if distance(laser, enemy) < 1.0:
                lasers.remove(laser)
                enemies.remove(enemy)
                score += score_per_enemy
                spawn_explosion(enemy.x, enemy.y)
    
    # Enemy lasers vs player
    for laser in enemy_lasers[:]:
        if player.invulnerable <= 0 and distance(laser, player) < 1.0:
            lasers.remove(laser)
            player.lives -= 1
            player.invulnerable = 2.0  # 2 seconds
            spawn_explosion(player.x, player.y)
    
    # Player vs enemies (crash)
    for enemy in enemies[:]:
        if player.invulnerable <= 0 and distance(player, enemy) < 1.0:
            enemies.remove(enemy)
            player.lives -= 1
            player.invulnerable = 2.0
            spawn_explosion(player.x, player.y)
```

### Enemy Spawning

```python
def _spawn_enemy():
    if len(enemies) >= max_enemies:
        return
    
    x = random.random() * (width - 4) + 2
    y = -2  # Start above screen
    
    enemy_type = random.choice(["fighter", "bomber", "scout"])
    
    if enemy_type == "fighter":
        char = "▽"
        velocity_x = (random.random() - 0.5) * 5.0
        velocity_y = 5.0
    elif enemy_type == "bomber":
        char = "▼"
        velocity_x = (random.random() - 0.5) * 2.0
        velocity_y = 3.0
    else:  # scout
        char = "△"
        velocity_x = (random.random() - 0.5) * 10.0
        velocity_y = 8.0
    
    enemies.append(Enemy(x, y, velocity_x, velocity_y, char, enemy_type))
```

### Particle System

```python
def spawn_explosion(x: float, y: float):
    for _ in range(particle_count):
        angle = random.random() * 2 * math.pi
        speed = random.random() * 10.0
        
        particles.append(Particle(
            x=x,
            y=y,
            velocity_x=math.cos(angle) * speed,
            velocity_y=math.sin(angle) * speed,
            life=0.5 + random.random() * 0.5,
            char=random.choice(["*", "+", "x", ".", "°"]),
            color=random.choice(["red", "yellow", "orange"])
        ))
```

## Rendering

### Render Layers

```
1. Clear screen
2. Render starfield (background)
3. Render particles (explosions)
4. Render enemies
5. Render player
6. Render lasers
7. Render HUD (score, lives)
```

### Player Ship

Ship character changes based on movement (banking effect):

```
Left:   /  (banking left)
Center: |  (straight)
Right:  \  (banking right)
```

## Keyboard Controls

| Key | Action |
|-----|--------|
| `←` | Move left |
| `→` | Move right |
| `↑` | Move up |
| `↓` | Move down |
| `Space` | Fire laser |
| `Esc` | Exit game |
| `p` | Pause/resume |
| `r` | Restart game (when game over) |

## Implementation Details

### Initialization

```python
async def initialize(self, renderer) -> bool:
    if not await super().initialize(renderer):
        return False
    
    # Get terminal dimensions
    width, height = renderer.get_terminal_size()
    
    # Create space shooter renderer
    self.space_renderer = SpaceShooterRenderer(width, height)
    
    return True
```

### Frame Rendering

```python
async def render_frame(self, delta_time: float) -> bool:
    # Update game state
    self.space_renderer.update(delta_time)
    
    # Get rendered output
    output = self.space_renderer.render()
    
    # Display
    self.renderer.clear()
    self.renderer.write(output)
    
    return True  # Continue until game over or exit
```

### Keyboard Input

```python
def handle_key(self, key_press: KeyPress) -> None:
    if key_press.name == "Escape":
        self.active = False
    elif key_press.name == "ArrowLeft":
        self.space_renderer.move_player(-1, 0)
    elif key_press.name == "ArrowRight":
        self.space_renderer.move_player(1, 0)
    elif key_press.name == "ArrowUp":
        self.space_renderer.move_player(0, -1)
    elif key_press.name == "ArrowDown":
        self.space_renderer.move_player(0, 1)
    elif key_press.name == "Space":
        self.space_renderer.fire_laser()
```

## HUD

### Heads-Up Display

```
┌─────────────────────────────────────────┐
│ SCORE: 1500   LIVES: ■■□          │
└─────────────────────────────────────────┘
```

### Game Over Screen

```
╔════════════════════════════════════╗
║                                      ║
║            GAME OVER                  ║
║                                      ║
║           FINAL SCORE                 ║
║              3500                    ║
║                                      ║
║         Press 'r' to restart          ║
║         Press 'Esc' to exit          ║
║                                      ║
╚════════════════════════════════════╝
```

## Implementation Checklist

### Core Functionality
- [x] Starfield with parallax
- [x] Player ship movement
- [x] Enemy spawning and movement
- [x] Laser shooting
- [x] Collision detection
- [x] Particle explosion effects
- [x] Score tracking
- [x] Lives system

### Configuration
- [x] Player speed
- [x] Laser speed
- [x] Enemy speed
- [x] Spawn rate
- [x] Max enemies
- [x] Lives count

### Controls
- [x] Arrow key movement
- [x] Space to fire
- [x] Pause/resume
- [x] Restart
- [x] Exit

## Best Practices

### Performance

- **Object pooling**: Reuse particles and lasers when possible
- **Simple collision**: Distance-based (faster than box/box)
- **Efficient rendering**: Use character grid approach
- **Frame independence**: Use delta_time for all movement

### Gameplay

- **Fair difficulty**: Start easy, increase gradually
- **Responsive controls**: No input lag
- **Clear feedback**: Visual cues for hits, explosions
- **Rewarding**: Score system with progression

## Related Documentation

- /docs/reference/fullscreen-framework.md - Full-screen plugin framework
- /docs/reference/particle-systems.md - Particle systems
- /docs/plugins/core/matrix_plugin_spec.md - Matrix rain plugin

## Future Enhancements

### Planned Features

- [ ] Power-ups (speed boost, shield, multi-shot)
- [ ] Boss battles
- [ ] High score saving
- [ ] Multiple levels with different enemies
- [ ] Sound effects
- [ ] Two-player mode
- [ ] Weapon upgrades

### Gameplay Variations

- [ ] Survival mode (infinite enemies)
- [ ] Time attack (score as much as possible in time limit)
- [ ] Challenge mode (specific enemy patterns)

## Troubleshooting

### Game Too Fast

1. Decrease `player_speed`, `laser_speed`, `enemy_speed`
2. Increase target FPS limit
3. Check delta_time calculation

### Game Too Slow

1. Increase speed settings
2. Decrease `max_enemies` to reduce processing
3. Check terminal size (smaller = faster)

### Controls Not Responsive

1. Verify key parser is receiving input
2. Check for input lag (terminal settings)
3. Ensure plugin is in active state

### Enemies Don't Spawn

1. Check `spawn_rate` configuration
2. Verify `max_enemies` limit
3. Check if spawning logic is being called

## Extension Points

### Custom Enemy Types

Add new enemy types:

```python
def _spawn_enemy():
    # Add new enemy types
    enemy_type = random.choice(["fighter", "bomber", "scout", "custom"])
    
    if enemy_type == "custom":
        char = "◆"
        velocity_x = 0  # No horizontal movement
        velocity_y = 2.0  # Slow descent
        # Add custom behavior (e.g., shoots in bursts)
```

### Custom Weapons

Add weapon types:

```python
def fire_laser(self):
    weapon_type = self.current_weapon
    
    if weapon_type == "spread":
        # Fire 3 lasers in spread pattern
        for angle in [-0.2, 0, 0.2]:
            lasers.append(Laser(..., velocity_x=angle * laser_speed))
    elif weapon_type == "laser":
        # Single straight shot
        lasers.append(Laser(..., velocity_x=0))
```

### Custom Power-Ups

Implement power-up system:

```python
@dataclass
class PowerUp:
    x: float
    y: float
    type: str  # "speed", "shield", "multi", "health"
    char: str

def spawn_powerup(x: float, y: float):
    powerup_types = ["speed", "shield", "multi", "health"]
    powerup_type = random.choice(powerup_types)
    
    if powerup_type == "speed":
        char = "⚡"
    elif powerup_type == "shield":
        char = "©"
    elif powerup_type == "multi":
        char = "✦"
    else:  # health
        char = "♥"
    
    powerups.append(PowerUp(x, y, powerup_type, char))
```
