use crate::{
window::{Window, WindowConfig, AppHandler, run_window},
renderer::Renderer,
entity::EntityManager,
input::Input,
time::Time,
EngineResult
};
use winit::event::WindowEvent;
pub struct Engine {
pub entities: EntityManager,
pub input: Input,
pub time: Time,
pub renderer: Option<Renderer>,
}
impl Engine {
pub fn new() -> Self {
Self {
entities: EntityManager::new(),
input: Input::new(),
time: Time::new(),
renderer: None,
}
}
pub async fn init_renderer(&mut self, window: &Window) -> EngineResult<()> {
self.renderer = Some(Renderer::new(window).await?);
Ok(())
}
pub fn update(&mut self, delta_time: f32) {
self.time.tick();
self.input.new_frame();
self.entities.update_physics(delta_time);
}
pub fn handle_event(&mut self, event: &WindowEvent) {
self.input.handle_event(event);
}
pub fn render(&mut self) -> EngineResult<()> {
if let Some(renderer) = &mut self.renderer {
renderer.begin_frame();
let renderable = self.entities.get_renderable_entities();
renderer.draw_entities(renderable);
renderer.end_frame()?;
}
Ok(())
}
pub fn renderer(&self) -> Option<&Renderer> {
self.renderer.as_ref()
}
pub fn renderer_mut(&mut self) -> Option<&mut Renderer> {
self.renderer.as_mut()
}
}
pub trait Game {
fn init(&mut self, engine: &mut Engine) -> EngineResult<()> {
Ok(())
}
fn update(&mut self, engine: &mut Engine, delta_time: f32) -> EngineResult<()>;
fn render(&mut self, engine: &mut Engine) -> EngineResult<()> {
engine.render()
}
fn on_event(&mut self, engine: &mut Engine, event: &WindowEvent) -> EngineResult<()> {
Ok(())
}
fn cleanup(&mut self, engine: &mut Engine) {}
}
struct GameAppHandler {
engine: Engine,
game: Box<dyn Game>,
initialized: bool,
}
impl GameAppHandler {
fn new(game: Box<dyn Game>) -> Self {
Self {
engine: Engine::new(),
game,
initialized: false,
}
}
}
impl AppHandler for GameAppHandler {
fn on_init(&mut self, window: &Window) -> EngineResult<()> {
pollster::block_on(self.engine.init_renderer(window))?;
self.game.init(&mut self.engine)?;
self.initialized = true;
Ok(())
}
fn on_update(&mut self, _window: &Window, delta_time: f32) -> EngineResult<()> {
if self.initialized {
self.engine.update(delta_time);
self.game.update(&mut self.engine, delta_time)?;
}
Ok(())
}
fn on_render(&mut self, _window: &Window) -> EngineResult<()> {
if self.initialized {
self.game.render(&mut self.engine)?;
}
Ok(())
}
fn on_window_event(&mut self, _window: &Window, event: &WindowEvent) -> EngineResult<()> {
if self.initialized {
self.engine.handle_event(event);
self.game.on_event(&mut self.engine, event)?;
}
Ok(())
}
fn on_exit(&mut self) {
if self.initialized {
self.game.cleanup(&mut self.engine);
}
}
}
pub fn run_game(config: WindowConfig, game: Box<dyn Game>) -> EngineResult<()> {
let handler = GameAppHandler::new(game);
run_window(config, Box::new(handler))
}
impl Default for Engine {
fn default() -> Self {
Self::new()
}
}