Skip to content

Commit

Permalink
Add physics system to GraphicsApplication
Browse files Browse the repository at this point in the history
  • Loading branch information
facundo-villa committed Dec 26, 2023
1 parent eee9701 commit 8fdcc89
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 24 deletions.
20 changes: 16 additions & 4 deletions src/application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -127,6 +127,7 @@ pub struct GraphicsApplication {
input_system_handle: orchestrator::EntityHandle<input_manager::InputManager>,
renderer_handle: orchestrator::EntityHandle<rendering::renderer::Renderer>,
audio_system_handle: orchestrator::EntityHandle<dyn audio_system::AudioSystem>,
physics_system_handle: orchestrator::EntityHandle<physics::PhysicsWorld>,
}

impl Application for GraphicsApplication {
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -236,6 +244,10 @@ impl GraphicsApplication {
&self.audio_system_handle
}

pub fn get_physics_world_handle(&self) -> &orchestrator::EntityHandle<crate::physics::PhysicsWorld> {
&self.physics_system_handle
}

pub fn do_loop(&mut self) {
while !self.application.close {
self.tick();
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down
23 changes: 12 additions & 11 deletions src/orchestrator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,11 +143,11 @@ pub trait Event {

pub struct EventImplementation<I, V> where I: Entity {
entity: EntityHandle<I>,
function: fn(&mut I, V),
function: fn(&mut I, OrchestratorReference, V),
}

impl <I: Entity, V: Copy + 'static> EventImplementation<I, V> {
pub fn new(entity: EntityHandle<I>, function: fn(&mut I, V)) -> Self {
pub fn new(entity: EntityHandle<I>, function: fn(&mut I, OrchestratorReference, V)) -> Self {
Self {
entity,
function,
Expand All @@ -161,7 +161,7 @@ impl <T: Entity, V: Copy + 'static> Event for EventImplementation<T, V> {

let value = value.downcast_ref::<V>().unwrap();

(self.function)(lock.deref_mut(), *value);
(self.function)(lock.deref_mut(), OrchestratorReference { orchestrator, internal_id: self.entity.internal_id }, *value);
}
}

Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -420,19 +420,20 @@ impl Orchestrator {
(getter)(component.downcast_ref::<C>().unwrap())
}

pub fn invoke_mut<E: Entity + 'static>(&self, handle: &EntityHandle<E>, 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::<E>().unwrap();
function(component, OrchestratorReference { orchestrator: self, internal_id: handle.external_id });
pub fn invoke_mut<E: Entity + 'static>(&self, handle: &mut EntityHandle<E>, 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<S: System + ?Sized + 'static>(&self, entity_handle: &EntityHandle<S>) -> EntityReference<S> {
let systems_data = self.systems_data.read().unwrap();
EntityReference { lock: std::rc::Rc::clone(&entity_handle.container) }
}

pub fn subscribe_to<T: Entity, E: Entity, V: Copy + 'static>(&mut self, subscriber_handle: &EntityHandle<T>, provoking_component: &EntityHandle<E>, provoking_property: fn() -> Property2<E, V>, function_to_invoke: fn(&mut T, V)) {
pub fn subscribe_to<T: Entity, E: Entity, V: Copy + 'static>(&mut self, subscriber_handle: &EntityHandle<T>, provoking_component: &EntityHandle<E>, provoking_property: fn() -> Property2<E, V>, 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 {
Expand Down Expand Up @@ -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;
}
Expand Down
50 changes: 50 additions & 0 deletions src/physics/mod.rs
Original file line number Diff line number Diff line change
@@ -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<Sphere>,
}

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 {}
24 changes: 16 additions & 8 deletions tests/gallery_shooter.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
#![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]
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());

Expand All @@ -26,7 +27,7 @@ fn gallery_shooter() {
],)
);

let mut player: EntityHandle<Player> = orchestrator.spawn_entity(Player::new(lookaround_action_handle, audio_system_handle)).expect("Failed to spawn player");
let mut player: EntityHandle<Player> = 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::<bool>::value, Player::shoot);

Expand All @@ -53,6 +54,7 @@ struct Player {
camera: EntityHandle<byte_engine::camera::Camera>,

audio_system: EntityHandle<dyn byte_engine::audio::audio_system::AudioSystem>,
physics_world: EntityHandle<physics::PhysicsWorld>,

magazine_size: Property<usize>,
magazine_as_string: DerivedProperty<usize, String>,
Expand All @@ -67,7 +69,7 @@ impl Component for Player {
}

impl Player {
fn new(lookaround: EntityHandle<Action<Vec3f>>, audio_system: EntityHandle<dyn AudioSystem>) -> orchestrator::EntityReturn<'static, Self> {
fn new(lookaround: EntityHandle<Action<Vec3f>>, audio_system: EntityHandle<dyn AudioSystem>, physics_world_handle: EntityHandle<physics::PhysicsWorld>) -> orchestrator::EntityReturn<'static, Self> {
orchestrator::EntityReturn::new_from_closure(move |orchestrator| {
let mut transform = maths_rs::Mat4f::identity();

Expand All @@ -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)),

Expand All @@ -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 {
Expand All @@ -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<physics::PhysicsWorld>, 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,)),
}
Expand Down

0 comments on commit 8fdcc89

Please sign in to comment.