diff --git a/Cargo.lock b/Cargo.lock index 7c9ab04..ceee21c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -573,6 +573,17 @@ version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" +[[package]] +name = "galactica-content" +version = "0.0.0" +dependencies = [ + "anyhow", + "cgmath", + "serde", + "toml", + "walkdir", +] + [[package]] name = "game" version = "0.1.0" @@ -581,6 +592,7 @@ dependencies = [ "bytemuck", "cgmath", "crossbeam", + "galactica-content", "image", "nalgebra", "pollster", diff --git a/Cargo.toml b/Cargo.toml index d537eab..52a2cc1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,7 +26,15 @@ panic = "abort" incremental = false rpath = false + +[workspace] +members = ["crates/content"] + + [dependencies] +# Internal crates +galactica-content = { path = "crates/content" } + # Files image = { version = "0.24", features = ["png"] } toml = "0.8.8" @@ -35,12 +43,13 @@ serde = { version = "1.0.193", features = ["derive"] } winit = "0.28" wgpu = "0.18" bytemuck = { version = "1.12", features = ["derive"] } +# Physics +rapier2d = "0.17.2" +nalgebra = "0.32.3" +crossbeam = "0.8.3" # Misc helpers pollster = "0.3" anyhow = "1.0" cgmath = "0.18.0" rand = "0.8.5" walkdir = "2.4.0" -rapier2d = "0.17.2" -nalgebra = "0.32.3" -crossbeam = "0.8.3" diff --git a/crates/content/Cargo.toml b/crates/content/Cargo.toml new file mode 100644 index 0000000..28c2d79 --- /dev/null +++ b/crates/content/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "galactica-content" +version = "0.0.0" +edition = "2021" + +[dependencies] +toml = "0.8.8" +serde = { version = "1.0.193", features = ["derive"] } +anyhow = "1.0" +cgmath = "0.18.0" +walkdir = "2.4.0" diff --git a/src/content/engine.rs b/crates/content/src/engine.rs similarity index 100% rename from src/content/engine.rs rename to crates/content/src/engine.rs diff --git a/src/content/gun.rs b/crates/content/src/gun.rs similarity index 100% rename from src/content/gun.rs rename to crates/content/src/gun.rs diff --git a/src/content/mod.rs b/crates/content/src/lib.rs similarity index 99% rename from src/content/mod.rs rename to crates/content/src/lib.rs index 34305f1..1fcb4b1 100644 --- a/src/content/mod.rs +++ b/crates/content/src/lib.rs @@ -1,8 +1,8 @@ -#![allow(dead_code)] mod engine; mod gun; mod ship; mod system; +mod util; pub use engine::Engine; pub use gun::{Gun, Projectile}; diff --git a/src/content/ship.rs b/crates/content/src/ship.rs similarity index 100% rename from src/content/ship.rs rename to crates/content/src/ship.rs diff --git a/src/content/system.rs b/crates/content/src/system.rs similarity index 100% rename from src/content/system.rs rename to crates/content/src/system.rs diff --git a/src/util.rs b/crates/content/src/util.rs similarity index 100% rename from src/util.rs rename to crates/content/src/util.rs diff --git a/src/game/game.rs b/src/game/game.rs index d4ddea7..29ea89d 100644 --- a/src/game/game.rs +++ b/src/game/game.rs @@ -1,14 +1,15 @@ +use cgmath::Point2; use std::time::Instant; use winit::event::{ElementState, MouseButton, MouseScrollDelta, TouchPhase, VirtualKeyCode}; -use super::{ - camera::Camera, - system::System, - util, - world::{ShipGun, ShipHandle, ShipOutfit, World}, - InputStatus, +use super::{camera::Camera, outfits, system::System, util}; +use crate::{ + consts, + content::Content, + inputstatus::InputStatus, + physics::{Physics, ShipHandle}, + render::Sprite, }; -use crate::{consts, content::Content, render::Sprite}; pub struct Game { pub input: InputStatus, @@ -19,23 +20,32 @@ pub struct Game { paused: bool, pub time_scale: f32, - world: World, + world: Physics, } impl Game { pub fn new(ct: Content) -> Self { - let mut world = World::new(); + let mut world = Physics::new(); let c = world.add_ship( &ct.ships[0], vec![ - ShipOutfit::Gun(ShipGun::new(ct.guns[0].clone(), 1)), - ShipOutfit::Gun(ShipGun::new(ct.guns[0].clone(), 2)), - ShipOutfit::Engine(ct.engines[0].clone()), + outfits::ShipOutfit::Gun(outfits::ShipGun::new(ct.guns[0].clone(), 1)), + outfits::ShipOutfit::Gun(outfits::ShipGun::new(ct.guns[0].clone(), 2)), + outfits::ShipOutfit::Engine(ct.engines[0].clone()), ], + Point2 { x: 0.0, y: 0.0 }, ); - world.add_ship(&ct.ships[0], vec![]); + world.add_ship(&ct.ships[0], vec![], Point2 { x: 300.0, y: 300.0 }); + world.add_ship( + &ct.ships[0], + vec![], + Point2 { + x: -300.0, + y: 300.0, + }, + ); Game { last_update: Instant::now(), diff --git a/src/game/mod.rs b/src/game/mod.rs index 7302468..918b090 100644 --- a/src/game/mod.rs +++ b/src/game/mod.rs @@ -1,11 +1,10 @@ mod camera; mod game; -mod inputstatus; +pub mod objects; +pub mod outfits; mod system; mod systemobject; mod util; -mod world; pub use game::Game; -pub use inputstatus::InputStatus; pub use systemobject::SystemObject; diff --git a/src/game/objects/mod.rs b/src/game/objects/mod.rs new file mode 100644 index 0000000..5e8aba8 --- /dev/null +++ b/src/game/objects/mod.rs @@ -0,0 +1,5 @@ +mod projectile; +mod ship; + +pub use projectile::{Projectile, ProjectileBuilder}; +pub use ship::Ship; diff --git a/src/game/world/projectile.rs b/src/game/objects/projectile.rs similarity index 100% rename from src/game/world/projectile.rs rename to src/game/objects/projectile.rs diff --git a/src/game/world/ship/ship.rs b/src/game/objects/ship.rs similarity index 86% rename from src/game/world/ship/ship.rs rename to src/game/objects/ship.rs index 9ab82f1..5cea722 100644 --- a/src/game/world/ship/ship.rs +++ b/src/game/objects/ship.rs @@ -6,16 +6,39 @@ use rapier2d::geometry::ColliderBuilder; use rapier2d::pipeline::ActiveEvents; use super::ProjectileBuilder; -use super::{outfits::ShipOutfits, InputStatus, ShipControls, ShipOutfit, ShipTickResult}; -use crate::game::{util, world::ShipHandle}; use crate::{ content, + game::{outfits, util}, + inputstatus::InputStatus, + physics::ShipHandle, render::{Sprite, SpriteTexture}, }; +pub struct ShipControls { + pub left: bool, + pub right: bool, + pub thrust: bool, + pub guns: bool, +} + +impl ShipControls { + pub fn new() -> Self { + ShipControls { + left: false, + right: false, + thrust: false, + guns: false, + } + } +} + +pub struct ShipTickResult { + pub projectiles: Vec, +} + pub struct Ship { pub physics_handle: ShipHandle, - outfits: ShipOutfits, + outfits: outfits::ShipOutfits, sprite: SpriteTexture, size: f32, @@ -26,8 +49,12 @@ pub struct Ship { } impl Ship { - pub fn new(c: &content::Ship, outfits: Vec, physics_handle: ShipHandle) -> Self { - let mut o = ShipOutfits::new(c); + pub fn new( + c: &content::Ship, + outfits: Vec, + physics_handle: ShipHandle, + ) -> Self { + let mut o = outfits::ShipOutfits::new(c); for x in outfits.into_iter() { o.add(x) } diff --git a/src/game/world/ship/outfits.rs b/src/game/outfits.rs similarity index 100% rename from src/game/world/ship/outfits.rs rename to src/game/outfits.rs diff --git a/src/game/world/mod.rs b/src/game/world/mod.rs deleted file mode 100644 index fa2fd1d..0000000 --- a/src/game/world/mod.rs +++ /dev/null @@ -1,13 +0,0 @@ -mod physicswrapper; -mod projectile; -mod ship; -mod world; - -pub use projectile::{Projectile, ProjectileBuilder}; -pub use ship::{Ship, ShipControls, ShipGun, ShipOutfit, ShipOutfits, ShipTickResult}; -pub use world::World; - -use rapier2d::{dynamics::RigidBodyHandle, geometry::ColliderHandle}; - -#[derive(Debug, Copy, Clone)] -pub struct ShipHandle(pub(in super::super) RigidBodyHandle, ColliderHandle); diff --git a/src/game/world/ship/mod.rs b/src/game/world/ship/mod.rs deleted file mode 100644 index 64b96c6..0000000 --- a/src/game/world/ship/mod.rs +++ /dev/null @@ -1,29 +0,0 @@ -mod outfits; -mod ship; - -pub use outfits::{ShipGun, ShipOutfit, ShipOutfits}; -pub use ship::Ship; - -use super::{super::InputStatus, ProjectileBuilder}; - -pub struct ShipControls { - pub left: bool, - pub right: bool, - pub thrust: bool, - pub guns: bool, -} - -impl ShipControls { - pub fn new() -> Self { - ShipControls { - left: false, - right: false, - thrust: false, - guns: false, - } - } -} - -pub struct ShipTickResult { - pub projectiles: Vec, -} diff --git a/src/game/inputstatus.rs b/src/inputstatus.rs similarity index 100% rename from src/game/inputstatus.rs rename to src/inputstatus.rs diff --git a/src/main.rs b/src/main.rs index 66af9eb..b3cd953 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,10 +1,11 @@ mod consts; -mod content; mod game; +mod inputstatus; +mod physics; mod render; -mod util; use anyhow::Result; +use galactica_content as content; use winit::{ event::{Event, KeyboardInput, WindowEvent}, event_loop::{ControlFlow, EventLoop}, diff --git a/src/physics/mod.rs b/src/physics/mod.rs new file mode 100644 index 0000000..2c37c70 --- /dev/null +++ b/src/physics/mod.rs @@ -0,0 +1,9 @@ +mod physics; +mod wrapper; + +pub use physics::Physics; + +use rapier2d::{dynamics::RigidBodyHandle, geometry::ColliderHandle}; + +#[derive(Debug, Copy, Clone)] +pub struct ShipHandle(pub(super) RigidBodyHandle, ColliderHandle); diff --git a/src/game/world/world.rs b/src/physics/physics.rs similarity index 64% rename from src/game/world/world.rs rename to src/physics/physics.rs index d7d71df..0a2df18 100644 --- a/src/game/world/world.rs +++ b/src/physics/physics.rs @@ -1,3 +1,4 @@ +use cgmath::Point2; use crossbeam::channel::Receiver; use nalgebra::vector; use rapier2d::{ @@ -7,57 +8,59 @@ use rapier2d::{ }; use std::collections::HashMap; -use super::{ - physicswrapper::PhysicsWrapper, Projectile, ProjectileBuilder, Ship, ShipHandle, ShipOutfit, +use super::{wrapper::Wrapper, ShipHandle}; +use crate::{ + content, + game::{objects, outfits}, + render::Sprite, }; -use crate::{content, render::Sprite}; /// Keeps track of all objects in the world that we can interact with. /// Also wraps our physics engine -pub struct World { - physics: PhysicsWrapper, - projectiles: HashMap, - ships: HashMap, +pub struct Physics { + wrapper: Wrapper, + projectiles: HashMap, + ships: HashMap, collision_handler: ChannelEventCollector, collision_queue: Receiver, } // Private methods -impl World { +impl Physics { fn remove_projectile(&mut self, c: ColliderHandle) { let p = match self.projectiles.remove(&c) { Some(p) => p, None => return, }; - self.physics.rigid_body_set.remove( + self.wrapper.rigid_body_set.remove( p.rigid_body, - &mut self.physics.im, - &mut self.physics.collider_set, - &mut self.physics.ij, - &mut self.physics.mj, + &mut self.wrapper.im, + &mut self.wrapper.collider_set, + &mut self.wrapper.ij, + &mut self.wrapper.mj, true, ); } fn remove_ship(&mut self, h: ShipHandle) { - self.physics.rigid_body_set.remove( + self.wrapper.rigid_body_set.remove( h.0, - &mut self.physics.im, - &mut self.physics.collider_set, - &mut self.physics.ij, - &mut self.physics.mj, + &mut self.wrapper.im, + &mut self.wrapper.collider_set, + &mut self.wrapper.ij, + &mut self.wrapper.mj, true, ); self.ships.remove(&h.1); } - fn add_projectile(&mut self, pb: ProjectileBuilder) -> ColliderHandle { - let r = self.physics.rigid_body_set.insert(pb.rigid_body.build()); - let c = self.physics.collider_set.insert_with_parent( + fn add_projectile(&mut self, pb: objects::ProjectileBuilder) -> ColliderHandle { + let r = self.wrapper.rigid_body_set.insert(pb.rigid_body.build()); + let c = self.wrapper.collider_set.insert_with_parent( pb.collider.build(), r, - &mut self.physics.rigid_body_set, + &mut self.wrapper.rigid_body_set, ); self.projectiles.insert(c, pb.build(r, c)); return c; @@ -65,13 +68,13 @@ impl World { } // Public methods -impl World { +impl Physics { pub fn new() -> Self { let (collision_send, collision_queue) = crossbeam::channel::unbounded(); let (contact_force_send, _) = crossbeam::channel::unbounded(); Self { - physics: PhysicsWrapper::new(), + wrapper: Wrapper::new(), projectiles: HashMap::new(), ships: HashMap::new(), collision_handler: ChannelEventCollector::new(collision_send, contact_force_send), @@ -79,21 +82,26 @@ impl World { } } - pub fn add_ship(&mut self, ct: &content::Ship, outfits: Vec) -> ShipHandle { + pub fn add_ship( + &mut self, + ct: &content::Ship, + outfits: Vec, + position: Point2, + ) -> ShipHandle { let rb = RigidBodyBuilder::dynamic() - .translation(vector![0.0, 0.0]) + .translation(vector![position.x, position.y]) .can_sleep(false); let cl = ColliderBuilder::ball(50.0).restitution(0.7).mass(1.0); - let r = self.physics.rigid_body_set.insert(rb.build()); - let c = self.physics.collider_set.insert_with_parent( + let r = self.wrapper.rigid_body_set.insert(rb.build()); + let c = self.wrapper.collider_set.insert_with_parent( cl.build(), r, - &mut self.physics.rigid_body_set, + &mut self.wrapper.rigid_body_set, ); let h = ShipHandle(r, c); - self.ships.insert(c, Ship::new(ct, outfits, h)); + self.ships.insert(c, objects::Ship::new(ct, outfits, h)); return h; } @@ -106,7 +114,7 @@ impl World { to_remove.push(s.physics_handle); continue; } - let r = &mut self.physics.rigid_body_set[s.physics_handle.0]; + let r = &mut self.wrapper.rigid_body_set[s.physics_handle.0]; res.push(s.tick(r, t)); } for r in to_remove { @@ -119,7 +127,7 @@ impl World { } // Update physics - self.physics.step(t, &self.collision_handler); + self.wrapper.step(t, &self.collision_handler); // Handle collision events while let Ok(event) = &self.collision_queue.try_recv() { @@ -159,22 +167,22 @@ impl World { } pub fn get_rigid_body(&self, r: RigidBodyHandle) -> &RigidBody { - &self.physics.rigid_body_set[r] + &self.wrapper.rigid_body_set[r] } - pub fn get_ship_mut(&mut self, s: &ShipHandle) -> &mut Ship { + pub fn get_ship_mut(&mut self, s: &ShipHandle) -> &mut objects::Ship { self.ships.get_mut(&s.1).unwrap() } pub fn get_ship_sprites(&self) -> impl Iterator + '_ { self.ships .values() - .map(|x| x.get_sprite(&self.physics.rigid_body_set[x.physics_handle.0])) + .map(|x| x.get_sprite(&self.wrapper.rigid_body_set[x.physics_handle.0])) } pub fn get_projectile_sprites(&self) -> impl Iterator + '_ { self.projectiles .values() - .map(|x| x.get_sprite(&self.physics.rigid_body_set[x.rigid_body])) + .map(|x| x.get_sprite(&self.wrapper.rigid_body_set[x.rigid_body])) } } diff --git a/src/game/world/physicswrapper.rs b/src/physics/wrapper.rs similarity index 95% rename from src/game/world/physicswrapper.rs rename to src/physics/wrapper.rs index 9054841..6f8a578 100644 --- a/src/game/world/physicswrapper.rs +++ b/src/physics/wrapper.rs @@ -8,7 +8,7 @@ use rapier2d::{ pipeline::{EventHandler, PhysicsPipeline}, }; -pub(super) struct PhysicsWrapper { +pub(super) struct Wrapper { pub rigid_body_set: RigidBodySet, pub collider_set: ColliderSet, @@ -22,7 +22,7 @@ pub(super) struct PhysicsWrapper { pub ccd: CCDSolver, } -impl PhysicsWrapper { +impl Wrapper { pub fn new() -> Self { Self { rigid_body_set: RigidBodySet::new(),