From 5af2a88b715579036a6c49397588ffe2e04400e1 Mon Sep 17 00:00:00 2001 From: hgn Date: Thu, 20 Oct 2022 21:04:30 +0100 Subject: [PATCH] rewinds --- menu.h | 2 +- player.h | 126 ++++++++++++++++++++++++++++++++++++++++++++++- player_physics.h | 2 + world_routes.h | 2 +- 4 files changed, 128 insertions(+), 4 deletions(-) diff --git a/menu.h b/menu.h index d83538e..0bfdd26 100644 --- 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 ){} diff --git a/player.h b/player.h index c9502a3..e4814d3 100644 --- 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(); } diff --git a/player_physics.h b/player_physics.h index bc1434c..4a2add1 100644 --- a/player_physics.h +++ b/player_physics.h @@ -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(); diff --git a/world_routes.h b/world_routes.h index d8d36d2..3de9278 100644 --- a/world_routes.h +++ b/world_routes.h @@ -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 ); /* -- 2.25.1