diff --git a/src/application.rs b/src/application.rs index 46309243..c3acc400 100644 --- a/src/application.rs +++ b/src/application.rs @@ -60,7 +60,7 @@ impl Application for BaseApplication { use log::{info, trace}; use maths_rs::prelude::Base; -use crate::{orchestrator::{self, EntityHandle}, window_system, input_manager, Vector2, rendering::{self}, resource_management, file_tracker, audio::audio_system}; +use crate::{orchestrator::{self, EntityHandle}, window_system, input_manager, Vector2, rendering::{self}, resource_management, file_tracker, audio::audio_system, physics}; /// An orchestrated application is an application that uses the orchestrator to manage systems. /// It is the recommended way to create a simple application. @@ -127,6 +127,7 @@ pub struct GraphicsApplication { input_system_handle: orchestrator::EntityHandle, renderer_handle: orchestrator::EntityHandle, audio_system_handle: orchestrator::EntityHandle, + physics_system_handle: orchestrator::EntityHandle, } impl Application for GraphicsApplication { @@ -169,7 +170,9 @@ impl Application for GraphicsApplication { let audio_system_handle = orchestrator.spawn_entity(audio_system::DefaultAudioSystem::new_as_system(resource_manager_handle.clone())).unwrap(); - GraphicsApplication { application, file_tracker_handle, window_system_handle, input_system_handle, mouse_device_handle, renderer_handle, tick_count: 0, audio_system_handle } + let physics_system_handle = orchestrator.spawn_entity(physics::PhysicsWorld::new_as_system()).unwrap(); + + GraphicsApplication { application, file_tracker_handle, window_system_handle, input_system_handle, mouse_device_handle, renderer_handle, tick_count: 0, audio_system_handle, physics_system_handle } } fn initialize(&mut self, _arguments: std::env::Args) { @@ -203,8 +206,13 @@ impl Application for GraphicsApplication { true }); - self.application.get_orchestrator().invoke_mut(&self.input_system_handle, input_manager::InputManager::update); - self.application.get_orchestrator().invoke_mut(&self.renderer_handle, rendering::renderer::Renderer::render); + self.application.get_orchestrator().invoke_mut(&mut self.input_system_handle, input_manager::InputManager::update); + + self.physics_system_handle.get_mut(|physics_system| { + physics_system.update(); + }); + + self.application.get_orchestrator().invoke_mut(&mut self.renderer_handle, rendering::renderer::Renderer::render); self.audio_system_handle.get_mut(|audio_system| { audio_system.render(); @@ -236,6 +244,10 @@ impl GraphicsApplication { &self.audio_system_handle } + pub fn get_physics_world_handle(&self) -> &orchestrator::EntityHandle { + &self.physics_system_handle + } + pub fn do_loop(&mut self) { while !self.application.close { self.tick(); diff --git a/src/lib.rs b/src/lib.rs index 0be39247..415b4feb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -31,7 +31,7 @@ pub mod math; pub mod rendering; pub mod gameplay; pub mod jspd; -//pub mod gdeflate; +pub mod physics; pub use maths_rs::{Vec2f, Vec3f, Quatf, prelude::Base}; use serde::{Serialize, Deserialize}; diff --git a/src/orchestrator.rs b/src/orchestrator.rs index 9fb40527..02acdb64 100644 --- a/src/orchestrator.rs +++ b/src/orchestrator.rs @@ -143,11 +143,11 @@ pub trait Event { pub struct EventImplementation where I: Entity { entity: EntityHandle, - function: fn(&mut I, V), + function: fn(&mut I, OrchestratorReference, V), } impl EventImplementation { - pub fn new(entity: EntityHandle, function: fn(&mut I, V)) -> Self { + pub fn new(entity: EntityHandle, function: fn(&mut I, OrchestratorReference, V)) -> Self { Self { entity, function, @@ -161,7 +161,7 @@ impl Event for EventImplementation { let value = value.downcast_ref::().unwrap(); - (self.function)(lock.deref_mut(), *value); + (self.function)(lock.deref_mut(), OrchestratorReference { orchestrator, internal_id: self.entity.internal_id }, *value); } } @@ -221,7 +221,7 @@ impl <'c, T: Entity + 'static> EntityReturn<'c, T> { } } - pub fn new_from_closure<'a, F: FnOnce(OrchestratorReference) -> T + 'static>(function: F) -> Self { + pub fn new_from_closure<'a, F: FnOnce(OrchestratorReference) -> T + 'c>(function: F) -> Self { Self { create: std::boxed::Box::new(function), post_creation_functions: Vec::new(), @@ -420,11 +420,12 @@ impl Orchestrator { (getter)(component.downcast_ref::().unwrap()) } - pub fn invoke_mut(&self, handle: &EntityHandle, function: fn(&mut E, OrchestratorReference)) { - let systems_data = self.systems_data.read().unwrap(); - let mut component = systems_data.systems[&handle.internal_id].write().unwrap(); - let component = component.downcast_mut::().unwrap(); - function(component, OrchestratorReference { orchestrator: self, internal_id: handle.external_id }); + pub fn invoke_mut(&self, handle: &mut EntityHandle, function: fn(&mut E, OrchestratorReference)) { + let external_id = handle.external_id; + + handle.get_mut(|c| { + function(c, OrchestratorReference { orchestrator: self, internal_id: external_id }); + }) } pub fn get_entity(&self, entity_handle: &EntityHandle) -> EntityReference { @@ -432,7 +433,7 @@ impl Orchestrator { EntityReference { lock: std::rc::Rc::clone(&entity_handle.container) } } - pub fn subscribe_to(&mut self, subscriber_handle: &EntityHandle, provoking_component: &EntityHandle, provoking_property: fn() -> Property2, function_to_invoke: fn(&mut T, V)) { + pub fn subscribe_to(&mut self, subscriber_handle: &EntityHandle, provoking_component: &EntityHandle, provoking_property: fn() -> Property2, function_to_invoke: fn(&mut T, OrchestratorReference, V)) { if let std::collections::hash_map::Entry::Occupied(mut e) = self.events.entry((EntityHash::from(provoking_component), provoking_property.addr())) { e.get_mut().push(Box::new(EventImplementation::new(subscriber_handle.clone(), function_to_invoke))); } else { @@ -605,7 +606,7 @@ mod tests { EntityReturn::new(MySystem {}) } - fn on_event(&mut self, value: bool) { + fn on_event(&mut self, _: OrchestratorReference, value: bool) { unsafe { COUNTER += 1; } diff --git a/src/physics/mod.rs b/src/physics/mod.rs new file mode 100644 index 00000000..489c69c7 --- /dev/null +++ b/src/physics/mod.rs @@ -0,0 +1,50 @@ +use maths_rs::Vec3f; + +use crate::orchestrator::{Entity, System, EntityReturn}; + +pub struct Sphere { + position: Vec3f, + velocity: Vec3f, + radius: f32, +} + +impl Sphere { + pub fn new(position: Vec3f, velocity: Vec3f, radius: f32) -> Self { + Self { + position, + velocity, + radius, + } + } +} + +pub struct PhysicsWorld { + spheres: Vec, +} + +impl PhysicsWorld { + fn new() -> Self { + Self { + spheres: Vec::new(), + } + } + + pub fn new_as_system() -> EntityReturn<'static, Self> { + EntityReturn::new(Self::new()) + } + + pub fn add_sphere(&mut self, sphere: Sphere) { + self.spheres.push(sphere); + } + + pub fn update(&mut self) { + for sphere in self.spheres.iter_mut() { + sphere.position += sphere.velocity; + + log::info!("Sphere position: {:?}", sphere.position); + } + } +} + +impl Entity for PhysicsWorld {} +impl System for PhysicsWorld {} \ No newline at end of file diff --git a/tests/gallery_shooter.rs b/tests/gallery_shooter.rs index eee81336..0bcaded0 100644 --- a/tests/gallery_shooter.rs +++ b/tests/gallery_shooter.rs @@ -1,7 +1,7 @@ #![feature(const_mut_refs)] -use byte_engine::{application::Application, Vec3f, input_manager::{self, Action}, Vector3, orchestrator::{Component, EntityHandle, self, Property, DerivedProperty,}, math, rendering::mesh, rendering::point_light::PointLight, audio::audio_system::AudioSystem, ui::{self, Text}}; -use maths_rs::prelude::{MatTranslate, MatScale, MatInverse}; +use byte_engine::{application::Application, Vec3f, input_manager::{self, Action}, Vector3, orchestrator::{Component, EntityHandle, self, Property, DerivedProperty,}, math, rendering::mesh, rendering::point_light::PointLight, audio::audio_system::AudioSystem, ui::{self, Text}, physics}; +use maths_rs::{prelude::{MatTranslate, MatScale, MatInverse}, vec::Vec3}; #[ignore] #[test] @@ -9,6 +9,7 @@ fn gallery_shooter() { let mut app = byte_engine::application::GraphicsApplication::new("Gallery Shooter"); let audio_system_handle = app.get_audio_system_handle().clone(); + let physics_world_handle = app.get_physics_world_handle().clone(); app.initialize(std::env::args()); @@ -26,7 +27,7 @@ fn gallery_shooter() { ],) ); - let mut player: EntityHandle = orchestrator.spawn_entity(Player::new(lookaround_action_handle, audio_system_handle)).expect("Failed to spawn player"); + let mut player: EntityHandle = orchestrator.spawn_entity(Player::new(lookaround_action_handle, audio_system_handle, physics_world_handle)).expect("Failed to spawn player"); orchestrator.subscribe_to(&player, &trigger_action, input_manager::Action::::value, Player::shoot); @@ -53,6 +54,7 @@ struct Player { camera: EntityHandle, audio_system: EntityHandle, + physics_world: EntityHandle, magazine_size: Property, magazine_as_string: DerivedProperty, @@ -67,7 +69,7 @@ impl Component for Player { } impl Player { - fn new(lookaround: EntityHandle>, audio_system: EntityHandle) -> orchestrator::EntityReturn<'static, Self> { + fn new(lookaround: EntityHandle>, audio_system: EntityHandle, physics_world_handle: EntityHandle) -> orchestrator::EntityReturn<'static, Self> { orchestrator::EntityReturn::new_from_closure(move |orchestrator| { let mut transform = maths_rs::Mat4f::identity(); @@ -83,6 +85,8 @@ impl Player { Self { audio_system: audio_system, + physics_world: physics_world_handle, + camera: camera_handle, mesh: orchestrator.spawn(mesh::Mesh::new("Box", "solid", transform)), @@ -95,11 +99,11 @@ impl Player { } impl Player { - fn shoot(&mut self, value: bool) { + fn shoot(&mut self, orchestrator: orchestrator::OrchestratorReference, value: bool) { if value { self.audio_system.get_mut(|audio_system| audio_system.play("gun")); - // TODO: spawn bullet + orchestrator.spawn_entity(Bullet::new(&mut self.physics_world, Vec3::new(0.0, 0.0, 0.0))); self.magazine_size.set(|value| { if value - 1 == 0 { @@ -117,16 +121,20 @@ struct Bullet { } impl orchestrator::Entity for Bullet {} -impl orchestrator::System for Bullet {} +impl orchestrator::Component for Bullet {} impl Bullet { - fn new(position: Vec3f) -> orchestrator::EntityReturn<'static, Self> { + fn new(physics_world_handle: &mut EntityHandle, position: Vec3f) -> orchestrator::EntityReturn<'_, Self> { orchestrator::EntityReturn::new_from_closure(move |orchestrator| { let mut transform = maths_rs::Mat4f::identity(); transform *= maths_rs::Mat4f::from_translation(Vec3f::new(0.0, 0.0, 0.0)); transform *= maths_rs::Mat4f::from_scale(Vec3f::new(0.05, 0.05, 0.05)); + physics_world_handle.get_mut(|physics_world| { + physics_world.add_sphere(physics::Sphere::new(position, Vec3f::new(0.0, 0.0, 1.0), 0.1)); + }); + Self { mesh: orchestrator.spawn(mesh::Mesh::new("Sphere", "solid", transform,)), }