Minor reorganization

master
Mark 2023-12-29 15:14:04 -08:00
parent c6f22557f2
commit da1b38cd33
Signed by: Mark
GPG Key ID: C6D63995FE72FD80
22 changed files with 156 additions and 107 deletions

12
Cargo.lock generated
View File

@ -573,6 +573,17 @@ version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817"
[[package]]
name = "galactica-content"
version = "0.0.0"
dependencies = [
"anyhow",
"cgmath",
"serde",
"toml",
"walkdir",
]
[[package]] [[package]]
name = "game" name = "game"
version = "0.1.0" version = "0.1.0"
@ -581,6 +592,7 @@ dependencies = [
"bytemuck", "bytemuck",
"cgmath", "cgmath",
"crossbeam", "crossbeam",
"galactica-content",
"image", "image",
"nalgebra", "nalgebra",
"pollster", "pollster",

View File

@ -26,7 +26,15 @@ panic = "abort"
incremental = false incremental = false
rpath = false rpath = false
[workspace]
members = ["crates/content"]
[dependencies] [dependencies]
# Internal crates
galactica-content = { path = "crates/content" }
# Files # Files
image = { version = "0.24", features = ["png"] } image = { version = "0.24", features = ["png"] }
toml = "0.8.8" toml = "0.8.8"
@ -35,12 +43,13 @@ serde = { version = "1.0.193", features = ["derive"] }
winit = "0.28" winit = "0.28"
wgpu = "0.18" wgpu = "0.18"
bytemuck = { version = "1.12", features = ["derive"] } bytemuck = { version = "1.12", features = ["derive"] }
# Physics
rapier2d = "0.17.2"
nalgebra = "0.32.3"
crossbeam = "0.8.3"
# Misc helpers # Misc helpers
pollster = "0.3" pollster = "0.3"
anyhow = "1.0" anyhow = "1.0"
cgmath = "0.18.0" cgmath = "0.18.0"
rand = "0.8.5" rand = "0.8.5"
walkdir = "2.4.0" walkdir = "2.4.0"
rapier2d = "0.17.2"
nalgebra = "0.32.3"
crossbeam = "0.8.3"

11
crates/content/Cargo.toml Normal file
View File

@ -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"

View File

@ -1,8 +1,8 @@
#![allow(dead_code)]
mod engine; mod engine;
mod gun; mod gun;
mod ship; mod ship;
mod system; mod system;
mod util;
pub use engine::Engine; pub use engine::Engine;
pub use gun::{Gun, Projectile}; pub use gun::{Gun, Projectile};

View File

@ -1,14 +1,15 @@
use cgmath::Point2;
use std::time::Instant; use std::time::Instant;
use winit::event::{ElementState, MouseButton, MouseScrollDelta, TouchPhase, VirtualKeyCode}; use winit::event::{ElementState, MouseButton, MouseScrollDelta, TouchPhase, VirtualKeyCode};
use super::{ use super::{camera::Camera, outfits, system::System, util};
camera::Camera, use crate::{
system::System, consts,
util, content::Content,
world::{ShipGun, ShipHandle, ShipOutfit, World}, inputstatus::InputStatus,
InputStatus, physics::{Physics, ShipHandle},
render::Sprite,
}; };
use crate::{consts, content::Content, render::Sprite};
pub struct Game { pub struct Game {
pub input: InputStatus, pub input: InputStatus,
@ -19,23 +20,32 @@ pub struct Game {
paused: bool, paused: bool,
pub time_scale: f32, pub time_scale: f32,
world: World, world: Physics,
} }
impl Game { impl Game {
pub fn new(ct: Content) -> Self { pub fn new(ct: Content) -> Self {
let mut world = World::new(); let mut world = Physics::new();
let c = world.add_ship( let c = world.add_ship(
&ct.ships[0], &ct.ships[0],
vec![ vec![
ShipOutfit::Gun(ShipGun::new(ct.guns[0].clone(), 1)), outfits::ShipOutfit::Gun(outfits::ShipGun::new(ct.guns[0].clone(), 1)),
ShipOutfit::Gun(ShipGun::new(ct.guns[0].clone(), 2)), outfits::ShipOutfit::Gun(outfits::ShipGun::new(ct.guns[0].clone(), 2)),
ShipOutfit::Engine(ct.engines[0].clone()), 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 { Game {
last_update: Instant::now(), last_update: Instant::now(),

View File

@ -1,11 +1,10 @@
mod camera; mod camera;
mod game; mod game;
mod inputstatus; pub mod objects;
pub mod outfits;
mod system; mod system;
mod systemobject; mod systemobject;
mod util; mod util;
mod world;
pub use game::Game; pub use game::Game;
pub use inputstatus::InputStatus;
pub use systemobject::SystemObject; pub use systemobject::SystemObject;

5
src/game/objects/mod.rs Normal file
View File

@ -0,0 +1,5 @@
mod projectile;
mod ship;
pub use projectile::{Projectile, ProjectileBuilder};
pub use ship::Ship;

View File

@ -6,16 +6,39 @@ use rapier2d::geometry::ColliderBuilder;
use rapier2d::pipeline::ActiveEvents; use rapier2d::pipeline::ActiveEvents;
use super::ProjectileBuilder; use super::ProjectileBuilder;
use super::{outfits::ShipOutfits, InputStatus, ShipControls, ShipOutfit, ShipTickResult};
use crate::game::{util, world::ShipHandle};
use crate::{ use crate::{
content, content,
game::{outfits, util},
inputstatus::InputStatus,
physics::ShipHandle,
render::{Sprite, SpriteTexture}, 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<ProjectileBuilder>,
}
pub struct Ship { pub struct Ship {
pub physics_handle: ShipHandle, pub physics_handle: ShipHandle,
outfits: ShipOutfits, outfits: outfits::ShipOutfits,
sprite: SpriteTexture, sprite: SpriteTexture,
size: f32, size: f32,
@ -26,8 +49,12 @@ pub struct Ship {
} }
impl Ship { impl Ship {
pub fn new(c: &content::Ship, outfits: Vec<ShipOutfit>, physics_handle: ShipHandle) -> Self { pub fn new(
let mut o = ShipOutfits::new(c); c: &content::Ship,
outfits: Vec<outfits::ShipOutfit>,
physics_handle: ShipHandle,
) -> Self {
let mut o = outfits::ShipOutfits::new(c);
for x in outfits.into_iter() { for x in outfits.into_iter() {
o.add(x) o.add(x)
} }

View File

@ -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);

View File

@ -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<ProjectileBuilder>,
}

View File

@ -1,10 +1,11 @@
mod consts; mod consts;
mod content;
mod game; mod game;
mod inputstatus;
mod physics;
mod render; mod render;
mod util;
use anyhow::Result; use anyhow::Result;
use galactica_content as content;
use winit::{ use winit::{
event::{Event, KeyboardInput, WindowEvent}, event::{Event, KeyboardInput, WindowEvent},
event_loop::{ControlFlow, EventLoop}, event_loop::{ControlFlow, EventLoop},

9
src/physics/mod.rs Normal file
View File

@ -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);

View File

@ -1,3 +1,4 @@
use cgmath::Point2;
use crossbeam::channel::Receiver; use crossbeam::channel::Receiver;
use nalgebra::vector; use nalgebra::vector;
use rapier2d::{ use rapier2d::{
@ -7,57 +8,59 @@ use rapier2d::{
}; };
use std::collections::HashMap; use std::collections::HashMap;
use super::{ use super::{wrapper::Wrapper, ShipHandle};
physicswrapper::PhysicsWrapper, Projectile, ProjectileBuilder, Ship, ShipHandle, ShipOutfit, 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. /// Keeps track of all objects in the world that we can interact with.
/// Also wraps our physics engine /// Also wraps our physics engine
pub struct World { pub struct Physics {
physics: PhysicsWrapper, wrapper: Wrapper,
projectiles: HashMap<ColliderHandle, Projectile>, projectiles: HashMap<ColliderHandle, objects::Projectile>,
ships: HashMap<ColliderHandle, Ship>, ships: HashMap<ColliderHandle, objects::Ship>,
collision_handler: ChannelEventCollector, collision_handler: ChannelEventCollector,
collision_queue: Receiver<CollisionEvent>, collision_queue: Receiver<CollisionEvent>,
} }
// Private methods // Private methods
impl World { impl Physics {
fn remove_projectile(&mut self, c: ColliderHandle) { fn remove_projectile(&mut self, c: ColliderHandle) {
let p = match self.projectiles.remove(&c) { let p = match self.projectiles.remove(&c) {
Some(p) => p, Some(p) => p,
None => return, None => return,
}; };
self.physics.rigid_body_set.remove( self.wrapper.rigid_body_set.remove(
p.rigid_body, p.rigid_body,
&mut self.physics.im, &mut self.wrapper.im,
&mut self.physics.collider_set, &mut self.wrapper.collider_set,
&mut self.physics.ij, &mut self.wrapper.ij,
&mut self.physics.mj, &mut self.wrapper.mj,
true, true,
); );
} }
fn remove_ship(&mut self, h: ShipHandle) { fn remove_ship(&mut self, h: ShipHandle) {
self.physics.rigid_body_set.remove( self.wrapper.rigid_body_set.remove(
h.0, h.0,
&mut self.physics.im, &mut self.wrapper.im,
&mut self.physics.collider_set, &mut self.wrapper.collider_set,
&mut self.physics.ij, &mut self.wrapper.ij,
&mut self.physics.mj, &mut self.wrapper.mj,
true, true,
); );
self.ships.remove(&h.1); self.ships.remove(&h.1);
} }
fn add_projectile(&mut self, pb: ProjectileBuilder) -> ColliderHandle { fn add_projectile(&mut self, pb: objects::ProjectileBuilder) -> ColliderHandle {
let r = self.physics.rigid_body_set.insert(pb.rigid_body.build()); let r = self.wrapper.rigid_body_set.insert(pb.rigid_body.build());
let c = self.physics.collider_set.insert_with_parent( let c = self.wrapper.collider_set.insert_with_parent(
pb.collider.build(), pb.collider.build(),
r, r,
&mut self.physics.rigid_body_set, &mut self.wrapper.rigid_body_set,
); );
self.projectiles.insert(c, pb.build(r, c)); self.projectiles.insert(c, pb.build(r, c));
return c; return c;
@ -65,13 +68,13 @@ impl World {
} }
// Public methods // Public methods
impl World { impl Physics {
pub fn new() -> Self { pub fn new() -> Self {
let (collision_send, collision_queue) = crossbeam::channel::unbounded(); let (collision_send, collision_queue) = crossbeam::channel::unbounded();
let (contact_force_send, _) = crossbeam::channel::unbounded(); let (contact_force_send, _) = crossbeam::channel::unbounded();
Self { Self {
physics: PhysicsWrapper::new(), wrapper: Wrapper::new(),
projectiles: HashMap::new(), projectiles: HashMap::new(),
ships: HashMap::new(), ships: HashMap::new(),
collision_handler: ChannelEventCollector::new(collision_send, contact_force_send), 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<ShipOutfit>) -> ShipHandle { pub fn add_ship(
&mut self,
ct: &content::Ship,
outfits: Vec<outfits::ShipOutfit>,
position: Point2<f32>,
) -> ShipHandle {
let rb = RigidBodyBuilder::dynamic() let rb = RigidBodyBuilder::dynamic()
.translation(vector![0.0, 0.0]) .translation(vector![position.x, position.y])
.can_sleep(false); .can_sleep(false);
let cl = ColliderBuilder::ball(50.0).restitution(0.7).mass(1.0); let cl = ColliderBuilder::ball(50.0).restitution(0.7).mass(1.0);
let r = self.physics.rigid_body_set.insert(rb.build()); let r = self.wrapper.rigid_body_set.insert(rb.build());
let c = self.physics.collider_set.insert_with_parent( let c = self.wrapper.collider_set.insert_with_parent(
cl.build(), cl.build(),
r, r,
&mut self.physics.rigid_body_set, &mut self.wrapper.rigid_body_set,
); );
let h = ShipHandle(r, c); 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; return h;
} }
@ -106,7 +114,7 @@ impl World {
to_remove.push(s.physics_handle); to_remove.push(s.physics_handle);
continue; 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)); res.push(s.tick(r, t));
} }
for r in to_remove { for r in to_remove {
@ -119,7 +127,7 @@ impl World {
} }
// Update physics // Update physics
self.physics.step(t, &self.collision_handler); self.wrapper.step(t, &self.collision_handler);
// Handle collision events // Handle collision events
while let Ok(event) = &self.collision_queue.try_recv() { while let Ok(event) = &self.collision_queue.try_recv() {
@ -159,22 +167,22 @@ impl World {
} }
pub fn get_rigid_body(&self, r: RigidBodyHandle) -> &RigidBody { 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() self.ships.get_mut(&s.1).unwrap()
} }
pub fn get_ship_sprites(&self) -> impl Iterator<Item = Sprite> + '_ { pub fn get_ship_sprites(&self) -> impl Iterator<Item = Sprite> + '_ {
self.ships self.ships
.values() .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<Item = Sprite> + '_ { pub fn get_projectile_sprites(&self) -> impl Iterator<Item = Sprite> + '_ {
self.projectiles self.projectiles
.values() .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]))
} }
} }

View File

@ -8,7 +8,7 @@ use rapier2d::{
pipeline::{EventHandler, PhysicsPipeline}, pipeline::{EventHandler, PhysicsPipeline},
}; };
pub(super) struct PhysicsWrapper { pub(super) struct Wrapper {
pub rigid_body_set: RigidBodySet, pub rigid_body_set: RigidBodySet,
pub collider_set: ColliderSet, pub collider_set: ColliderSet,
@ -22,7 +22,7 @@ pub(super) struct PhysicsWrapper {
pub ccd: CCDSolver, pub ccd: CCDSolver,
} }
impl PhysicsWrapper { impl Wrapper {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
rigid_body_set: RigidBodySet::new(), rigid_body_set: RigidBodySet::new(),