Implement concept of fast forwarding

This commit is contained in:
Sofia 2026-07-26 20:10:41 +03:00
parent f67843cc59
commit 91f76b3836
2 changed files with 57 additions and 19 deletions

View File

@ -352,6 +352,7 @@ impl Game {
playback.bind_mut().replay = recorder.bind().replay.clone(); playback.bind_mut().replay = recorder.bind().replay.clone();
playback.bind_mut().current_map = self.current_map.clone(); playback.bind_mut().current_map = self.current_map.clone();
playback.bind_mut().current_time = recorder.bind().time_elapsed + time_delta; playback.bind_mut().current_time = recorder.bind().time_elapsed + time_delta;
playback.bind_mut().fast_forwarding = true;
self.current_replay_playback = Some(playback.clone()); self.current_replay_playback = Some(playback.clone());
self.base_mut().add_child(&playback); self.base_mut().add_child(&playback);
} }
@ -789,11 +790,19 @@ impl Game {
self.stop_playback(); self.stop_playback();
} }
if let Some(player) = self.find_player_mut(id) if let Some(player) = self.find_player(id)
&& let Some(character) = &mut player.character && let Some(mut character) = player.character.clone()
{ {
// This is a respawn, remove old character // This is a respawn, remove old character
character.queue_free(); character.queue_free();
if let Some(mut recorder) = self.replay_recorder.clone()
&& let Some(state) = player.get_state()
{
recorder
.bind_mut()
.record_event(ReplayEvent::Respawn(id, state));
}
} }
if let Some(mut map) = self.current_map.clone() { if let Some(mut map) = self.current_map.clone() {
@ -867,6 +876,14 @@ impl Game {
if let Some(character) = &mut player.character { if let Some(character) = &mut player.character {
// This is a respawn, delete old character // This is a respawn, delete old character
character.queue_free(); character.queue_free();
if let Some(mut recorder) = self.replay_recorder.clone()
&& let Some(state) = player.get_state()
{
recorder
.bind_mut()
.record_event(ReplayEvent::Respawn(id, state));
}
} }
let mut character = map.bind_mut().spawn_player( let mut character = map.bind_mut().spawn_player(

View File

@ -23,6 +23,8 @@ pub struct ReplayPlayback {
pub spectated_player_id: u16, pub spectated_player_id: u16,
pub fast_forwarding: bool,
base: Base<Node>, base: Base<Node>,
} }
@ -46,27 +48,43 @@ impl INode for ReplayPlayback {
while let Some(frame) = self.replay.frames.get(self.current_frame_idx) while let Some(frame) = self.replay.frames.get(self.current_frame_idx)
&& frame.time <= self.current_time && frame.time <= self.current_time
{ {
if let Some(map) = &mut self.current_map { if !self.fast_forwarding {
for (id, data) in &frame.player_data { if let Some(map) = &mut self.current_map {
if !self.player_characters.contains_key(id) { for (id, data) in &frame.player_data {
if let Some(player) = map.bind_mut().spawn_replay_player(*id, data.clone()) if !self.player_characters.contains_key(id) {
{ if let Some(player) =
self.player_characters.insert(*id, player); map.bind_mut().spawn_replay_player(*id, data.clone())
{
self.player_characters.insert(*id, player);
}
} }
} }
} }
}
for event in &frame.events { for event in &frame.events {
match event { match event {
ReplayEvent::Death(damage_source, player_id) => { ReplayEvent::Death(damage_source, player_id) => {
if let Some(character) = self.player_characters.get_mut(player_id) { if let Some(character) = self.player_characters.get_mut(player_id) {
character.bind_mut().kill(*damage_source); character.bind_mut().kill(*damage_source);
}
} }
} ReplayEvent::Shoot(player_id, to) => {
ReplayEvent::Shoot(player_id, to) => { if let Some(character) = self.player_characters.get_mut(player_id) {
if let Some(character) = self.player_characters.get_mut(player_id) { character.bind_mut().try_shoot(*to, false);
character.bind_mut().try_shoot(*to, false); }
}
ReplayEvent::Respawn(player_id, data) => {
if let Some(mut character) = self.player_characters.remove(player_id) {
character.queue_free();
}
if let Some(map) = &mut self.current_map {
if let Some(player) =
map.bind_mut().spawn_replay_player(*player_id, data.clone())
{
self.player_characters.insert(*player_id, player);
}
}
} }
} }
} }
@ -90,6 +108,8 @@ impl INode for ReplayPlayback {
self.current_frame_idx += 1; self.current_frame_idx += 1;
} }
self.fast_forwarding = false;
if self.current_frame_idx >= self.replay.frames.len() { if self.current_frame_idx >= self.replay.frames.len() {
for (id, mut character) in self.player_characters.clone() { for (id, mut character) in self.player_characters.clone() {
character.queue_free(); character.queue_free();
@ -203,6 +223,7 @@ pub struct ReplayFrame {
pub enum ReplayEvent { pub enum ReplayEvent {
Death(DamageSource, u16), Death(DamageSource, u16),
Shoot(u16, Vector3), Shoot(u16, Vector3),
Respawn(u16, ReplayPlayerState),
} }
#[derive(Debug)] #[derive(Debug)]
@ -220,7 +241,7 @@ pub struct ReplayPlayerState {
} }
impl Player { impl Player {
fn get_state(&self) -> Option<ReplayPlayerState> { pub fn get_state(&self) -> Option<ReplayPlayerState> {
if let Some(character) = &self.character { if let Some(character) = &self.character {
Some(ReplayPlayerState { Some(ReplayPlayerState {
transform: character.dyn_bind().get_transform(), transform: character.dyn_bind().get_transform(),