rewinds
authorhgn <hgodden00@gmail.com>
Thu, 20 Oct 2022 20:04:30 +0000 (21:04 +0100)
committerhgn <hgodden00@gmail.com>
Thu, 20 Oct 2022 20:04:30 +0000 (21:04 +0100)
menu.h
player.h
player_physics.h
world_routes.h

diff --git a/menu.h b/menu.h
index d83538e8f28134f54331662178d14b6229cf8bcc..0bfdd261047b640c2d46a6e5dde5dbfd1f89b1fa 100644 (file)
--- a/menu.h
+++ b/menu.h
@@ -61,7 +61,7 @@ static menu_buttons[] =
 /*a*/{"g_map",           5, NULL },
 /*b*/{"g_controls",      1, NULL },
 /*c*/{"text_quitty",     8, NULL },
-/*d*/{"text_yes",        8, menu_btn_fuckoff },
+/*d*/{"text_yes",        8, menu_btn_fuckoff,{-1,-1,-1,-1} },
 };
 
 static void menu_btn_map_a( int event ){}
index c9502a32493d780a6504663af4423c78a3a38d63..e4814d3400d1b2066e24f769638b352dafc62ae8 100644 (file)
--- a/player.h
+++ b/player.h
@@ -5,6 +5,8 @@
 #ifndef PLAYER_H
 #define PLAYER_H
 
+#define PLAYER_REWIND_FRAMES 60*4
+
 #include "audio.h"
 #include "common.h"
 #include "world.h"
@@ -74,7 +76,7 @@ static struct gplayer
    m4x3f visual_transform,
          inv_visual_transform;
 
-   int is_dead, death_tick_allowance;
+   int is_dead, death_tick_allowance, rewinding;
 
    v3f land_target;
    v3f land_target_log[22];
@@ -90,6 +92,17 @@ static struct gplayer
    v3f camera_pos, smooth_localcam;
    v2f angles;
 
+   struct rewind_frame
+   {
+      v3f pos;
+      v2f ang;
+   }
+   *rewind_buffer;
+   u32 rewind_incrementer,
+       rewind_length;
+
+   float rewind_time;
+
    /* animation */
    double jump_time;
    float fslide,
@@ -163,6 +176,7 @@ static void player_kill(void);
 static float *player_cam_pos(void);
 static void player_save_frame(void);
 static void player_restore_frame(void);
+static void player_save_rewind_frame(void);
 
 /* 
  * Submodules
@@ -230,17 +244,44 @@ static void player_init(void)                                            /* 1 */
                .function = reset_player
        });
 
+   player.rewind_length = 0;
+   player.rewind_buffer = vg_alloc( sizeof(struct rewind_frame) 
+                                       * PLAYER_REWIND_FRAMES );
+
    /* other systems */
    vg_loader_highwater( player_model_init, player_model_free, NULL );
 }
 
+static void player_save_rewind_frame(void)
+{
+   if( player.rewind_length < PLAYER_REWIND_FRAMES )
+   {
+      struct rewind_frame *fr = 
+         &player.rewind_buffer[ player.rewind_length ++ ];
+
+      v2_copy( player.angles, fr->ang );
+      v3_copy( player.camera_pos, fr->pos );
+
+      player.rewind_incrementer = 0;
+   }
+}
+
 /* Deal with input etc */
 static void player_update_pre(void)
 {
    struct player_phys *phys = &player.phys;
 
+   if( player.rewinding )
+   {
+      return;
+   }
+
    if( vg_get_button_down( "reset" ) )
    {
+      player.rewinding = 1;
+      player.rewind_time = (float)player.rewind_length - 0.0001f;
+      player_save_rewind_frame();
+
       player.is_dead = 0;
       player.death_tick_allowance = 30;
       player_restore_frame();
@@ -255,6 +296,9 @@ static void player_update_pre(void)
       player.mdl.shoes[1] = 1;
 
       world_routes_notify_reset();
+
+      /* apply 1 frame of movement */
+      player_do_motion();
    }
 
    if( vg_get_button_down( "switchmode" ) )
@@ -270,6 +314,9 @@ static void player_update_pre(void)
 
 static void player_update_fixed(void)                                    /* 2 */
 {
+   if( player.rewinding )
+      return;
+
    if( player.death_tick_allowance )
       player.death_tick_allowance --;
 
@@ -281,6 +328,13 @@ static void player_update_fixed(void)                                    /* 2 */
    }
    else
    {
+      player.rewind_incrementer ++;
+
+      if( player.rewind_incrementer > (u32)(0.25/VG_TIMESTEP_FIXED) )
+      {
+         player_save_rewind_frame();
+      }
+
       player_do_motion();
    }
 }
