use lyra_engine::{math::{self, Vec3}, ecs::{World, components::{transform::TransformComponent, camera::CameraComponent, model::ModelComponent, DeltaTime}, EventQueue, SimpleSystem, Component, Criteria, CriteriaSchedule, BatchedSystem}, math::Transform, input::{KeyCode, InputButtons, MouseMotion, ActionHandler, Layout, Action, ActionKind, LayoutId, ActionMapping, Binding, ActionSource, ActionMappingId, InputActionPlugin, ActionState}, game::Game, plugin::Plugin, render::{window::{CursorGrabMode, WindowOptions}, light::PointLight}, change_tracker::Ct}; use lyra_engine::assets::{ResourceManager, Model}; mod free_fly_camera; use free_fly_camera::{FreeFlyCameraPlugin, FreeFlyCamera}; use tracing::debug; struct FixedTimestep { max_tps: u32, fixed_time: f32, accumulator: f32, } impl FixedTimestep { pub fn new(max_tps: u32) -> Self { Self { max_tps, fixed_time: Self::calc_fixed_time(max_tps), accumulator: 0.0, } } fn calc_fixed_time(max_tps: u32) -> f32 { 1.0 / max_tps as f32 } fn set_tps(&mut self, tps: u32) { self.max_tps = tps; self.fixed_time = Self::calc_fixed_time(tps); } fn tps(&self) -> u32 { self.max_tps } fn fixed_time(&self) -> f32 { self.fixed_time } } impl Criteria for FixedTimestep { fn can_run(&mut self, world: &mut edict::World, check_count: u32) -> CriteriaSchedule { if check_count == 0 { let delta_time = world.get_resource::().unwrap(); self.accumulator += **delta_time; } if self.accumulator >= self.fixed_time { self.accumulator -= self.fixed_time; return CriteriaSchedule::YesAndLoop; } CriteriaSchedule::No } } #[derive(Clone)] struct TpsAccumulator(f32); #[async_std::main] async fn main() { let setup_sys = |world: &mut World| -> anyhow::Result<()> { { let mut window_options = world.get_resource_mut::>().unwrap(); window_options.cursor_grab = CursorGrabMode::Confined; window_options.cursor_visible = false; } let mut resman = world.get_resource_mut::().unwrap(); //let diffuse_texture = resman.request::("assets/happy-tree.png").unwrap(); let antique_camera_model = resman.request::("assets/AntiqueCamera.glb").unwrap(); let cube_model = resman.request::("assets/cube-texture-bin.glb").unwrap(); drop(resman); /* world.spawn(( ModelComponent(cube_model.clone()), TransformComponent::from(Transform::from_xyz(3.0, 0.5, -2.2)), )); */ world.spawn(( ModelComponent(antique_camera_model), TransformComponent::from(Transform::from_xyz(0.0, -5.0, -10.0)), )); /* let light = PointLight { color: Vec3::new(1.0, 1.0, 1.0), position: Vec3::new(0.0, -5.0, -8.0), constant: 1.0, linear: 0.09, quadratic: 0.032, }; world.spawn((light,)); */ let pos = Vec3::new(0.0, 0.0, -10.0); world.spawn(( PointLight { color: Vec3::new(1.0, 1.0, 1.0), intensity: 2.0, constant: 1.0, linear: 0.045, quadratic: 0.0075, }, TransformComponent::from(Transform::from_xyz(pos.x, pos.y, pos.z)), ModelComponent(cube_model), )); let mut camera = CameraComponent::new_3d(); camera.transform.translation += math::Vec3::new(0.0, 0.0, 7.5); //camera.transform.rotate_y(Angle::Degrees(-25.0)); //camera.transform.rotate_z(math::Angle::Degrees(-90.0)); world.spawn(( camera, FreeFlyCamera::default() )); Ok(()) }; let fps_system = |world: &mut World| -> anyhow::Result<()> { let mut counter = world.get_resource_mut::().unwrap(); let fps = counter.tick(); println!("FPS: {fps}"); Ok(()) }; let fps_plugin = move |game: &mut Game| { let world = game.world(); world.insert_resource(fps_counter::FPSCounter::new()); }; let spin_system = |world: &mut World| -> anyhow::Result<()> { const SPEED: f32 = 5.0; let delta_time = **world.get_resource::().unwrap(); for transform in world.query_mut::<(&mut TransformComponent,)>().iter_mut() { let t = &mut transform.transform; t.rotate_y(math::Angle::Degrees(SPEED * delta_time)); } Ok(()) }; let jiggle_plugin = move |game: &mut Game| { game.world().insert_resource(TpsAccumulator(0.0)); let mut sys = BatchedSystem::new(); sys.with_criteria(FixedTimestep::new(45)); sys.with_system(spin_system); sys.with_system(fps_system); game.with_system("fixed", sys, &[]); fps_plugin(game); }; let action_handler_plugin = |game: &mut Game| { let action_handler = ActionHandler::new() .add_layout(LayoutId::from(0)) .add_action("forward_backward", Action::new(ActionKind::Button)) .add_action("left_right", Action::new(ActionKind::Button)) .add_mapping(ActionMapping::new(LayoutId::from(0), ActionMappingId::from(0)) .bind("forward_backward", &[ ActionSource::Keyboard(KeyCode::W).into_binding_modifier(1.0), ActionSource::Keyboard(KeyCode::S).into_binding_modifier(-1.0) ]) .bind("left_right", &[ ActionSource::Keyboard(KeyCode::A).into_binding_modifier(1.0), ActionSource::Keyboard(KeyCode::D).into_binding_modifier(-1.0) ]) .finish() ); let test_system = |world: &mut World| -> anyhow::Result<()> { let handler = world.get_resource::().unwrap(); if let Some(alpha) = handler.get_pressed_modifier("forward_backward") { debug!("'forward_backward': {alpha}"); } if let Some(alpha) = handler.get_pressed_modifier("left_right") { debug!("'left_right': {alpha}"); } Ok(()) }; game.world().insert_resource(action_handler); game.with_plugin(InputActionPlugin); game.with_system("test_actions", test_system, &[]); }; Game::initialize().await .with_plugin(lyra_engine::DefaultPlugins) .with_startup_system(setup_sys) .with_plugin(action_handler_plugin) //.with_plugin(fps_plugin) .with_plugin(jiggle_plugin) .with_plugin(FreeFlyCameraPlugin) .run().await; }