use crate::{
engine::{Engine, Game, run_game},
window::WindowConfig,
entity::{EntityManager, Transform, Sprite, Velocity},
math::{Position, Size, Color},
resources::Resources,
systems::{System, SystemSet},
EngineResult,
};
use std::any::Any;
use winit::event::WindowEvent;
pub struct App {
resources: Resources,
startup_systems: Vec<Box<dyn System>>,
update_systems: Vec<Box<dyn System>>,
render_systems: Vec<Box<dyn System>>,
window_config: WindowConfig,
}
impl App {
pub fn new() -> AppBuilder {
AppBuilder::new()
}
pub fn run(self) -> EngineResult<()> {
let game = ShadowGame {
app: self,
initialized: false,
};
run_game(game.app.window_config.clone(), Box::new(game))
}
}
pub struct AppBuilder {
resources: Resources,
startup_systems: Vec<Box<dyn System>>,
update_systems: Vec<Box<dyn System>>,
render_systems: Vec<Box<dyn System>>,
window_config: WindowConfig,
}
impl AppBuilder {
pub fn new() -> Self {
Self {
resources: Resources::new(),
startup_systems: Vec::new(),
update_systems: Vec::new(),
render_systems: Vec::new(),
window_config: WindowConfig::default(),
}
}
pub fn set_window(mut self, config: WindowConfig) -> Self {
self.window_config = config;
self
}
pub fn insert_resource<T: 'static>(mut self, resource: T) -> Self {
self.resources.insert(resource);
self
}
pub fn add_startup_system<T: System + 'static>(mut self, system: T) -> Self {
self.startup_systems.push(Box::new(system));
self
}
pub fn add_system<T: System + 'static>(mut self, system: T) -> Self {
self.update_systems.push(Box::new(system));
self
}
pub fn add_system_set(mut self, system_set: SystemSet) -> Self {
match system_set {
SystemSet::Startup(systems) => {
self.startup_systems.extend(systems);
}
SystemSet::Update(systems) => {
self.update_systems.extend(systems);
}
SystemSet::Render(systems) => {
self.render_systems.extend(systems);
}
}
self
}
pub fn build(self) -> App {
App {
resources: self.resources,
startup_systems: self.startup_systems,
update_systems: self.update_systems,
render_systems: self.render_systems,
window_config: self.window_config,
}
}
}
struct ShadowGame {
app: App,
initialized: bool,
}
impl Game for ShadowGame {
fn init(&mut self, engine: &mut Engine) -> EngineResult<()> {
for system in &mut self.app.startup_systems {
system.run(engine, &mut self.app.resources)?;
}
self.initialized = true;
Ok(())
}
fn update(&mut self, engine: &mut Engine, delta_time: f32) -> EngineResult<()> {
if !self.initialized {
return Ok(());
}
if let Some(time) = self.app.resources.get_mut::<TimeResource>() {
time.update(delta_time);
}
for system in &mut self.app.update_systems {
system.run(engine, &mut self.app.resources)?;
}
Ok(())
}
fn render(&mut self, engine: &mut Engine) -> EngineResult<()> {
if !self.initialized {
return Ok(());
}
for system in &mut self.app.render_systems {
system.run(engine, &mut self.app.resources)?;
}
engine.render()?;
Ok(())
}
fn on_event(&mut self, engine: &mut Engine, event: &WindowEvent) -> EngineResult<()> {
if let Some(input) = self.app.resources.get_mut::<InputResource>() {
input.handle_event(event);
}
Ok(())
}
}
#[derive(Debug)]
pub struct TimeResource {
pub delta_time: f32,
pub total_time: f32,
}
impl TimeResource {
pub fn new() -> Self {
Self {
delta_time: 0.0,
total_time: 0.0,
}
}
pub fn update(&mut self, delta_time: f32) {
self.delta_time = delta_time;
self.total_time += delta_time;
}
}
#[derive(Debug)]
pub struct InputResource {
}
impl InputResource {
pub fn new() -> Self {
Self {}
}
pub fn handle_event(&mut self, _event: &WindowEvent) {
}
}
impl Default for AppBuilder {
fn default() -> Self {
Self::new()
}
}