@@ -309,11 +363,79 @@ static void player_update_post(void)
    if( freecam )
       player_freecam();
 
+
    /* CAMERA POSITIONING: LAYER 0 */
    v2_copy( player.angles, camera_angles );
    v3_copy( player.camera_pos, camera_pos );
-   camera_update();
 
+   if( player.rewinding )
+   {
+      if( player.rewind_time <= 0.0f )
+      {
+         player.rewinding = 0;
+         player.rewind_length = 1;
+      }
+      else
+      {
+         assert( player.rewind_length > 0 );
+
+         v2f override_angles;
+         v3f override_pos;
+
+         float budget         = vg.time_delta,
+               overall_length = player.rewind_length*0.25f;
+
+         for( int i=0; (i<10)&&(player.rewind_time>0.0f)&&(budget>0.0f); i ++ )
+         {
+            /* Interpolate frames */
+            int i0 = floorf( player.rewind_time ),
+                i1 = VG_MIN( i0+1, player.rewind_length-1 );
+            
+            struct rewind_frame *fr =  &player.rewind_buffer[i0],
+                                *fr1 = &player.rewind_buffer[i1];
+
+            float dist = vg_maxf( v3_dist( fr->pos, fr1->pos ), 0.001f ),
+                  subl = vg_fractf( player.rewind_time ) + 0.001f,
+                  
+#if 0
+                  speed=sqrtf(player.rewind_time*player.rewind_time+11.0f)*3.0f,
+#else
+                  speed = (3.0f-(1.0f/(0.4f+0.4f*player.rewind_time)))*28.0f,
+#endif
+                  mod  = speed * (budget / dist),
+
+                  advl = vg_minf( mod, subl ),
+                  advt = (advl / mod) * budget;
+
+            player.rewind_time -= advl;
+            budget -= advt;
+         }
+
+         player.rewind_time = vg_maxf( 0.0f, player.rewind_time );
+         
+         int i0 = floorf( player.rewind_time ),
+             i1 = VG_MIN( i0+1, player.rewind_length-1 );
+         
+         struct rewind_frame *fr =  &player.rewind_buffer[i0],
+                             *fr1 = &player.rewind_buffer[i1];
+         
+         float sub = vg_fractf(player.rewind_time);
+
+         v3_lerp( fr->pos, fr1->pos, sub, override_pos );
+         override_angles[0] = vg_alerpf( fr->ang[0], fr1->ang[0], sub );
+         override_angles[1] = vg_lerpf ( fr->ang[1], fr1->ang[1], sub );
+
+         /* CAMERA POSITIONING: LAYER 1 */
+         float blend = (4.0f-player.rewind_time) * 0.25f,
+               c     = vg_clampf( blend, 0.0f, 1.0f );
+
+         camera_angles[0] = vg_alerpf(override_angles[0], player.angles[0], c);
+         camera_angles[1] = vg_lerpf (override_angles[1], player.angles[1], c);
+         v3_lerp( override_pos, player.camera_pos, c, camera_pos );
+      }
+   }
+
+   camera_update();
    player_audio();
 }
 
index bc1434c66f801f8e37881ee4ab68c91634a4079f..4a2add1b906fdd76f069c337aebdee1629157e48 100644 (file)
@@ -683,6 +683,8 @@ static void player_do_motion(void)
             player.angles[0] = atan2f( fwd_dir[2], fwd_dir[0] );
          }
          
+         player.rewind_length = 0;
+         player.rewind_incrementer = 10000;
          player_save_frame();
 
          audio_lock();
index d8d36d210efcccc7dfd8747c7148f039af0664e5..3de9278b5a13079cef0df65717b29058a00e9e93 100644 (file)
@@ -431,7 +431,7 @@ static void world_routes_ui_draw( u32 route, v4f colour, float offset )
    fade_colour[3] *= 1.0f-fade_amt;
 
    /* 1 minute timer */
-   float timer_delta = (vg.time - world.routes.last_interaction) * (1.0/60.0),
+   float timer_delta = (vg.time - world.routes.last_interaction) * (1.0/30.0),
          timer_scale = 1.0f - vg_minf( timer_delta, 1.0f );
 
    /*