diff --git a/src/doodad.rs b/src/doodad.rs index 1ab67f1..2341001 100644 --- a/src/doodad.rs +++ b/src/doodad.rs @@ -3,29 +3,21 @@ use sdl2::render::Canvas; use sdl2::video::Window; use crate::physics::PhysVec; +use crate::physics::Position; use crate::Camera; use crate::Drawable; use crate::SpriteAtlas; pub struct Doodad { - sprite: String, - pos: PhysVec, - scale: u32, -} - -impl Doodad { - pub fn new(pos: PhysVec) -> Self { - Doodad { - sprite: "a0.png".to_owned(), - pos, - scale: 1, - } - } + pub sprite: String, + pub pos: Position, + pub scale: u32, + pub angle: f64, } impl Drawable for Doodad { fn position(&self) -> PhysVec { - self.pos + self.pos.to_cartesian().into() } fn draw( @@ -48,10 +40,15 @@ impl Drawable for Doodad { let sprite = sa.get(&self.sprite); - let mut dest_rect_0 = Rect::new(0, 0, 112 / self.scale, 112 / self.scale); + let mut dest_rect_0 = Rect::new( + 0, + 0, + sprite.rect.width() / self.scale, + sprite.rect.height() / self.scale, + ); dest_rect_0.center_on(Point::new( - 112 / (2 * self.scale) as i32, - 112 / (2 * self.scale) as i32, + sprite.rect.width() as i32 / (2 * self.scale) as i32, + sprite.rect.height() as i32 / (2 * self.scale) as i32, )); // set the current frame for time @@ -63,8 +60,11 @@ impl Drawable for Doodad { &sprite.texture, Some(sprite.rect), Some(dest_rect_0), - 0.0, // angle - Point::new(120 / (2 * self.scale) as i32, 270 / (2 * self.scale) as i32), // center + self.angle.to_degrees(), // angle + Point::new( + sprite.rect.width() as i32 / (2 * self.scale) as i32, + sprite.rect.width() as i32 / (2 * self.scale) as i32, + ), // center false, false, )?; diff --git a/src/main.rs b/src/main.rs index 6dd3e5f..574ee56 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,4 @@ +use rand::Rng; use sdl2::{event::Event, keyboard::Keycode, render::Canvas, video::Window}; use std::{time::Duration, time::Instant}; @@ -7,11 +8,10 @@ mod physics; mod ship; mod spriteatlas; -use crate::doodad::Doodad; -use crate::inputstatus::InputStatus; -use crate::physics::PhysVec; -use crate::ship::Ship; -use crate::spriteatlas::SpriteAtlas; +use crate::{ + doodad::Doodad, inputstatus::InputStatus, physics::PhysVec, physics::Position, ship::Ship, + spriteatlas::SpriteAtlas, +}; trait Drawable { /// Return the world position of this object @@ -51,38 +51,67 @@ struct Camera { impl Camera { fn new() -> Self { Camera { - pos: PhysVec::zero(), + pos: PhysVec { x: 0.0, y: 0.0 }, } } } -static FTL: f64 = 1.0 / 140.0; // frame time limit +static FTL: f64 = 1.0 / 200.0; // frame time limit struct System { - decor: Vec>, + bodies: Vec>, } impl System { fn new() -> Self { - let mut s = System { decor: Vec::new() }; + let mut s = System { bodies: Vec::new() }; - s.decor.push(Box::new(Doodad::new(PhysVec::zero()))); - s.decor - .push(Box::new(Doodad::new(PhysVec { x: 100.0, y: 23.0 }))); + let mut num = rand::thread_rng(); + for _ in 0..25 { + s.bodies.push(Box::new(Doodad { + sprite: "small.png".to_owned(), + pos: Position::new_cartesian( + num.gen_range(-500.0..500.0), + num.gen_range(-500.0..500.0), + ), + scale: 1, + angle: num.gen_range(-3.0..3.0), + })); + } + + s.bodies.push(Box::new(Doodad { + pos: Position::new_polar(PhysVec { x: 0.0, y: 0.0 }, 0.0, 0.0), + sprite: "a0.png".to_owned(), + scale: 1, + angle: 0.0, + })); + + s.bodies.push(Box::new(Doodad { + pos: Position::new_polar(PhysVec { x: 0.0, y: 0.0 }, 300.0, 31.0), + sprite: "earth.png".to_owned(), + scale: 1, + angle: 180.0, + })); return s; } + /// Calculate the state of this body after t seconds. + pub fn tick(&mut self, _t: f64) { + //let body = &mut self.bodies[1]; + //body.pos.angle += 0.1 * t; + //body.angle -= 0.1 * t; + } + fn draw( &self, canvas: &mut Canvas, sa: &SpriteAtlas, c: &Camera, ) -> Result<(), String> { - for d in &self.decor { - d.draw(canvas, sa, c)? + for body in &self.bodies { + body.draw(canvas, sa, c)?; } - return Ok(()); } } @@ -108,7 +137,7 @@ fn main() -> Result<(), String> { let sa = SpriteAtlas::new(&texture_creator)?; let mut event_pump = sdl_context.event_pump()?; - let system = System::new(); + let mut system = System::new(); let mut i = InputStatus::new(); let mut c = Camera::new(); @@ -157,6 +186,7 @@ fn main() -> Result<(), String> { //last_frame_time = frame_time; s.body.tick(frame_time); + system.tick(frame_time); if i.key_thrust { s.body.thrust(50.0 * frame_time); diff --git a/src/physics/body.rs b/src/physics/body.rs index 0dfad4f..842b465 100644 --- a/src/physics/body.rs +++ b/src/physics/body.rs @@ -12,7 +12,7 @@ impl PhysBody { pub fn new() -> Self { return PhysBody { pos: PhysVec { x: 200.0, y: 200.0 }, - vel: PhysVec::zero(), + vel: PhysVec { x: 0.0, y: 0.0 }, mass: 1.0, angle: 0.0, }; diff --git a/src/physics/mod.rs b/src/physics/mod.rs index 33dbd22..23fb5a1 100644 --- a/src/physics/mod.rs +++ b/src/physics/mod.rs @@ -1,5 +1,9 @@ mod body; +mod physpol; mod physvec; +mod position; pub use body::PhysBody; +pub use physpol::PhysPol; pub use physvec::PhysVec; +pub use position::Position; diff --git a/src/physics/physpol.rs b/src/physics/physpol.rs new file mode 100644 index 0000000..dab7399 --- /dev/null +++ b/src/physics/physpol.rs @@ -0,0 +1,17 @@ +use super::PhysVec; + +#[derive(Debug, Clone, Copy)] +pub struct PhysPol { + pub center: PhysVec, + pub radius: f64, + pub angle: f64, +} + +impl PhysPol { + pub fn to_cartesian(&self) -> PhysVec { + return PhysVec { + x: self.radius * self.angle.sin(), + y: self.radius * self.angle.cos(), + } + self.center; + } +} diff --git a/src/physics/physvec.rs b/src/physics/physvec.rs index 49d4fe5..3a9e91b 100644 --- a/src/physics/physvec.rs +++ b/src/physics/physvec.rs @@ -6,12 +6,6 @@ pub struct PhysVec { pub y: f64, } -impl PhysVec { - pub fn zero() -> Self { - return PhysVec { x: 0f64, y: 0f64 }; - } -} - impl From<(u32, u32)> for PhysVec { fn from(value: (u32, u32)) -> Self { PhysVec { diff --git a/src/physics/position.rs b/src/physics/position.rs new file mode 100644 index 0000000..358715b --- /dev/null +++ b/src/physics/position.rs @@ -0,0 +1,48 @@ +use super::PhysPol; +use super::PhysVec; + +#[derive(Debug, Clone, Copy)] +pub enum Position { + Cartesian(PhysVec), + Polar(PhysPol), +} + +impl Position { + pub fn new_cartesian(x: f64, y: f64) -> Self { + return Self::Cartesian(PhysVec { x, y }); + } + + pub fn new_polar(center: PhysVec, radius: f64, angle: f64) -> Self { + return Self::Polar(PhysPol { + center, + radius, + angle, + }); + } + + /* + pub fn to_polar(&self) -> Self { + match self { + Self::Cartesian(pv) => Self::Polar(pv.to_polar()), + Self::Polar(_) => self.clone(), + } + } + */ + + pub fn to_cartesian(&self) -> Self { + match self { + Self::Cartesian(_) => self.clone(), + Self::Polar(pp) => Self::Cartesian(pp.to_cartesian()), + } + } +} + +impl Into for Position { + fn into(self) -> PhysVec { + let c = self.to_cartesian(); + match c { + Self::Cartesian(pv) => pv, + _ => unreachable!(), + } + } +} diff --git a/src/spriteatlas.rs b/src/spriteatlas.rs index 4409435..7ac58a9 100644 --- a/src/spriteatlas.rs +++ b/src/spriteatlas.rs @@ -28,6 +28,8 @@ impl<'a> SpriteAtlas<'a> { b.load_one(texture_creator, "gypsum.png")?; b.load_one(texture_creator, "a0.png")?; + b.load_one(texture_creator, "small.png")?; + b.load_one(texture_creator, "earth.png")?; return Ok(b); }