diff --git a/src/bin/flappy/main.rs b/src/bin/flappy/main.rs index 7d521d9..7a69013 100644 --- a/src/bin/flappy/main.rs +++ b/src/bin/flappy/main.rs @@ -128,13 +128,57 @@ enum PlayerState { } // A tape tracking the bird's state every frame -#[derive(Component, Default)] +#[derive(Component)] struct Tape { - linear_velocities: Vec, - angular_velocities: Vec, - external_impulses: Vec, - positions: Vec, - rotations: Vec, + capacity: usize, + linear_velocities: VecDeque, + angular_velocities: VecDeque, + external_impulses: VecDeque, + positions: VecDeque, + rotations: VecDeque, +} + +impl Tape { + fn new_with_capacity(capacity: usize) -> Self { + Tape { + capacity, + linear_velocities: VecDeque::with_capacity(capacity), + angular_velocities: VecDeque::with_capacity(capacity), + external_impulses: VecDeque::with_capacity(capacity), + positions: VecDeque::with_capacity(capacity), + rotations: VecDeque::with_capacity(capacity), + } + } + + fn push(&mut self, lv: LinearVelocity, av: AngularVelocity, ei: ExternalImpulse, p: Position, r: Rotation) { + // If we are at capacity, make room + if self.linear_velocities.len() == self.capacity { + self.linear_velocities.pop_front().unwrap(); + self.angular_velocities.pop_front().unwrap(); + self.external_impulses.pop_front().unwrap(); + self.positions.pop_front().unwrap(); + self.rotations.pop_front().unwrap(); + } + + self.linear_velocities.push_back(lv); + self.angular_velocities.push_back(av); + self.external_impulses.push_back(ei); + self.positions.push_back(p); + self.rotations.push_back(r); + } + + fn pop(&mut self) -> Option<(LinearVelocity, AngularVelocity, ExternalImpulse, Position, Rotation)> { + if self.linear_velocities.is_empty() { + None + } else { + let lv = self.linear_velocities.pop_back().unwrap(); + let av = self.angular_velocities.pop_back().unwrap(); + let ei = self.external_impulses.pop_back().unwrap(); + let p = self.positions.pop_back().unwrap(); + let r = self.rotations.pop_back().unwrap(); + Some((lv, av, ei, p, r)) + } + } } fn init_bird(mut commands: Commands, bird_assets: Res) { @@ -150,7 +194,10 @@ fn init_bird(mut commands: Commands, bird_assets: Res) { MaxLinearSpeed(500.0), ); - let tape = Tape::default(); + // 60fps * 60 seconds + // let tape = Tape::new_with_capacity(60 * 60); + const REWIND_SECONDS: usize = 5; + let tape = Tape::new_with_capacity(60 * REWIND_SECONDS); commands.spawn(( name, @@ -749,11 +796,7 @@ fn record( birds .iter_mut() .for_each(|(lv, av, ei, p, r, mut tape)| { - tape.linear_velocities.push(*lv); - tape.angular_velocities.push(*av); - tape.external_impulses.push(*ei); - tape.positions.push(*p); - tape.rotations.push(*r); + tape.push(*lv, *av, *ei, *p, *r); }); } @@ -781,15 +824,15 @@ fn rewind( birds.iter_mut().for_each( |(mut lv, mut av, mut ei, mut p, mut r, mut tape)| { - if tape.positions.is_empty() { - next.set(PlayerState::Pause); - } else { - lv.0 = tape.linear_velocities.pop().unwrap().0; - av.0 = tape.angular_velocities.pop().unwrap().0; - ei.set_impulse(tape.external_impulses.pop().unwrap().impulse()); - p.0 = tape.positions.pop().unwrap().0; - *r = tape.rotations.pop().unwrap(); + if let Some((new_lv, new_av, new_ei, new_p, new_r)) = tape.pop() { + lv.0 = new_lv.0; + av.0 = new_av.0; + ei.set_impulse(new_ei.impulse()); + p.0 = new_p.0; + *r = new_r; frames.0 += 1; + } else { + next.set(PlayerState::Pause); } }, );