Preserving more data, but rewind backfilling still not working...

main
Elijah Voigt 3 months ago
parent 8002c8bae9
commit c20bd94b79

@ -80,7 +80,9 @@ fn main() {
sync_resource_to_ui::<RewindFrames>.run_if(resource_changed::<RewindFrames>), sync_resource_to_ui::<RewindFrames>.run_if(resource_changed::<RewindFrames>),
), ),
scoring.run_if(on_event::<CollisionEnded>), scoring.run_if(on_event::<CollisionEnded>),
manage_batches.run_if(on_event::<CollisionStarted>).run_if(in_state(PlayerState::Alive).or(in_state(PlayerState::Rewind))), manage_batches
.run_if(on_event::<CollisionStarted>)
.run_if(in_state(PlayerState::Alive).or(in_state(PlayerState::Rewind))),
update_batch_position.run_if(any_component_changed::<Batch>), update_batch_position.run_if(any_component_changed::<Batch>),
update_tooltip.run_if(in_state(DebuggingState::On)), update_tooltip.run_if(in_state(DebuggingState::On)),
), ),
@ -114,10 +116,15 @@ enum PlayerState {
// A tape tracking the bird's state every frame // A tape tracking the bird's state every frame
#[derive(Component, Default)] #[derive(Component, Default)]
struct Tape { struct Tape {
translations: Vec<Vec3>, accumulated_translations: Vec<AccumulatedTranslation>,
rotations: Vec<Quat>,
linear_velocities: Vec<LinearVelocity>, linear_velocities: Vec<LinearVelocity>,
angular_velocities: Vec<AngularVelocity>, angular_velocities: Vec<AngularVelocity>,
external_angular_impulses: Vec<ExternalAngularImpulse>,
external_forces: Vec<ExternalForce>,
external_impulses: Vec<ExternalImpulse>,
external_torques: Vec<ExternalTorque>,
positions: Vec<Position>,
rotations: Vec<Rotation>,
} }
fn init_bird( fn init_bird(
@ -176,9 +183,7 @@ struct Hitbox;
#[derive(Component, Clone)] #[derive(Component, Clone)]
struct Batch(usize); struct Batch(usize);
fn init_first_batches( fn init_first_batches(mut commands: Commands) {
mut commands: Commands
) {
commands.spawn(Batch(0)); commands.spawn(Batch(0));
commands.spawn(Batch(1)); commands.spawn(Batch(1));
commands.spawn(Batch(2)); commands.spawn(Batch(2));
@ -205,7 +210,10 @@ fn populate_batch(
let Batch(batch_id) = batches.get(trigger.target()).unwrap(); let Batch(batch_id) = batches.get(trigger.target()).unwrap();
commands commands
.entity(trigger.target()) .entity(trigger.target())
.insert((Transform::from_xyz(500.0 * (*batch_id) as f32, 0.0, 0.0), Visibility::Inherited)) .insert((
Transform::from_xyz(500.0 * (*batch_id) as f32, 0.0, 0.0),
Visibility::Inherited,
))
.with_children(|parent| { .with_children(|parent| {
parent.spawn(Ground(-2)); parent.spawn(Ground(-2));
parent.spawn(Ground(-1)); parent.spawn(Ground(-1));
@ -224,7 +232,7 @@ fn populate_batch(
fn update_batch_position( fn update_batch_position(
mut root_changes: Query<(&mut Transform, &Batch), (Changed<Batch>, Without<ChildOf>)>, mut root_changes: Query<(&mut Transform, &Batch), (Changed<Batch>, Without<ChildOf>)>,
) { ) {
root_changes.iter_mut().for_each(|(mut t, Batch(idx))|{ root_changes.iter_mut().for_each(|(mut t, Batch(idx))| {
info!("Updating batch {:?}", idx); info!("Updating batch {:?}", idx);
t.translation.x = 500.0 * (*idx) as f32; t.translation.x = 500.0 * (*idx) as f32;
}); });
@ -245,8 +253,9 @@ fn populate_ground(
ground_assets.material.clone(), ground_assets.material.clone(),
ground_assets.mesh.clone(), ground_assets.mesh.clone(),
Name::new("ground"), Name::new("ground"),
RigidBody::Static, Collider::rectangle(1.0, 1.0), RigidBody::Static,
Transform::from_xyz(100.0 * (*idx) as f32, -300.0, -1.0).with_scale(Vec3::splat(100.0)) Collider::rectangle(1.0, 1.0),
Transform::from_xyz(100.0 * (*idx) as f32, -300.0, -1.0).with_scale(Vec3::splat(100.0)),
)); ));
} }
@ -266,17 +275,15 @@ fn populate_pipe(
pipe_t, pipe_t,
pipe_assets.material.clone(), pipe_assets.material.clone(),
pipe_assets.mesh.clone(), pipe_assets.mesh.clone(),
RigidBody::Static, Collider::rectangle(1.0, 1.0), RigidBody::Static,
Collider::rectangle(1.0, 1.0),
Name::new("pipe"), Name::new("pipe"),
)); ));
} }
/// The hitbox should cover the entire height of the screen so if the player /// The hitbox should cover the entire height of the screen so if the player
/// passes between the pipes it registers a point /// passes between the pipes it registers a point
fn populate_hitbox( fn populate_hitbox(trigger: Trigger<OnAdd, Hitbox>, mut commands: Commands) {
trigger: Trigger<OnAdd, Hitbox>,
mut commands: Commands,
) {
commands.entity(trigger.target()).insert(( commands.entity(trigger.target()).insert((
RigidBody::Static, RigidBody::Static,
Collider::rectangle(1.0, 10.0), Collider::rectangle(1.0, 10.0),
@ -502,7 +509,21 @@ fn toggle_rewind(keycode: Res<ButtonInput<KeyCode>>, mut next: ResMut<NextState<
fn record( fn record(
#[cfg(debug_assertions)] state: Res<State<PlayerState>>, #[cfg(debug_assertions)] state: Res<State<PlayerState>>,
mut birds: Query<(&Transform, &LinearVelocity, &AngularVelocity, &mut Tape), With<Bird>>, mut birds: Query<
(
&AccumulatedTranslation,
&LinearVelocity,
&AngularVelocity,
&ExternalAngularImpulse,
&ExternalForce,
&ExternalImpulse,
&ExternalTorque,
&Position,
&Rotation,
&mut Tape,
),
With<Bird>,
>,
) { ) {
debug_assert!( debug_assert!(
matches!(state.get(), PlayerState::Alive), matches!(state.get(), PlayerState::Alive),
@ -511,11 +532,16 @@ fn record(
birds birds
.iter_mut() .iter_mut()
.for_each(|(transform, linear_velocity, angular_velocity, mut tape)| { .for_each(|(at, lv, av, eai, ef, ei, et, p, r, mut tape)| {
tape.translations.push(transform.translation); tape.accumulated_translations.push(*at);
tape.rotations.push(transform.rotation); tape.linear_velocities.push(*lv);
tape.linear_velocities.push(*linear_velocity); tape.angular_velocities.push(*av);
tape.angular_velocities.push(*angular_velocity); tape.external_angular_impulses.push(*eai);
tape.external_forces.push(*ef);
tape.external_impulses.push(*ei);
tape.external_torques.push(*et);
tape.positions.push(*p);
tape.rotations.push(*r);
}); });
} }
@ -523,9 +549,15 @@ fn rewind(
#[cfg(debug_assertions)] state: Res<State<PlayerState>>, #[cfg(debug_assertions)] state: Res<State<PlayerState>>,
mut birds: Query< mut birds: Query<
( (
&mut Transform, &mut AccumulatedTranslation,
&mut AngularVelocity,
&mut LinearVelocity, &mut LinearVelocity,
&mut AngularVelocity,
&mut ExternalAngularImpulse,
&mut ExternalForce,
&mut ExternalImpulse,
&mut ExternalTorque,
&mut Position,
&mut Rotation,
&mut Tape, &mut Tape,
), ),
With<Bird>, With<Bird>,
@ -538,22 +570,24 @@ fn rewind(
); );
birds.iter_mut().for_each( birds.iter_mut().for_each(
|(mut transform, mut angular_velocity, mut linear_velocity, mut tape)| { |(mut at, mut lv, mut av, mut eai, mut ef, mut ei, mut et, mut p, mut r, mut tape)| {
match (tape.translations.pop(), tape.rotations.pop()) { if !tape.positions.is_empty() {
(Some(t), Some(r)) => { at.0 = tape.accumulated_translations.pop().unwrap().0;
transform.translation = t; lv.0 = tape.linear_velocities.pop().unwrap().0;
transform.rotation = r; av.0 = tape.angular_velocities.pop().unwrap().0;
frames.0 += 1; eai.set_impulse(tape.external_angular_impulses.pop().unwrap().impulse());
} ef.set_force(tape.external_forces.pop().unwrap().force());
(None, None) => (), ei.set_impulse(tape.external_impulses.pop().unwrap().impulse());
_ => panic!("Translations and rotations are out of sync!"), et.set_torque(tape.external_torques.pop().unwrap().torque());
} p.0 = tape.positions.pop().unwrap().0;
// TODO: Only need to set {angular|linear}_velocity at end of Rewind *r = {
if let Some(av) = tape.angular_velocities.pop() { let curr = tape.rotations.pop().unwrap();
*angular_velocity = av; Rotation {
} cos: curr.cos,
if let Some(lv) = tape.linear_velocities.pop() { sin: curr.sin,
*linear_velocity = lv; }
};
frames.0 += 1;
} }
}, },
); );
@ -593,7 +627,9 @@ fn pause_bird(
debug_assert!(!matches!(state.get(), PlayerState::Alive)); debug_assert!(!matches!(state.get(), PlayerState::Alive));
// Increment death count // Increment death count
if state.get() == &PlayerState::Stasis { deaths.0 += 1 } if state.get() == &PlayerState::Stasis {
deaths.0 += 1
}
debug!("Setting bird to Static"); debug!("Setting bird to Static");
**bird = RigidBody::Static; **bird = RigidBody::Static;
@ -673,32 +709,46 @@ fn manage_batches(
batches: Query<(Entity, &Batch)>, batches: Query<(Entity, &Batch)>,
mut commands: Commands, mut commands: Commands,
) { ) {
debug_assert!(matches!(state.get(), PlayerState::Alive) || matches!(state.get(), PlayerState::Rewind)); debug_assert!(
matches!(state.get(), PlayerState::Alive) || matches!(state.get(), PlayerState::Rewind)
);
events events
.read() .read()
// This is written in a wonky way to avoid borrow checker rules // This is written in a wonky way to avoid borrow checker rules
// Instaed of updating the Batch in place we use Commands to get it and upsert a new batch // Instaed of updating the Batch in place we use Commands to get it and upsert a new batch
.filter_map(|CollisionStarted(a, b)| { .filter_map(|CollisionStarted(a, b)| {
if bird.contains(*a) && let Ok((e, Batch(idx))) = batches.get(*b) && *idx > 2 { if bird.contains(*a)
&& let Ok((e, Batch(idx))) = batches.get(*b)
&& *idx > 2
{
Some((e, idx)) Some((e, idx))
} else { None } } else {
}).for_each(|(_, idx)| { None
}
})
.for_each(|(_, idx)| {
let (old_batch_idx, new_batch_idx) = match state.get() { let (old_batch_idx, new_batch_idx) = match state.get() {
PlayerState::Alive => (idx - 2, idx + 2), PlayerState::Alive => (idx - 2, idx + 2),
PlayerState::Rewind => (idx + 2, idx - 2), PlayerState::Rewind => (idx + 2, idx - 2),
_ => panic!("Should not happen!"), _ => panic!("Should not happen!"),
}; };
// Find all entities with the old batch and adjust them // Find all entities with the old batch and adjust them
batches.iter().filter_map(|(e, batch)| { batches
(batch.0 == old_batch_idx).then_some(e) .iter()
}).for_each(|e| { .filter_map(|(e, batch)| (batch.0 == old_batch_idx).then_some(e))
commands.entity(e).insert(Batch(new_batch_idx)); .for_each(|e| {
}) commands.entity(e).insert(Batch(new_batch_idx));
})
}); });
} }
fn update_tooltip( fn update_tooltip(
mut query: Query<(&mut ToolTip, Option<&LinearVelocity>, Option<&Batch>, Entity)>, mut query: Query<(
&mut ToolTip,
Option<&LinearVelocity>,
Option<&Batch>,
Entity,
)>,
) { ) {
query.iter_mut().for_each(|(mut tt, lv, b, _e)| { query.iter_mut().for_each(|(mut tt, lv, b, _e)| {
// Add Linear Velocity if present on entity // Add Linear Velocity if present on entity

@ -18,9 +18,7 @@ impl Plugin for DebuggingPlugin {
.add_systems( .add_systems(
Update, Update,
( (
( (toggle_state_visibility::<DebuggingState>,)
toggle_state_visibility::<DebuggingState>,
)
.run_if(state_changed::<DebuggingState>), .run_if(state_changed::<DebuggingState>),
toggle_debug_state.run_if(input_just_pressed(KeyCode::F12)), toggle_debug_state.run_if(input_just_pressed(KeyCode::F12)),
(toggle_light_gizmo, toggle_aabb_gizmo).run_if(state_changed::<DebuggingState>), (toggle_light_gizmo, toggle_aabb_gizmo).run_if(state_changed::<DebuggingState>),
@ -242,11 +240,7 @@ fn tooltip_follow(
} }
/// Lok tooltip to entity by inserting the Tooltip component on it /// Lok tooltip to entity by inserting the Tooltip component on it
fn lock_tooltip( fn lock_tooltip(q: Query<Option<&ToolTip>>, hover_map: Res<HoverMap>, mut commands: Commands) {
q: Query<Option<&ToolTip>>,
hover_map: Res<HoverMap>,
mut commands: Commands,
) {
hover_map.0.iter().for_each(|(_, hit_data_map)| { hover_map.0.iter().for_each(|(_, hit_data_map)| {
if let Some((e, _)) = hit_data_map.iter().min_by(|(_, a), (_, b)| { if let Some((e, _)) = hit_data_map.iter().min_by(|(_, a), (_, b)| {
if a.depth > b.depth { if a.depth > b.depth {
@ -266,17 +260,14 @@ fn lock_tooltip(
info!("Removing tooltip from {:?}", e); info!("Removing tooltip from {:?}", e);
commands.entity(*e).remove::<ToolTip>(); commands.entity(*e).remove::<ToolTip>();
} }
_ => () _ => (),
} }
} }
}); });
} }
/// when a tooltip is added to an entity, insert the text component /// when a tooltip is added to an entity, insert the text component
fn add_tooltip_text( fn add_tooltip_text(trigger: Trigger<OnAdd, ToolTip>, mut commands: Commands) {
trigger: Trigger<OnAdd, ToolTip>,
mut commands: Commands,
) {
info!("Adding text2d to {:?}", trigger.target()); info!("Adding text2d to {:?}", trigger.target());
commands.entity(trigger.target()).with_children(|parent| { commands.entity(trigger.target()).with_children(|parent| {
parent.spawn(( parent.spawn((
@ -296,15 +287,25 @@ fn populate_tooltip_info(
if let Ok((mut tt, e, t, n)) = tooltips.get_mut(trigger.target()) { if let Ok((mut tt, e, t, n)) = tooltips.get_mut(trigger.target()) {
tt.insert("ID", format!("{e}")); tt.insert("ID", format!("{e}"));
tt.insert("Name", n.into()); tt.insert("Name", n.into());
tt.insert("Pos", format!("{:.2?} {:.2?} {:.2?}", t.translation.x, t.translation.y, t.translation.z)); tt.insert(
"Pos",
format!(
"{:.2?} {:.2?} {:.2?}",
t.translation.x, t.translation.y, t.translation.z
),
);
} }
} }
fn tooltip_update_transform( fn tooltip_update_transform(mut events: Query<(&mut ToolTip, &Transform), Changed<Transform>>) {
mut events: Query<(&mut ToolTip, &Transform), Changed<Transform>>,
) {
events.iter_mut().for_each(|(mut tt, t)| { events.iter_mut().for_each(|(mut tt, t)| {
tt.insert("Pos", format!("{:.2?} {:.2?} {:.2?}", t.translation.x, t.translation.y, t.translation.z)); tt.insert(
"Pos",
format!(
"{:.2?} {:.2?} {:.2?}",
t.translation.x, t.translation.y, t.translation.z
),
);
}); });
} }
@ -333,7 +334,7 @@ fn tooltip_draw(
// Find the tooltip text child // Find the tooltip text child
children.iter().for_each(|child| { children.iter().for_each(|child| {
if let Ok(mut text) = text_2d.get_mut(child) { if let Ok(mut text) = text_2d.get_mut(child) {
text.0 = format!("{}", tt); text.0 = format!("{tt}");
} }
}); });
}) })

Loading…
Cancel
Save