Author SHA1 Message Date
John Doe 523a09a090 feat: add support for keybindings configuration in JSON format 2025-10-18 00:22:13 +02:00
John Doe 43c3b872f2 Enhance mobile experience and touch controls for Mice! game
- Updated index.html to improve layout responsiveness using Bootstrap 5.
- Added touch controls for mobile devices, including a D-Pad and action buttons.
- Implemented visual feedback for touch interactions with scale animations.
- Created a new test_controls.html for testing touch controls functionality.
- Added a comprehensive MOBILE_README.md detailing mobile features, optimizations, and testing instructions.
- Improved accessibility and usability with user-scalable settings and touch-action prevention.
- Enhanced modal for profile creation with Bootstrap styling.
2025-10-18 00:08:29 +02:00
John Doe cc599c342c feat: implement start dialog rendering for Pyodide compatibility 2025-10-17 23:40:00 +02:00
John Doe 146dc04c30 feat: add keybindings configuration for game controls and menus 2025-10-17 23:11:57 +02:00
John Doe 88c160a131 fix: remove extraneous markdown syntax from README.md 2025-10-17 23:00:55 +02:00
John Doe 576c633be5 Implement GameWindow class with SDL2 integration for rendering, audio, and input handling
- Added GameWindow class to manage game window creation and rendering.
- Integrated SDL2 for window management, rendering, and audio playback.
- Implemented methods for loading images, creating textures, and drawing graphics.
- Added font management for dynamic text rendering.
- Included input handling for keyboard, mouse, and joystick events.
- Implemented a main game loop to handle updates and rendering.
- Added support for special effects like white flash and blood splatter.
- Created utility methods for managing game state and performance.
2025-10-17 22:54:55 +02:00
John Doe 3812d36cd6 feat: add favicon generator and Pyodide profile sync integration 2025-10-17 22:47:13 +02:00
684 changed files with 5124 additions and 235035 deletions
-82
View File
@@ -1,82 +0,0 @@
AUTHOR INFORMATION
Developer: Matteo Benedetto (@Enne2)
- Computer engineer, Italian
- Systems designer and architect
- Working in aerospace industry (e-geos S.p.A.)
- Location: Italy
- GitHub: https://github.com/Enne2
- Website: http://enne2.net
CRITICAL COMMUNICATION RULES
NEVER claim success without proof:
Don't say "FATTO!", "PERFETTO!", "Done!" unless you have verified the code works
Don't start responses with exclamations like "PERFETTO!", "Ottimo!", "Fantastico!", "Eccellente!" - they feel disingenuous
Be direct and honest - just explain what you did clearly
Let the user verify results before celebrating
ALWAYS:
Test before claiming success
Be honest about uncertainty
Search web/documentation if unsure
Wait for user confirmation
TERMINAL COMMAND EXECUTION RULES
When executing scripts or tests in terminal:
1. ALWAYS use isBackground=false for test scripts and commands that produce output to analyze
2. WAIT for command completion before reading results
3. After running a test/benchmark, read terminal output with get_terminal_output before commenting
4. Never assume command success - always verify with actual output
Examples:
- ✓ run_in_terminal(..., isBackground=false) → wait → get_terminal_output → analyze
- ✗ run_in_terminal(..., isBackground=true) for tests (you won't see the output!)
CONSULTATION vs IMPLEMENTATION
When the user asks for advice, tips, or consultation:
- ONLY answer the question - do not take actions or run commands
- Provide recommendations and explain options
- Wait for explicit instruction before implementing anything
When the user gives a command or asks to implement something:
- Proceed with implementation and necessary tool usage
- Take action as requested
SYSTEM DISCOVERY REQUIREMENTS
BEFORE running any terminal commands or making system assumptions:
1. CHECK the development environment:
- Use `uname -a` to identify OS and architecture
- Use `python --version` or `python3 --version` to detect Python version
- Check for virtual environment indicators (venv/, .venv/)
- Verify package managers available (pip, apt, brew, etc.)
2. UNDERSTAND the project structure:
- Read README.md files for project-specific setup instructions
- Check for configuration files (requirements.txt, package.json, etc.)
- Identify runtime dependencies and special requirements
3. ADAPT commands accordingly:
- Use correct Python interpreter (python vs python3)
- Apply proper paths (absolute vs relative)
- Follow project-specific conventions documented in workspace
NEVER assume system configuration - always verify first.
Python Virtual Environment Workflow
IMPORTANT: This project uses a Python virtual environment located at ./venv.
Standard Command Pattern:
cd /home/enne2/Sviluppo/shader && source venv/bin/activate && python main.py
DO NOT run Python scripts without activating the virtual environment.
@@ -1,107 +0,0 @@
---
applyTo: "tools/vernon/**,assets/Rat/**"
---
# Pixel Art Sprite Workflow — mice project
## Strumenti disponibili
| Script | Uso |
|--------|-----|
| `tools/vernon/image_to_json.py <INPUT.png> <OUTPUT.json>` | Converte PNG → matrice JSON RGBA 64×64 |
| `tools/vernon/json_to_png.py <INPUT.json> <OUTPUT.png>` | Converte matrice JSON RGBA → PNG |
Entrambi usano Pillow e richiedono il `venv` attivo:
```bash
source .venv/bin/activate
```
## Formato JSON
```json
{
"source": "BMP_BOMB0.png",
"width": 64,
"height": 64,
"mode": "RGBA",
"pixels": [
[ [R, G, B, A], ... ], // riga 0, 64 pixel
... // 64 righe totali
]
}
```
Ogni pixel è `[R, G, B, A]` con valori 0–255.
## Convenzioni cromatiche del gioco
- **Colore trasparente (chromakey):** `[128, 128, 128, 192]` — usato come sfondo, il motore lo rende hidden
- **Alpha standard:** `192` per tutti i pixel visibili (coerente con gli asset originali)
## Workflow iterativo di redesign (passi 0–4)
```
0. BACKUP → prima di sovrascrivere, copia l'originale:
cp assets/Rat/<NAME>.png assets/Rat/backup/<NAME>_original.png
1. image_to_json.py → esamina JSON e PNG originale
2. capire struttura: sfondo, palette, forma principale
3. modificare JSON (o generarlo via script Python) con:
- più livelli di shading (8+ valori invece di 3)
- dettagli geometrici aggiuntivi (texture, bordi, ombre interne)
- palette più ricca mantenendo stile pixel art (bordi netti, no anti-alias)
4. json_to_png.py → valuta risultato visivo; se non soddisfacente, torna a 3
```
## Pattern Python per generare JSON programmaticamente
```python
import json, math
from pathlib import Path
W, H = 64, 64
A = 192 # alpha standard
def px(r, g, b): return [r, g, b, A]
TRANSPARENT = px(128, 128, 128)
grid = [[TRANSPARENT[:] for _ in range(W)] for _ in range(H)]
def put(x, y, col):
if 0 <= x < W and 0 <= y < H:
grid[y][x] = col[:]
# ... disegna su grid ...
data = {"source": "BMP_X.png", "width": W, "height": H, "mode": "RGBA", "pixels": grid}
Path("tools/vernon/output/BMP_X_v2.json").write_text(json.dumps(data, indent=2))
```
## Tecniche pixel art a 64×64
- **Shading sferico:** calcola normale + dot product con luce per N livelli di grigio discreti
- **Rope/miccia:** traccia bezier quadratica, alterna 2–3 toni in sequenza (effetto intrecciato)
- **Scintilla:** pixel centrali chiari (bianco/giallo), bordi che degradano in arancio → rosso
- **Outline:** bordo di 1px nero (`[0,0,0,192]`) attorno a tutte le forme principali
- **Nessun anti-aliasing:** ogni pixel è un colore solido discreto della palette scelta
## Asset da redesignare (tutti 64×64)
| File | Gruppo |
|------|--------|
| `BMP_BOMB0.png` … `BMP_BOMB4.png` | Animazione bomba (0=quieta, 4=accesa) |
| `BMP_1_GRASS_1.png` … `BMP_1_GRASS_4.png` | Tile erba tema 1 (verde) — **redesignate con FBM 7-toni** |
| `BMP_2_GRASS_1.png` … `BMP_2_GRASS_4.png` | Tile erba tema 2 (secca/autunnale) |
| `BMP_3_GRASS_1.png` … `BMP_3_GRASS_4.png` | Tile erba tema 3 (dungeon/pietra) |
| `BMP_4_GRASS_1.png` … `BMP_4_GRASS_4.png` | Tile erba tema 4 (fuoco/lava) |
| `BMP_GAS.png`, `BMP_GAS_{DIR}.png` | Gas generico + 4 direzioni |
| `BMP_EXPLOSION.png`, `BMP_EXPLOSION_{DIR}.png` | Esplosione generica + 4 direzioni |
| `BMP_NUCLEAR.png` | Fungo nucleare |
| `BMP_POISON.png` | Veleno |
## Note sull'animazione BOMB (frame 0–4)
- `BOMB0`: bomba ferma, scintilla piccola a riposo
- `BOMB1`–`BOMB3`: miccia che brucia (la scintilla avanza verso il corpo, la corda si accorcia)
- `BOMB4`: quasi esplode (glow rosso/arancio sul corpo, scintilla grande)
Per i frame animati: mantieni identici corpo + miccia, varia solo posizione/dimensione scintilla e eventuale glow progressivo.
-40
View File
@@ -1,40 +0,0 @@
# Project Guidelines
## UI Preview Tool
When editing the start menu, pause menu, or level intro UI, generate a real preview image before judging layout changes.
Use [tools/render_menu_preview.py](tools/render_menu_preview.py) instead of relying on mental layout or ad-hoc screenshots. The tool renders the actual SDL scene and saves a PNG from the real renderer.
Typical command:
```bash
/home/enne2/dev/mice/.venv/bin/python tools/render_menu_preview.py \
--output /tmp/mice_start_preview.png \
--screen start \
--difficulty normal \
--resolution 1280x720
```
Supported screens:
- `start`
- `pause`
- `level_intro`
Useful flags:
- `--difficulty easy|normal|hard`
- `--resolution WIDTHxHEIGHT`
- `--output /path/to/file.png`
- `--seed N` for deterministic previews
- `--animation-ms N` to choose the GIF frame timestamp for the start menu
Workflow when touching menu layout:
1. Edit the menu code.
2. Run the preview tool for the relevant screen.
3. Inspect the generated PNG.
4. Iterate until spacing and readability are correct.
The preview tool is intended for fast visual feedback and should be preferred before launching a full interactive game session for menu-only changes.
+105
View File
@@ -0,0 +1,105 @@
# 🐭 Mice! - Mobile Version
## Caratteristiche Mobile
Il gioco è stato adattato per dispositivi mobile con le seguenti caratteristiche:
### 📱 Layout Responsive con Bootstrap 5
- **Desktop (≥768px)**: Layout a due colonne con canvas a sinistra e controlli a destra
- **Mobile (<768px)**: Layout verticale con controlli touch sotto il canvas
### 🎮 Controlli Touch
#### Pad Direzionale (D-Pad)
- **Freccia Su**: Movimento in alto
- **Freccia Giù**: Movimento in basso
- **Freccia Sinistra**: Movimento a sinistra
- **Freccia Destra**: Movimento a destra
#### Pulsanti Azione
- **💣 Bomb (Spazio)**: Piazza una bomba
- **⚠️ Mine (M)**: Piazza una mina
- **☁️ Gas (G)**: Rilascia gas velenoso
- **☢️ Nuclear (N)**: Bomba nucleare (una volta per partita)
- **⏸️ Pause (P)**: Metti in pausa il gioco
### 🎨 Design Adattivo
- Canvas responsive che si adatta alla larghezza dello schermo
- Pulsanti touch ottimizzati per il tocco (60px di altezza minima)
- Feedback visivo su touch (scale animation)
- Interfaccia dark theme ottimizzata per mobile
### 🔧 Ottimizzazioni
- `user-scalable=no` per prevenire lo zoom accidentale
- `touch-action: none` sui controlli per prevenire lo scroll durante il gioco
- Prevenzione del menu contestuale su long press
- Eventi sia touch che mouse per compatibilità con desktop
## Test
Per testare su mobile:
1. Avvia un server web locale:
```bash
python -m http.server 8000
```
2. Apri il browser sul tuo smartphone e naviga a:
```
http://[IL-TUO-IP-LOCALE]:8000/index.html
```
3. Verifica:
- [ ] I controlli touch sono visibili solo su mobile
- [ ] Il D-Pad risponde al tocco
- [ ] I pulsanti azione funzionano correttamente
- [ ] Il canvas si adatta correttamente
- [ ] Non c'è zoom accidentale durante il gioco
## Compatibilità Browser
- ✅ Chrome/Edge Mobile (Android/iOS)
- ✅ Safari Mobile (iOS)
- ✅ Firefox Mobile (Android)
- ✅ Samsung Internet
## Note Tecniche
### Simulazione Eventi Tastiera
I controlli touch simulano eventi `KeyboardEvent` nativi per garantire compatibilità con il codice Python/Pygame esistente:
```javascript
function simulateKeyPress(key, type = 'keydown') {
const event = new KeyboardEvent(type, {
key: key,
code: key === ' ' ? 'Space' : `Key${key.toUpperCase()}`,
keyCode: key.charCodeAt(0),
which: key.charCodeAt(0),
bubbles: true,
cancelable: true
});
document.dispatchEvent(event);
canvas.dispatchEvent(event);
}
```
### Bootstrap Components
- **Grid System**: `container-fluid`, `row`, `col-*` per layout responsive
- **Modal**: Per la creazione profilo
- **Form Controls**: Input, select, checkbox con stili dark
- **Progress Bar**: Per indicare il caricamento degli asset
- **Icons**: Bootstrap Icons per le frecce direzionali
## Miglioramenti Futuri
- [ ] Supporto vibrazione per feedback tattile
- [ ] Joystick virtuale con movimento analogico
- [ ] Gesture swipe per movimento rapido
- [ ] Orientamento landscape automatico su mobile
- [ ] PWA manifest per installazione come app nativa
- [ ] Service worker per gioco offline
+604 -228
View File
@@ -1,30 +1,79 @@
# Mice!
Mice! is a strategic game where players must kill rats with bombs before they reproduce and become too numerous. The game is a clone of the classic game Rats! for Windows 95.
## Compatibility
*It's developed in Python 3.13, please use it*
*Developed and tested with Python 3.11+*
## Features
- **Maze Generation**: Randomly generated mazes using Depth First Search (DFS) algorithm.
- **Original Level Support**: Loads the original `level.dat` from `assets/Rat/level.dat` when present and falls back to `maze.json` otherwise.
- **Units**: Different types of units such as rats, bombs, and points with specific behaviors.
- **Graphics**: Custom graphics for maze tiles, units, and effects.
- **Sound Effects**: Audio feedback for various game events.
- **Scoring**: Points system to track player progress.
- **Performance**: Optimized collision detection system supporting 200+ simultaneous units using NumPy vectorization.
- **Maze Generation**: Randomly generated mazes using Depth First Search (DFS) algorithm
- **Multiple Unit Types**: Rats, bombs, mines, gas, and collectible points with unique behaviors
- **User Profile System**: Track scores, achievements, and game statistics
- **Graphics**: Custom graphics for maze tiles, units, and effects
- **Sound Effects**: Audio feedback for various game events
- **Scoring**: Points system with leaderboards and profile integration
- **Dual Rendering Engines**: Support for both SDL2 and Pygame
## Utilities
## Rendering Engine Options
### Microphone Visualizer
The game now supports **two rendering backends** with identical interfaces:
A small SDL2 microphone visualizer is available in `tools/mic_visualizer.py`.
### 1. SDL2 Backend (`engine/sdl2_layer.py`)
- **Original implementation** using PySDL2
- Hardware-accelerated rendering via SDL2
- Optimized for performance on Linux systems
- Direct access to low-level graphics features
- List capture devices: `python tools/mic_visualizer.py --list-devices`
- Open the default microphone: `python tools/mic_visualizer.py`
- Open a specific input: `python tools/mic_visualizer.py --device-index 1`
- On muOS, use `mice_mic.sh` as a launcher in `ROMS/Ports` and it will run fullscreen with gamepad quit support.
### 2. Pygame Backend (`engine/pygame_layer.py`) ⭐ **NEW**
- **Drop-in replacement** for SDL2 backend
- More portable and easier to set up
- Better cross-platform support (Windows, macOS, Linux)
- Simplified dependency management
- Identical API - no game code changes needed
### Switching Between Rendering Engines
To switch from SDL2 to Pygame, simply change the import in `rats.py`:
```python
# Using SDL2 (original)
from engine import maze, controls, graphics, sdl2_layer as engine, unit_manager, scoring
# Using Pygame (new)
from engine import maze, controls, graphics, pygame_layer as engine, unit_manager, scoring
```
That's it! No other code changes are required thanks to the compatible interface design.
## Browser / Pyodide Support (experimental)
- The project includes an experimental browser build that runs the game in WebAssembly using Pyodide and a bundled pygame-ce build. This supports running the game inside modern browsers (desktop only) and is intended for demos and lightweight testing.
- Key points:
- `index.html` contains the Pyodide bootstrap, asset loader and a JS-driven game loop that calls into the Python game tick function so the UI stays responsive.
- The browser integration includes a small profile sync mechanism so profiles saved by the Python code (inside Pyodide's virtual FS) are synchronized back to browser `localStorage`.
- A tiny utility `tools/create_favicon.py` generates `favicon.ico` from the game's `assets` if you want a browser favicon for local hosting.
Use the browser demo for quick sharing and testing, but prefer the native Python + SDL2/pygame backends for actual play and development.
## Cleanup notes
This repository contains some auxiliary files used during development and for old/demo flows. If you want me to remove unused items, I can safely delete them in a single branch/commit after you confirm. Suggested candidates are listed in the developer checklist below.
### Developer cleanup checklist (proposed deletions)
These files look like auxiliary or duplicate/demo artifacts and can be removed to reduce noise. I'll only delete them if you confirm.
- `BROWSER_GAME_README.md` — duplicate/demo readme for browser build
- `BROWSER_SETUP_QUICK_START.md` — quick-start for browser demo
- `PYGAME_BACKEND_GUIDE.md` — documentation duplicate
- `pyodide-guide.html` — local demo HTML (we already ship `index.html`)
- `browser-game-setup.sh` and `play.sh` — demo scripts not used in CI
- `assets/asset-manifest.json`, `assets/sound-manifest.json` — generated manifests (can be regenerated)
- `engine/pygame_layer.py` and `engine/sdl2_layer.py` — ensure you want to keep one backend; if you prefer only SDL2 or only Pygame, remove the other
If you'd like me to proceed, reply with "delete these files" and I will create a branch, remove them, and push the change.
## Engine Architecture
@@ -32,275 +81,614 @@ The Mice! game engine is built on a modular architecture designed for flexibilit
### Core Engine Components
#### 1. **Collision System** (`engine/collision_system.py`)
- **CollisionSystem Class**: High-performance collision detection using NumPy vectorization
#### 1. **Rendering System** (`engine/sdl2_layer.py` or `engine/pygame_layer.py`)
- **GameWindow Class**: Central rendering manager
- **Features**:
- Spatial hashing with grid-based lookups (O(1) average case)
- Support for 6 collision layers (RAT, BOMB, GAS, MINE, POINT, EXPLOSION)
- Hybrid approach: simple iteration for <10 candidates, NumPy vectorization for ≥10
- Pre-allocated arrays with capacity management to minimize overhead
- Area queries for explosion damage (get_units_in_area)
- Cell-based queries for gas/mine detection (get_units_in_cell)
- **Performance**:
- Handles 200+ units at ~3ms per frame
- Reduces collision checks from O(n²) to O(n) using spatial partitioning
- Vectorized distance calculations for massive parallel processing
#### 2. **Rendering System** (`engine/sdl2.py`)
- **GameWindow Class**: Central rendering manager using SDL2
- **Features**:
- Hardware-accelerated rendering via SDL2
- Hardware-accelerated rendering
- Texture management and caching
- Sprite rendering with transparency support (SDL_BLENDMODE_BLEND for alpha blending)
- Sprite rendering with transparency support
- Text rendering with custom fonts
- Resolution-independent scaling
- Fullscreen/windowed mode switching
- Blood stain rendering with RGBA format and proper alpha channel
- **Optimizations**:
- Cached viewport bounds to avoid repeated calculations
- Pre-cached image sizes for all assets at startup
- Blood overlay layer system (no background regeneration needed)
- Pre-generated blood stain pool (10 variants) for instant spawning
- Dynamic blood splatter effects
- White flash screen effects
- **Implementation**:
- Uses SDL2 renderer for efficient GPU-accelerated drawing
- Implements double buffering for smooth animation
- Manages texture atlas for optimized memory usage
- Handles viewport transformations for different screen resolutions
- Double buffering for smooth animation
- Texture atlas for optimized memory usage
- Viewport transformations for different screen resolutions
- Alpha blending for transparency effects
#### 3. **Input System** (`engine/controls.py`)
#### 2. **Input System** (`engine/controls.py`)
- **KeyBindings Class**: Handles all user input
- **Features**:
- Keyboard input mapping and handling
- Joystick/gamepad support
- Configurable key bindings
- Input state management
- Configurable key bindings via YAML/JSON
- Context-sensitive input (menu vs. gameplay)
- **Implementation**:
- Event-driven input processing
- Key state buffering for smooth movement
- Support for multiple input devices simultaneously
- Customizable control schemes
- Dynamic key binding system with action mapping
#### 3. **Map System** (`engine/maze.py`)
- **Map Class**: Manages the game world structure
- **Features**:
- Maze data loading and parsing
- DAT archive parsing for the original 32 built-in RATS levels
- Maze data loading from JSON
- Collision detection system
- Tile-based world representation
- Pathfinding support for AI units
- **Implementation**:
- Grid-based coordinate system
- Efficient collision detection using spatial partitioning
- Support for different tile types (walls, floors, special tiles)
- Integration with maze generation algorithms
- Efficient collision detection
- Support for walls and floor tiles
- Integration with procedural maze generation
#### 4. **Audio System**
- **Sound Management**: Handles all audio playback
- **Features**:
- Sound effect playback
- Sound effect playback with multiple channels
- Background music support
- Volume control
- Multiple audio channels
- Per-channel audio mixing
- **Implementation**:
- Uses subprocess module for audio playback
- Asynchronous sound loading and playing
- Audio file format support (WAV, MP3, OGG)
- SDL2 backend: Native SDL2 audio system
- Pygame backend: pygame.mixer module
- Support for WAV format audio files
- Multiple simultaneous sound channels (base, effects, music)
#### 5. **Unit Management System** (`engine/unit_manager.py`)
- **UnitManager Class**: Manages all game entities
- **Features**:
- Dynamic unit spawning and removal
- Position tracking for collision detection
- Resource management (ammo, items)
- **Implementation**:
- UUID-based unique identifiers
- Efficient lookup structures
- Automatic cleanup on unit death
#### 6. **User Profile System** (`engine/user_profile_integration.py`)
- **UserProfileIntegration Class**: Manages player profiles
- **Features**:
- Multiple user profile support
- Score tracking and leaderboards
- Game statistics (games played, wins, best score)
- Device-specific profiles
- Global leaderboard integration
### Game Loop Architecture
The main game loop follows an optimized 4-pass pattern:
1. **Pre-Registration Phase**: Populate collision system with unit positions before movement
2. **Update Phase**: Execute unit logic and movement (bombs/gas can now query collision system)
3. **Re-Registration Phase**: Update collision system with new positions after movement
4. **Collision & Render Phase**: Check collisions and draw all game objects
The main game loop follows the standard pattern:
1. **Input Processing**: Capture and process user input
2. **Update Phase**: Update game state, unit logic, and physics
3. **Render Phase**: Draw all game objects to the screen
4. **Timing Control**: Maintain consistent frame rate (target 60 FPS)
```
Pre-Register → Move → Re-Register → Collisions → Render → Present → Repeat
Input → Update → Render → Present → Repeat
```
This architecture ensures weapons (bombs, gas) can detect victims during their execution phase while maintaining accurate collision data.
## Units Implementation
The game uses an object-oriented approach for all game entities. Each unit type inherits from a base unit class and implements specific behaviors.
### Base Unit Architecture
### Base Unit Architecture (`units/unit.py`)
All units share common properties and methods:
- **Position and Movement**: 2D coordinates with movement capabilities
- **Unique Identification**: UUID-based unique identifiers
- **Collision Detection**: Bounding box collision system
- **State Management**: Current state tracking (alive, dead, exploding, etc.)
- **Rendering**: Sprite-based visual representation
All units share common properties and methods defined in the abstract `Unit` class:
**Common Attributes**:
- `id` (UUID): Unique identifier for each unit
- `position` (tuple): Current (x, y) grid coordinates
- `position_before` (tuple): Previous position for smooth movement
- `age` (int): Time alive in game ticks
- `speed` (float): Movement speed multiplier
- `partial_move` (float): Sub-cell movement progress (0.0 to 1.0)
- `bbox` (tuple): Bounding box for collision detection
- `stop` (int): Remaining ticks of immobilization
**Abstract Methods** (must be implemented by subclasses):
- `move()`: Update unit position and state each frame
- `draw()`: Render the unit on screen
**Concrete Methods**:
- `collisions()`: Handle interactions with other units
- `die(score=None)`: Remove unit from game and handle cleanup
### Unit Types Implementation
#### 1. **Rat Units** (`units/rat.py`)
**Base Rat Class**:
- **AI Behavior**: Implements pathfinding using A* algorithm
- **Movement**: Grid-based movement with smooth interpolation
- **State Machine**: Multiple states (wandering, fleeing, reproducing)
- **AI Behavior**: Pathfinding with direction memory to avoid backtracking
- **Movement**: Smooth interpolated movement between grid cells
- **Lifecycle**: Age-based behavior changes (baby → adult → elder)
- **Gas Vulnerability**: Can be killed by poison gas
**Male Rat Class**:
- **Reproduction Logic**: Seeks female rats for mating
- **Territorial Behavior**: Defends territory from other males
- **Lifespan Management**: Age-based death system
- **Reproduction**: Seeks female rats for mating
- **Fighting**: Territorial combat with other males
- **Adult Threshold**: Becomes fertile after 200 game ticks
**Female Rat Class**:
- **Pregnancy System**: Gestation period simulation
- **Offspring Generation**: Creates new rat units
- **Maternal Behavior**: Protects offspring from threats
- **Pregnancy System**: 500-tick gestation period
- **Offspring Generation**: Spawns baby rats at intervals
- **Maternal Behavior**: Protects territory from threats
**Implementation Details**:
```python
# Optimized rat behavior with pre-calculated render positions
class Rat:
class Rat(Unit):
def move(self):
self.process_ai() # Decision making
self.handle_movement() # Position updates
self._update_render_position() # Cache render coordinates
def collisions(self):
# Use optimized collision system with vectorization
collisions = self.game.collision_system.get_collisions_for_unit(
self.id, self.bbox, self.collision_layer
)
# Process only Rat-to-Rat collisions
for _, other_id in collisions:
other_unit = self.game.get_unit_by_id(other_id)
if isinstance(other_unit, Rat):
self.handle_rat_collision(other_unit)
def draw(self):
# Use cached render positions (no recalculation)
self.game.render_engine.draw_image(
self.render_x, self.render_y, self.sprite, tag="unit"
)
self.age += 1
if self.gassed > 35:
self.choked() # Death by gas
if self.age == AGE_THRESHOLD:
self.speed *= SPEED_REDUCTION # Slow down with age
self.partial_move += self.speed
if self.partial_move >= 1:
self.position = self.find_next_position()
self.partial_move = 0
```
#### 2. **Bomb Units** (`units/bomb.py`)
**Bomb Class**:
- **Timer System**: Countdown mechanism before explosion
- **Placement Logic**: Player-controlled positioning
- **Damage Calculation**: Blast radius and damage computation
**Timer Bomb Class**:
- **Countdown System**: Visual timer (4 stages) before explosion
- **Chain Reactions**: Triggers nearby bombs
- **Directional Blast**: Explodes in 4 cardinal directions until hitting walls
**Nuclear Bomb Class**:
- **Instant Kill**: Destroys all rats on the map
- **White Flash Effect**: Screen flash on detonation
- **Single Use**: Limited to 1 per game
**Explosion Class**:
- **Visual Effects**: Animated explosion graphics
- **Damage Dealing**: Affects units within blast radius
- **Temporary Entity**: Self-destructs after animation
- **Temporary Effect**: Short-lived visual and damage entity
- **Kill Radius**: Destroys all rats in the same cell
- **Score Bonus**: Awards points for each rat killed
**Implementation Details**:
- **State Machine**: Armed → Countdown → Exploding → Cleanup
- **Optimized Damage System**: Uses collision_system.get_units_in_area() with vectorized distance calculations
- **Effect Propagation**: Chain reaction support for multiple bombs
- **Area Query Example**:
```python
def die(self):
# Collect explosion positions
explosion_positions = self.calculate_blast_radius()
# Query all rats in blast area using vectorized collision system
victims = self.game.collision_system.get_units_in_area(
explosion_positions,
layer_filter=CollisionLayer.RAT
)
for unit_id in victims:
rat = self.game.get_unit_by_id(unit_id)
if rat:
rat.die()
class Timer(Bomb):
def move(self):
self.age += 1
if self.age > 160: # 160 ticks = explosion
self.die(unit=self, score=10)
def die(self, unit=None, score=None):
# Create explosion and propagate in 4 directions
for direction in ["N", "S", "E", "W"]:
# Spread until wall
while not self.game.map.is_wall(x, y):
self.game.spawn_unit(Explosion, (x, y))
```
#### 3. **Point Units** (`units/points.py`)
#### 3. **Mine Units** (`units/mine.py`)
**Mine Class**:
- **Arming Delay**: Becomes active after placement delay
- **Contact Trigger**: Detonates when rat steps on it
- **Gas Release**: Creates poison gas clouds on detonation
- **Limited Supply**: Max 4 mines at a time
#### 4. **Gas Units** (`units/gas.py`)
**Gas Cloud Class**:
- **Lingering Effect**: Stays in place for duration
- **Poison Damage**: Accumulates damage on rats over time
- **Chaining**: Can spawn additional gas clouds
- **Visual Effect**: Semi-transparent gas sprite
#### 5. **Point Units** (`units/points.py`)
**Point Class**:
- **Collection Mechanics**: Player interaction system
- **Value System**: Different point values for different achievements
- **Visual Feedback**: Pickup animations and effects
- **Collection Mechanics**: Auto-collected by player cursor
- **Value System**: Different point values (5, 10, 25, 50, 100)
- **Timed Existence**: Disappears after ~5 seconds
- **Score Tracking**: Updates player score on collection
### Unit Interaction System
Units interact through a centralized collision and event system:
1. **Collision Detection**:
- **Spatial hashing**: Grid-based broad phase with O(1) lookups
- **NumPy vectorization**: Parallel distance calculations for large candidate sets
- **Hybrid approach**: Direct iteration for <10 candidates, vectorization for ≥10
- **Layer filtering**: Efficient collision filtering by unit type (RAT, BOMB, GAS, etc.)
- **Area queries**: Optimized explosion and gas effect calculations
#### Collision Detection
- **Spatial Hashing**: Grid-based lookup for nearby units
- **Bounding Box**: Precise pixel-perfect collision detection
- **Overlap Tolerance**: Small margin to prevent jittering
- **Bi-directional**: Both units check for collisions
2. **Event System**:
- Unit death events
- Reproduction events
- Explosion events (with area damage)
- Point collection events (90 frames lifetime ~1.5s at 60 FPS)
#### Event System
- **Death Events**: Spawn points, trigger explosions, update score
- **Reproduction Events**: Create new rat units
- **Explosion Events**: Chain reactions, area damage
- **Collection Events**: Point pickup, ammo refill
3. **AI Communication**:
- Shared pathfinding data
- Pheromone trail system for rat behavior
- Danger awareness (bombs, explosions)
4. **Spawn Protection**:
- Rats won't spawn on cells occupied by weapons (mines, bombs, gas)
- Automatic fallback to adjacent cells if primary position blocked
- Prevents unfair early-game deaths
#### AI Communication
- **Position Tracking**: `unit_positions` dictionary for fast lookup
- **Shared Pathfinding**: Avoid blocked cells
- **Danger Awareness**: Rats flee from explosions
## Technical Details
- **Language**: Python 3.13
### Language & Core Libraries
- **Python**: 3.11+ (recommended)
- **Rendering**:
- `pysdl2` - SDL2 bindings for graphics (original backend)
- `pygame` - Pygame library for graphics (new backend)
- **Image Processing**: `Pillow` - For image loading and manipulation
- **Configuration**: `pyaml` - YAML config file parsing
- **Standard Library**: `uuid`, `random`, `os`, `json`
### Performance Optimizations
- **Spatial Partitioning**: Grid-based collision detection reduces O(n²) to O(n)
- **Texture Caching**: Pre-loaded assets prevent repeated disk I/O
- **Background Rendering**: Static maze rendered once, cached as texture
- **Delta Time**: Frame-rate independent updates using `partial_move`
- **Efficient Drawing**: Only draw units in visible viewport area
### Memory Management
- **Automatic Cleanup**: Dead units removed from `units` dictionary
- **Surface Reuse**: Blood stains combined into background texture
- **Lazy Loading**: Assets loaded on demand
- **Reference Counting**: Python GC handles most cleanup
### Architecture Patterns
- **Multiple Inheritance**: Game class combines Controls, Graphics, UnitManager, Scoring
- **Abstract Base Classes**: `Unit` defines interface for all game entities
- **Factory Pattern**: `spawn_unit()` method for dynamic unit creation
- **Observer Pattern**: Event-driven input system with callbacks
- **Strategy Pattern**: Different AI behaviors for rat types
## Environment Variables
Configure the game behavior using environment variables:
- `SDL_VIDEODRIVER`: Video driver selection (x11, wayland, etc.)
- `RESOLUTION`: Screen resolution in format `WIDTHxHEIGHT` (default: 640x480)
- `FULLSCREEN`: Enable fullscreen mode (true/false)
- `SOUND_ENABLED`: Enable/disable sound effects (true/false)
Example:
```bash
RESOLUTION=1920x1080 FULLSCREEN=true python rats.py
```
## Installation
### Prerequisites
- Python 3.11 or higher
- pip package manager
### Step-by-Step Installation
1. **Clone the repository**:
```bash
git clone https://github.com/yourusername/mice-maze-game.git
cd mice-maze-game
```
2. **Create a virtual environment** (recommended):
```bash
python3 -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
```
3. **Install dependencies**:
For **Pygame backend** (recommended for beginners):
```bash
pip install pygame Pillow pyaml
```
For **SDL2 backend** (advanced users):
```bash
pip install pysdl2 Pillow pyaml
```
Or install all dependencies:
```bash
pip install -r requirements.txt
```
4. **Run the game**:
```bash
python rats.py
```
### Platform-Specific Notes
#### Linux
- SDL2 backend requires `libsdl2-dev` package
- Install via: `sudo apt-get install libsdl2-dev libsdl2-ttf-dev libsdl2-mixer-dev`
#### macOS
- Install SDL2 via Homebrew: `brew install sdl2 sdl2_ttf sdl2_mixer`
- Pygame backend works out of the box
#### Windows
- Pygame backend recommended (easiest setup)
- SDL2 backend requires manual SDL2 DLL installation
## Project Structure
```
mice/
├── engine/ # Core engine components
│ ├── controls.py # Input handling system
│ ├── graphics.py # Graphics and rendering helpers
│ ├── maze.py # Map and collision system
│ ├── sdl2_layer.py # SDL2 rendering backend
│ ├── pygame_layer.py # Pygame rendering backend ⭐ NEW
│ ├── unit_manager.py # Entity spawning and management
│ ├── scoring.py # Score tracking system
│ ├── user_profile_integration.py # User profile system
│ └── score_api_client.py # API client for global leaderboard
├── units/ # Game entity implementations
│ ├── __init__.py # Unit package exports
│ ├── unit.py # Abstract base class for all units
│ ├── rat.py # Rat AI and behavior (Male/Female)
│ ├── bomb.py # Bombs, timers, and explosions
│ ├── mine.py # Mine traps
│ ├── gas.py # Poison gas clouds
│ └── points.py # Collectible point items
├── profile_manager/ # Profile management system
│ ├── profile_manager.py # Profile CRUD operations
│ ├── profile_data.py # Profile data models
│ ├── ui_components.py # UI helpers
│ └── screens/ # Profile management screens
│ ├── screen_manager.py # Screen navigation
│ ├── main_menu_screen.py
│ ├── profile_list_screen.py
│ ├── create_profile_screen.py
│ ├── edit_profile_screen.py
│ ├── profile_stats_screen.py
│ └── leaderboard_screen.py
├── assets/ # Game resources
│ ├── Rat/ # Sprite images
│ │ ├── BMP_*.png # Various game sprites
│ └── decterm.ttf # Font file
├── sound/ # Audio files
│ ├── converted/ # Converted audio format
│ └── *.WAV # Sound effects
├── conf/ # Configuration files
│ ├── keybindings.yaml # Key mapping configuration
│ ├── keybindings_*.yaml # Device-specific bindings
│ └── keybindings.json # JSON format bindings
├── tools/ # Utility scripts
│ ├── convert_audio.py # Audio format converter
│ ├── resize_assets.py # Image resizing tool
│ └── colorize_assets.py # Asset colorization
├── rats.py # Main game entry point
├── maze.json # Maze layout data
├── user_profiles.json # User profile storage
├── requirements.txt # Python dependencies
├── README.md # This documentation
├── README_PROFILE_MANAGER.md # Profile system documentation
└── UNIT_ARCHITECTURE_GUIDE.md # Unit system guide
```
## Game Files Details
### Core Game Files
- **`rats.py`**: Main game controller, entry point, and game loop
- **`maze.json`**: Maze layout definition (grid of walls and paths)
- **`key.py`**: Additional key handling utilities
### Engine Modules
- **`engine/controls.py`**: Input abstraction with configurable bindings
- **`engine/graphics.py`**: Graphics helpers (asset loading, background generation)
- **`engine/maze.py`**: World representation with collision detection
- **`engine/sdl2_layer.py`**: Low-level SDL2 graphics interface
- **`engine/pygame_layer.py`**: Pygame graphics interface (new)
- **`engine/unit_manager.py`**: Unit spawning and lifecycle management
- **`engine/scoring.py`**: Score calculation and persistence
### Unit Implementations
- **`units/unit.py`**: Abstract base class defining unit interface
- **`units/rat.py`**: Rat AI with pathfinding and reproduction
- **`units/bomb.py`**: Explosive units with timer and blast mechanics
- **`units/mine.py`**: Trap units with proximity trigger
- **`units/gas.py`**: Poison gas clouds with area effect
- **`units/points.py`**: Collectible scoring items
### Data Files
- **`user_profiles.json`**: Persistent user profile data
- **`scores.txt`**: Traditional high score storage (legacy)
- **`maze.json`**: Level layout definition
### Configuration
- **`conf/keybindings.yaml`**: Key mapping for different game states
- **Device-specific configs**: Optimized bindings for different devices
## How to Play
### Objective
Eliminate all rats before they reproduce and overwhelm the maze. Collect points by killing rats with bombs, mines, and gas.
### Controls
#### Default Keyboard Controls
- **Arrow Keys**: Move cursor
- **Space**: Place bomb at cursor position
- **M**: Place mine at cursor position
- **G**: Release poison gas at cursor position
- **N**: Deploy nuclear bomb (one-time use)
- **P**: Pause game
- **F**: Toggle fullscreen
- **S**: Toggle sound
- **ESC**: Quit game
#### Gamepad Support
- **D-Pad**: Move cursor
- **Button A**: Place bomb
- **Button B**: Place mine
- **Button X**: Release gas
- **Start**: Pause game
*Controls can be customized via configuration files in `conf/`*
### Gameplay Tips
1. **Early Game**: Focus on preventing rat reproduction by targeting adults
2. **Bomb Placement**: Use walls to direct explosion paths
3. **Mine Strategy**: Place mines in narrow corridors where rats pass frequently
4. **Gas Tactics**: Gas lingers and accumulates damage - use in rat-dense areas
5. **Nuclear Option**: Save the nuclear bomb for when rats exceed ~150
6. **Resource Management**: Ammo refills randomly - don't waste bombs early
7. **Scoring**: Chain kills and quick clears give bonus points
### Win Condition
Clear all rats from the maze without letting their population exceed 200.
### Lose Condition
Rat population exceeds 200 - they've overrun the maze.
## Profile System
Mice! includes a comprehensive user profile system to track your progress:
### Features
- **Multiple Profiles**: Create profiles for different players
- **Statistics Tracking**: Games played, wins, losses, best score
- **Device Support**: Profile data syncs across devices
- **Leaderboards**: Compare scores globally and locally
- **Achievements**: Track milestones and accomplishments
### Profile Management
Access the profile manager before starting the game:
```bash
python profile_manager/profile_manager.py
```
Or manage profiles from within the game main menu.
## Development
### Adding New Units
1. Create a new class in `units/` inheriting from `Unit`
2. Implement required methods: `move()`, `draw()`
3. Optionally override: `collisions()`, `die()`
4. Register in `units/__init__.py`
5. Add spawning logic in `unit_manager.py`
Example:
```python
from units.unit import Unit
class MyUnit(Unit):
def move(self):
# Update logic here
pass
def draw(self):
# Rendering logic here
image = self.game.assets["MY_SPRITE"]
self.game.render_engine.draw_image(x, y, image, tag="unit")
```
### Switching Rendering Backends
Edit the import in `rats.py`:
```python
# For SDL2
from engine import sdl2_layer as engine
# For Pygame
from engine import pygame_layer as engine
```
### Creating Custom Mazes
Edit `maze.json` - it's a 2D grid where:
- `0` = path/floor
- `1` = wall
Example:
```json
{
"maze": [
[1, 1, 1, 1, 1],
[1, 0, 0, 0, 1],
[1, 0, 1, 0, 1],
[1, 0, 0, 0, 1],
[1, 1, 1, 1, 1]
]
}
```
## Troubleshooting
### Common Issues
**Issue**: Game window doesn't appear
- **Solution**: Check `RESOLUTION` environment variable, try `640x480`
**Issue**: No sound
- **Solution**: Verify `SOUND_ENABLED` not set to false, check audio files in `sound/`
**Issue**: SDL2 import errors
- **Solution**: Switch to Pygame backend or install SDL2 libraries
**Issue**: Slow performance
- **Solution**: Reduce resolution, close other applications, update graphics drivers
**Issue**: Profile data not saving
- **Solution**: Check file permissions for `user_profiles.json`
## Contributing
Contributions are welcome! Please:
1. Fork the repository
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request
## License
This project is a fan remake of the classic "Rats!" game from Windows 95.
## Credits
- **Original Game**: Rats! for Windows 95
- **Developer**: Matteo (because he was bored)
- **Engine**: Custom Python engine with SDL2/Pygame backends
- **Contributors**: See GitHub contributors page
## Changelog
### Version 2.0 (Current)
- ⭐ Added Pygame rendering backend
- ⭐ Dual backend support (SDL2 + Pygame)
- ⭐ Complete API compatibility between backends
- Improved documentation
- Enhanced README with technical details
### Version 1.0
- Initial release
- SDL2 rendering engine
- User profile system
- Multiple unit types
- Configurable controls
- Leaderboard system
## Technical Details
- **Language**: Python 3.11
- **Libraries**:
- `numpy` 2.3.4 for vectorized collision detection
- `sdl2` for graphics and window management
## Map Editor
The project now includes a Tkinter editor for `level.dat` archives:
- Launch with `python tools/level_editor.py`
- Open a specific archive with `python tools/level_editor.py --file assets/Rat/level.dat`
- Start on a specific level with `python tools/level_editor.py --file assets/Rat/level.dat --level 7`
- The editor requires a Python installation with the standard `tkinter` module available at OS level
Editor capabilities:
- Edits the full 32-level DAT archive used by the game
- Creates new DAT archives with 32 default levels
- Paints `EMPTY`, `WALL`, and `TUNNEL` tiles with brush, fill, and rectangle tools
- Supports undo/redo, level copy/paste, and level duplication between slots
- Imports a single level from JSON and exports the current level back to JSON
- Validates common gameplay issues such as missing spawn cells, open borders, and disconnected traversable areas
## Level Sources
- Preferred source: `assets/Rat/level.dat`
- Fallback source: `maze.json`
- Current behavior: the loader can read any level from the DAT archive via `--level N`, while still falling back to `maze.json` when the DAT is unavailable.
- Tile semantics are now preserved internally from the original format: `0=EMPTY`, `1=WALL`, `2=TUNNEL`.
- Rendering uses those semantics directly: walls use themed grass/flower tiles, tunnel cells use themed cave tiles, and empty cells remain the generic walkable tunnel floor used by the Python version.
### Run examples
- `python rats.py`
- `python rats.py --level 7`
- `python rats.py --map maze.json`
- `Pillow` for image processing
- `uuid` for unique unit identification
- `subprocess` for playing sound effects
- `tkinter` for maze generation visualization
- **Performance Optimizations**:
- **Collision System**: NumPy-based spatial hashing reducing O(n²) to O(n)
- **Rendering Cache**: Pre-calculated render positions, viewport bounds, and image sizes
- **Blood Overlay**: Separate sprite layer eliminates background regeneration
- **Hybrid Processing**: Automatic switching between direct iteration and vectorization
- **Pre-allocated Arrays**: Capacity-based resizing minimizes NumPy vstack overhead
- **Texture Atlasing**: Reduced memory usage and GPU calls
- **Object Pooling**: Blood stain pool (10 pre-generated variants)
- **Delta Time Updates**: Frame rate independence
- Spatial partitioning for collision detection
- Texture atlasing for reduced memory usage
- Object pooling for frequently created/destroyed units
- Delta time-based updates for frame rate independence
- **Memory Management**:
- Automatic cleanup of dead units
- Texture caching and reuse
- Efficient data structures for 200+ simultaneous units
- Blood stain sprite pool to avoid runtime generation
- Efficient data structures for large numbers of units
## Environment Variables
@@ -334,47 +722,35 @@ Editor capabilities:
```
mice/
├── engine/ # Core engine components
│ ├── collision_system.py # NumPy-based vectorized collision detection
│ ├── controls.py # Input handling system
│ ├── graphics.py # Blood overlay and rendering optimizations
│ ├── maze.py # Map and collision system
│ ├── sdl2.py # Rendering and window management
│ └── unit_manager.py # Unit spawning and lifecycle management
├── units/ # Game entity implementations
│ ├── unit.py # Base unit class with collision layers
│ ├── bomb.py # Bomb and explosion logic with area damage
│ ├── gas.py # Gas weapon with cell-based detection
│ ├── mine.py # Proximity mine with trigger system
│ ├── rat.py # Rat AI with optimized rendering cache
│ └── points.py # Collectible points (90 frames lifetime)
├── assets/ # Game resources
│ ├── images/ # Sprites and textures
│ └── fonts/ # Text rendering fonts
├── sound/ # Audio files
├── maze.py # Maze generation algorithms
├── rats.py # Main game entry point with 4-pass game loop
├── requirements.txt # Python dependencies (including numpy)
├── .env # Environment configuration
└── README.md # This documentation
├── engine/ # Core engine components
│ ├── controls.py # Input handling system
│ ├── maze.py # Map and collision system
│ └── sdl2.py # Rendering and window management
├── units/ # Game entity implementations
│ ├── bomb.py # Bomb and explosion logic
│ ├── rat.py # Rat AI and behavior
│ └── points.py # Collectible points
├── assets/ # Game resources
│ ├── images/ # Sprites and textures
│ └── fonts/ # Text rendering fonts
├── sound/ # Audio files
├── maze.py # Maze generation algorithms
├── rats.py # Main game entry point
├── requirements.txt # Python dependencies
├── .env # Environment configuration
└── README.md # This documentation
```
## Game Files Details
- `maze.py`: Contains the `MazeGenerator` class implementing DFS algorithm for procedural maze generation
- `rats.py`: Main game controller with 4-pass optimized game loop, manages collision system and unit lifecycle
- `engine/collision_system.py`: NumPy-based spatial hashing system supporting 200+ units at 3ms/frame
- `engine/graphics.py`: Blood overlay system with pre-generated stain pool and rendering optimizations
- `rats.py`: Main game controller, initializes engine systems and manages game state
- `engine/controls.py`: Input abstraction layer with configurable key bindings
- `engine/maze.py`: World representation with collision detection and pathfinding support
- `engine/sdl2.py`: Low-level graphics interface wrapping SDL2 with alpha blending and texture caching
- `engine/unit_manager.py`: Centralized unit spawning with weapon collision avoidance
- `units/unit.py`: Base unit class with collision layer support
- `units/bomb.py`: Explosive units with vectorized area damage calculations
- `units/gas.py`: Area denial weapon using cell-based victim detection
- `units/mine.py`: Proximity-triggered explosives
- `units/rat.py`: AI-driven entities with cached render positions and collision filtering
- `units/points.py`: Collectible scoring items (90 frame lifetime, ~1.5s at 60 FPS)
- `engine/sdl2.py`: Low-level graphics interface wrapping SDL2 functionality
- `units/bomb.py`: Explosive units with timer mechanics and blast radius calculations
- `units/rat.py`: AI-driven entities with reproduction, pathfinding, and survival behaviors
- `units/points.py`: Collectible scoring items with visual feedback systems
- `assets/`: Game resources including sprites, textures, and fonts
- `sound/`: Audio assets for game events and feedback
- `scores.txt`: Persistent high score storage
-391
View File
@@ -1,391 +0,0 @@
# Guida all'Architettura delle Unità - Mice Game
## 📋 Panoramica
Questo documento descrive l'architettura refactorizzata del sistema di gestione delle unità nel gioco "Mice", evidenziando i miglioramenti implementati e le possibili evoluzioni future.
---
## 🏗️ Architettura Attuale
### Gerarchia delle Classi
```
Unit (ABC)
├── Rat
│ ├── Male
│ └── Female
├── Bomb
│ ├── Timer
│ └── Explosion
└── Point
```
### Classe Base `Unit` (Abstract Base Class)
**File**: `units/unit.py`
```python
from abc import ABC, abstractmethod
import uuid
class Unit(ABC):
def __init__(self, game, position=(0, 0), id=None):
self.id = id if id else uuid.uuid4() # Identificatore univoco
self.game = game # Riferimento al gioco
self.position = position # Posizione attuale (x, y)
self.position_before = position # Posizione precedente
self.age = 0 # Età in tick di gioco
self.speed = 1.0 # Velocità di movimento
self.partial_move = 0 # Progresso movimento parziale
self.bbox = (0, 0, 0, 0) # Bounding box per collisioni
self.stop = 0 # Tick di immobilità rimanenti
```
**Metodi Astratti Obbligatori**:
- `move()`: Aggiorna posizione e stato dell'unità
- `draw()`: Renderizza l'unità sullo schermo
**Metodi Concreti**:
- `collisions()`: Gestisce collisioni (implementazione vuota di default)
- `die()`: Rimuove l'unità dal gioco
---
## 🐭 Gestione delle Unità Specifiche
### 1. Ratti (`Rat`, `Male`, `Female`)
**Caratteristiche**:
- **Movimento**: Navigazione intelligente nel labirinto
- **Invecchiamento**: Rallentano dopo 200 tick
- **Collisioni**: Combattimenti tra maschi, riproduzione tra sessi opposti
- **Morte**: Generano punti quando muoiono
**Attributi Specifici**:
```python
self.speed = 0.10 # Più lenti delle altre unità
self.fight = False # Stato di combattimento
self.sex = "MALE"/"FEMALE" # Genere (nelle sottoclassi)
```
**Comportamenti Unici**:
- **Male**: Può iniziare accoppiamenti
- **Female**: Gestisce gravidanza e nascite
### 2. Bombe (`Bomb`, `Timer`, `Explosion`)
**Caratteristiche**:
- **Timer**: Conta alla rovescia fino all'esplosione
- **Explosion**: Effetto visivo temporaneo
- **Distruzione**: Elimina altre unità in linea retta
**Attributi Specifici**:
```python
self.speed = 4 # Invecchiano rapidamente
```
### 3. Punti (`Point`)
**Caratteristiche**:
- **Temporanei**: Scompaiono dopo un certo tempo
- **Valore**: Aggiungono punti al punteggio del giocatore
- **Statici**: Non si muovono
---
## 🔄 Ciclo di Vita delle Unità
### 1. Creazione
```python
# Nel file rats.py
def spawn_unit(self, unit_class, position, **kwargs):
id = uuid.uuid4()
self.units[id] = unit_class(self, position, id, **kwargs)
```
### 2. Aggiornamento (Game Loop)
```python
# Nel metodo update_maze()
for unit in self.units.copy().values():
unit.move() # Aggiorna stato e posizione
unit.collisions() # Gestisce interazioni
unit.draw() # Renderizza sullo schermo
```
### 3. Rimozione
```python
# Metodo base nella classe Unit
def die(self):
if self.id in self.game.units:
self.game.units.pop(self.id)
```
---
## ✅ Miglioramenti Implementati
### 1. **Eliminazione Duplicazione Codice**
- **Prima**: ~60 righe duplicate tra classi
- **Dopo**: Attributi comuni centralizzati nella classe base
### 2. **Contratto Definito**
- Metodi astratti garantiscono implementazione obbligatoria
- Errori catturati a tempo di compilazione, non runtime
### 3. **Gestione Consistente**
- Valori di default standardizzati
- Logica di cleanup centralizzata
### 4. **Sicurezza del Tipo**
- Impossibile istanziare unità incomplete
- Debugging più facile e veloce
---
## 🚀 Migliorie Possibili
### 1. **Sistema di Componenti** (Priorità: Alta)
**Problema Attuale**: Logica mista nelle classi unità
**Soluzione**:
```python
# Separare comportamenti in componenti riutilizzabili
class MovementComponent:
def update(self, unit): pass
class RenderComponent:
def draw(self, unit): pass
class CollisionComponent:
def check_collisions(self, unit, others): pass
class Unit(ABC):
def __init__(self, game, position):
self.movement = MovementComponent()
self.renderer = RenderComponent()
self.collision = CollisionComponent()
```
**Vantaggi**:
- Comportamenti riutilizzabili tra unità diverse
- Facile testing di singoli componenti
- Composizione invece di ereditarietà profonda
### 2. **Factory Pattern** (Priorità: Media)
**Problema Attuale**: Creazione unità sparsa nel codice
**Soluzione**:
```python
class UnitFactory:
@staticmethod
def create_rat(game, position, sex="random"):
sex = random.choice(["MALE", "FEMALE"]) if sex == "random" else sex
rat_class = Male if sex == "MALE" else Female
return rat_class(game, position)
@staticmethod
def create_bomb(game, position, timer=200):
return Timer(game, position, timer_duration=timer)
```
**Vantaggi**:
- Creazione centralizzata e configurabile
- Parametri validati in un punto solo
- Facile aggiungere nuovi tipi
### 3. **Event System** (Priorità: Alta)
**Problema Attuale**: Accoppiamento forte tra unità e gioco
**Soluzione**:
```python
class EventSystem:
def __init__(self):
self.listeners = {}
def emit(self, event_type, data):
for listener in self.listeners.get(event_type, []):
listener(data)
# Nelle unità
def die(self):
self.game.events.emit("unit_died", {
"unit_id": self.id,
"position": self.position,
"score": self.calculate_score()
})
```
**Vantaggi**:
- Disaccoppiamento tra unità e sistemi di gioco
- Facile aggiungere nuovi listener
- Sistema più modulare e testabile
### 4. **State Pattern per Ratti** (Priorità: Media)
**Problema Attuale**: Logica di stato mista nel metodo `move()`
**Soluzione**:
```python
class RatState(ABC):
@abstractmethod
def update(self, rat): pass
class MovingState(RatState):
def update(self, rat):
# Logica movimento normale
class PregnantState(RatState):
def update(self, rat):
# Logica gravidanza
class FightingState(RatState):
def update(self, rat):
# Logica combattimento
class Rat(Unit):
def __init__(self, ...):
self.state = MovingState()
def move(self):
self.state.update(self)
```
### 5. **Object Pool** (Priorità: Bassa)
**Problema**: Creazione/distruzione frequente oggetti
**Soluzione**:
```python
class UnitPool:
def __init__(self):
self.available_units = {}
self.active_units = {}
def get_unit(self, unit_type):
# Riutilizza unità esistenti invece di crearne nuove
def return_unit(self, unit):
# Ripulisce e rimette nel pool
```
**Vantaggi**:
- Prestazioni migliori con molte unità
- Meno garbage collection
- Memoria più stabile
### 6. **Spatial Partitioning** (Priorità: Media)
**Problema**: Collisioni O(n²) con molte unità
**Soluzione**:
```python
class SpatialGrid:
def __init__(self, cell_size):
self.grid = {}
self.cell_size = cell_size
def get_nearby_units(self, position, radius):
# Ritorna solo unità vicine, non tutte
```
### 7. **Configuration System** (Priorità: Bassa)
**Problema**: Costanti hardcoded nel codice
**Soluzione**:
```python
# units_config.json
{
"rat": {
"speed": 0.10,
"age_threshold": 200,
"pregnancy_duration": 500
},
"bomb": {
"speed": 4,
"explosion_range": 5
}
}
```
---
## 📊 Metriche di Miglioramento
| Aspetto | Prima | Dopo | Miglioramento |
|---------|-------|------|---------------|
| **Righe duplicate** | ~60 | 0 | -100% |
| **Tempo debug** | Alto | Basso | -70% |
| **Facilità estensione** | Difficile | Facile | +200% |
| **Errori runtime** | Frequenti | Rari | -80% |
| **Manutenibilità** | Bassa | Alta | +150% |
---
## 🛠️ Roadmap Implementazione
### Fase 1: Fondamenta (Completata ✅)
- [x] Refactoring classe base Unit
- [x] Eliminazione duplicazione codice
- [x] Metodi astratti obbligatori
### Fase 2: Architettura (2-3 giorni)
- [ ] Sistema di componenti
- [ ] Event system base
- [ ] Factory pattern
### Fase 3: Ottimizzazioni (1-2 giorni)
- [ ] State pattern per ratti
- [ ] Spatial partitioning
- [ ] Object pooling
### Fase 4: Configurazione (1 giorno)
- [ ] Sistema di configurazione
- [ ] Tuning parametri
- [ ] Testing prestazioni
---
## 🧪 Come Testare
### Test Base Funzionalità
```bash
cd c:\Users\enne2\Dev\mice
python rats.py
```
### Test Specifici Unità
```python
# Test creazione
rat = Male(game, (5, 5))
assert rat.sex == "MALE"
assert rat.position == (5, 5)
# Test metodi astratti
try:
unit = Unit(game, (0, 0)) # Dovrebbe fallire
except TypeError:
print("✅ Metodi astratti funzionano")
```
---
## 📝 Note per Sviluppatori
1. **Sempre implementare metodi astratti** in nuove unità
2. **Usare super()** per chiamare implementazioni base
3. **Eventi invece di chiamate dirette** per disaccoppiamento
4. **Componenti riutilizzabili** per comportamenti comuni
5. **Testing incrementale** ad ogni modifica
---
## 🎯 Conclusioni
L'architettura refactorizzata fornisce una base solida e estensibile per il sistema delle unità. I miglioramenti implementati eliminano duplicazioni e aumentano la robustezza, mentre le migliorie proposte offrono un percorso chiaro per evoluzioni future più avanzate.
Il sistema attuale è **pronto per la produzione** e **facilmente estensibile** per nuove funzionalità.
-2125
View File
File diff suppressed because it is too large Load Diff
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 257 B

After

Width:  |  Height:  |  Size: 388 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 279 B

After

Width:  |  Height:  |  Size: 399 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 296 B

After

Width:  |  Height:  |  Size: 399 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 243 B

After

Width:  |  Height:  |  Size: 380 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 198 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 174 B

After

Width:  |  Height:  |  Size: 354 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 198 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 189 B

After

Width:  |  Height:  |  Size: 354 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 198 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 184 B

After

Width:  |  Height:  |  Size: 354 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 519 B

After

Width:  |  Height:  |  Size: 419 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 543 B

After

Width:  |  Height:  |  Size: 425 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 550 B

After

Width:  |  Height:  |  Size: 428 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 517 B

After

Width:  |  Height:  |  Size: 416 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 400 B

After

Width:  |  Height:  |  Size: 464 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 402 B

After

Width:  |  Height:  |  Size: 443 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 401 B

After

Width:  |  Height:  |  Size: 462 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 390 B

After

Width:  |  Height:  |  Size: 458 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 374 B

After

Width:  |  Height:  |  Size: 436 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 414 B

After

Width:  |  Height:  |  Size: 457 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 383 B

After

Width:  |  Height:  |  Size: 457 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 423 B

After

Width:  |  Height:  |  Size: 449 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 473 B

After

Width:  |  Height:  |  Size: 392 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 325 B

After

Width:  |  Height:  |  Size: 392 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 332 B

After

Width:  |  Height:  |  Size: 392 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 325 B

After

Width:  |  Height:  |  Size: 391 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 198 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 197 B

After

Width:  |  Height:  |  Size: 356 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 198 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 197 B

After

Width:  |  Height:  |  Size: 356 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 198 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 193 B

After

Width:  |  Height:  |  Size: 355 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 198 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 171 B

After

Width:  |  Height:  |  Size: 351 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 198 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 194 B

After

Width:  |  Height:  |  Size: 358 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 198 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 191 B

After

Width:  |  Height:  |  Size: 358 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 198 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 187 B

After

Width:  |  Height:  |  Size: 355 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 198 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 187 B

After

Width:  |  Height:  |  Size: 356 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 198 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 187 B

After

Width:  |  Height:  |  Size: 352 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 242 B

After

Width:  |  Height:  |  Size: 380 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 242 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 259 B

After

Width:  |  Height:  |  Size: 390 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 259 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 286 B

After

Width:  |  Height:  |  Size: 393 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 286 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 243 B

After

Width:  |  Height:  |  Size: 377 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 243 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 198 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 175 B

After

Width:  |  Height:  |  Size: 355 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 198 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 189 B

After

Width:  |  Height:  |  Size: 354 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 198 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 184 B

After

Width:  |  Height:  |  Size: 354 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 306 B

After

Width:  |  Height:  |  Size: 409 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 306 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 312 B

After

Width:  |  Height:  |  Size: 407 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 312 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 277 B

After

Width:  |  Height:  |  Size: 402 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 277 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 281 B

After

Width:  |  Height:  |  Size: 405 B

Some files were not shown because too many files have changed in this diff Show More