| Crates.io | shadowengine2d |
| lib.rs | shadowengine2d |
| version | 2.0.0 |
| created_at | 2025-08-10 04:13:39.555933+00 |
| updated_at | 2025-09-07 01:15:52.743041+00 |
| description | A comprehensive 2D game engine built in Rust with ECS, rendering, audio, assets, animations, and scene management |
| homepage | https://github.com/JackOwnerOfwhisper/shadowengine2d |
| repository | https://github.com/JackOwnerOfwhisper/shadowengine2d |
| max_upload_size | |
| id | 1788488 |
| size | 370,187 |
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.
ShadowEngine2D includes an advanced 2D particle system for effects like explosions, fire, smoke, and more. Features include:
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);
}));
Add this to your Cargo.toml:
[dependencies]
shadowengine2d = "1.1.0"
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(())
}
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();
#[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(())
}
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(())
}
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);
cargo run --example bouncing_ball
cargo run --example modern_game
cargo run --example output_demo