diff --git a/src/main.rs b/src/main.rs index 3f17b45..aa6fc3e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,22 +1,32 @@ use std::time::{Duration, Instant}; + +// loop constants const UPDATE_INTERVAL: u32 = 40; const DEBUG_LOOP: bool = false; +// physics constants +const GRAVITY: f32 = -9.8; + // a struct made for physics objects #[derive(Copy, Clone)] struct PhysicsObject { location: [f32; 3], - velocity: [f32; 3] + velocity: [f32; 3], + gravity_enabled: bool } fn main() { + // global time + let mut time = Duration::new(0,0); + // track the delta time (the duration of the previous loop in milliseconds) let mut delta_time = Duration::new(0, 0); // create a test physics object let mut test_object = PhysicsObject { - location: [0.0, 0.0, 0.0], - velocity: [0.0, 0.0, 0.0] + location: [0.0, 0.0, 100.0], + velocity: [0.0, 0.0, 0.0], + gravity_enabled: true }; loop { @@ -25,51 +35,62 @@ fn main() { // update if delta_time.as_millis() as u32 >= UPDATE_INTERVAL { - if DEBUG_LOOP { - println!("Updating"); - } update(delta_time, &mut test_object); + // DEBUG + println!("Time: {}ms | test_object | Location: {:?} | Velocity: {:?}", time.as_millis(), test_object.location, test_object.velocity); + + // keep track of time + time += delta_time; + // reset the delta time - delta_time = Instant::now().duration_since(start_time); + delta_time = Duration::new(0,0); } - - // support interpolation via fractional "relative time" - let relative_time: f32 = delta_time.as_millis() as f32 / UPDATE_INTERVAL as f32; - - if DEBUG_LOOP { - println!("Displaying | Delta Time: {}ms | Relative Time: {}", delta_time.as_millis(), relative_time); - } - display(relative_time, &test_object); - + // update the time delta_time += Instant::now().duration_since(start_time); + + display(delta_time, &test_object); } } // update function // TODO - I think I'm resetting delta time in the wrong place or just using it incorrectly; frameskips aren't happening at all fn update(delta_time: Duration, object: &mut PhysicsObject) { - // calculate the exact timestep (fractional time in seconds) from delta time - let timestep: f32 = delta_time.as_millis() as f32 / 1000.0; - println!("Timestep: {}", timestep); - - // gravity - let acceleration: [f32; 3] = [0.0, 0.0, -9.8]; - - // update velocity based on acceleration (specifically gravity) - for i in 0..3 { - object.velocity[i] += acceleration[i] * timestep; + if DEBUG_LOOP { + println!("Updating"); } + // calculate the exact timestep (fractional time in seconds) from delta time + let timestep: f32 = delta_time.as_millis() as f32 / 1000.0; + // update location based on velocity for i in 0..3 { - object.location[i] += object.velocity[i]; + object.location[i] += timestep * object.velocity[i]; + } + + // gravity + if object.gravity_enabled { + object.velocity[2] += GRAVITY * timestep; + } + + // prevent the object from going below the ground plane, and kill downward velocity upon "hitting" the ground plane + if object.location[2] <= 0.0 { + object.location[2] = 0.0; + object.velocity[2] = object.velocity[2].max(0.0); } } // render function -fn display(interpolation: f32, object: &PhysicsObject) { +fn display(delta_time: Duration, object: &PhysicsObject) { + // calculate interpolation via delta time + let interpolation: f32 = delta_time.as_millis() as f32 / UPDATE_INTERVAL as f32; + + // DEBUG + if DEBUG_LOOP { + println!("Displaying | Delta Time: {}ms | Relative Time: {}", delta_time.as_millis(), interpolation); + } + // create a "render object", which we can apply interpolation to let mut render_object = *object; @@ -78,7 +99,8 @@ fn display(interpolation: f32, object: &PhysicsObject) { render_object.location[i] += render_object.velocity[i] * interpolation; } - println!("Object location: {:?}", render_object.location); + // DEBUG + // println!("test_object | Location: {:?} | Velocity: {:?}", render_object.location, render_object.velocity); } // 1D linear interpolation