# ShadowEngine2D
A comprehensive 2D game engine built in Rust, featuring Entity-Component-System (ECS) architecture, modern graphics rendering, audio systems, asset management, animations, and scene management.
## Features
- 🎮 **Entity-Component-System (ECS)** - Flexible and performant game object management
- 🎨 **Modern Graphics** - GPU-accelerated rendering with WGPU
- 🔊 **Audio System** - 3D positional audio, effects, and music playback
- 📦 **Asset Management** - Hot-reloadable assets with multiple format support
- 🎬 **Animation System** - Sprite animations and tweening with easing functions
- 🎭 **Scene Management** - Hierarchical scenes with transitions and lifecycle management
- ⌨️ **Input Handling** - Keyboard, mouse, and gamepad support
- 🖼️ **UI System** - Immediate-mode GUI with flexible layouts
- ⏱️ **Time Management** - Delta time, time scaling, and frame-rate independent logic
- ✨ **Particle System** - Advanced 2D particles with randomization, gravity, burst emission, and custom behaviors
## Particle System
ShadowEngine2D includes an advanced 2D particle system for effects like explosions, fire, smoke, and more. Features include:
- Randomized velocity, color, and size
- Gravity and acceleration
- Burst emission and emission shapes (point, circle)
- Custom update callbacks for unique behaviors
### Basic Usage
```rust
use shadowengine2d::prelude::*;
let mut emitter = ParticleEmitter::new(Position::new(400.0, 300.0));
emitter.emission_rate = 100.0;
emitter.particle_lifetime = 2.0;
emitter.particle_size = 10.0;
emitter.color = [1.0, 0.5, 0.2, 1.0];
emitter.velocity = Position::new(0.0, -150.0);
emitter.gravity = Position::new(0.0, 300.0);
emitter.velocity_randomness = Position::new(50.0, 50.0);
emitter.size_randomness = 5.0;
emitter.emission_shape = EmissionShape::Circle { radius: 20.0 };
emitter.burst = Some(50); // Optional: burst emission
// In your update loop:
emitter.update(delta_time);
// In your render loop:
emitter.render(&mut renderer);
// Optional: custom update callback for advanced effects
emitter.custom_update = Some(Box::new(|particle, dt| {
// Example: fade out alpha
particle.color[3] = 1.0 - (particle.age / particle.lifetime);
}));
```
## Quick Start
Add this to your `Cargo.toml`:
```toml
[dependencies]
shadowengine2d = "1.1.0"
```
## Basic Usage
```rust
use shadowengine2d::prelude::*;
fn main() -> EngineResult<()> {
App::new()
.set_window(WindowConfig {
title: "My Game".to_string(),
width: 800,
height: 600,
resizable: true,
})
.add_startup_system(setup)
.add_system(update)
.build()
.run()
}
fn setup(engine: &mut Engine, resources: &mut Resources) -> EngineResult<()> {
engine.entities.spawn()
.ball(400.0, 300.0, 100.0, -150.0, Color::RED, 50.0)
.build();
Ok(())
}
fn update(engine: &mut Engine, resources: &mut Resources) -> EngineResult<()> {
if engine.input.is_key_pressed(KeyCode::Space) {
engine.entities.spawn()
.at_position(400.0, 100.0)
.with_colored_square(Color::BLUE, 32.0)
.with_movement(0.0, -200.0)
.build();
}
Ok(())
}
```
## Entity Creation
```rust
let entity = engine.entities.spawn()
.at_position(100.0, 200.0)
.with_colored_square(Color::GREEN, 64.0)
.build();
let player = engine.entities.spawn()
.game_object(
Position::new(400.0, 300.0),
Sprite::new(Color::WHITE, Size::new(32.0, 48.0))
)
.with_velocity(Velocity::zero())
.build();
let ball = engine.entities.spawn()
.ball(x, y, vel_x, vel_y, color, size)
.build();
```
## Resources
```rust
#[derive(Debug)]
struct GameState {
score: u32,
lives: u32,
}
app.insert_resource(GameState { score: 0, lives: 3 });
fn game_logic(engine: &mut Engine, resources: &mut Resources) -> EngineResult<()> {
let mut state = resources.get_mut::<GameState>().unwrap();
state.score += 10;
Ok(())
}
```
## UI
```rust
fn ui_system(engine: &mut Engine, resources: &mut Resources) -> EngineResult<()> {
let mut ui = resources.get_mut::<UiContext>().unwrap();
ui.panel(Rect::new(10.0, 10.0, 200.0, 100.0), Color::new(0.0, 0.0, 0.0, 0.7));
ui.button(Rect::new(20.0, 30.0, 100.0, 30.0), "Start", ButtonStyle::primary());
ui.render_to_entities(&mut engine.entities);
Ok(())
}
```
## Debug Output
```rust
use shadowengine2d::{Output, debug, info, warn, error};
// Enable/disable debug output
Output::set_enabled(true);
// Different log levels
Output::debug("Debug information");
Output::info("General information");
Output::warn("Warning message");
Output::error("Error message (always shown)");
// Or use convenient macros with formatting
debug!("Player at position ({}, {})", x, y);
info!("Score: {}, Lives: {}", score, lives);
warn!("Low health: {}%", health_percent);
error!("Failed to load asset: {}", filename);
```
## Examples
```bash
cargo run --example bouncing_ball
cargo run --example modern_game
cargo run --example output_demo
```