before the storm
[carveJwlIkooP6JGAAIwe30JlM.git] / player.h
index 8619308a0cffe686a929574701353ca2d3be4c23..6fb74dcf6427c5c6ce6a709399f77edb9a9dadec 100644 (file)
--- a/player.h
+++ b/player.h
@@ -1,3 +1,7 @@
+/*
+ * Copyright 2021-2022 (C) Mount0 Software, Harry Godden - All Rights Reserved
+ */
+
 #ifndef PLAYER_H
 #define PLAYER_H
 
@@ -46,6 +50,7 @@ static struct gplayer
 
    /* TODO: eugh */
    m3x3f gate_vr_frame, gate_vr_pstep_frame;
+   int on_board_frame, in_air_frame;
 
    v3f a, v_last, m, bob, vl;
 
@@ -92,6 +97,9 @@ static struct gplayer
          fsetup,
          walk_timer,
          fonboard;
+
+v3f last_step_pos;
+   int step_phase;
 }
 player = 
 {
@@ -105,6 +113,11 @@ player =
  * Player API
  */
 
+static float *player_get_pos(void)
+{
+   return player.rb.co;
+}
+
 
 /*
  * Free camera movement
@@ -519,6 +532,8 @@ static void player_walk_physics(void)
          }
       }
    }
+
+   player.in_air = len==0?1:0;
    
    v3_zero( player.rb.w );
    q_axis_angle( player.rb.q, (v3f){0.0f,1.0f,0.0f}, -player.angles[0] );
@@ -544,8 +559,8 @@ static void player_walk_physics(void)
       v3_muladds( player.rb.v, forward_dir, diff, player.rb.v );
 
       /* TODO move */
-      float walk_norm = (float)player.mdl.anim_walk->length / 30.0f,
-            run_norm  = (float)player.mdl.anim_run->length  / 30.0f;
+      float walk_norm = 30.0f/(float)player.mdl.anim_walk->length,
+            run_norm  = 30.0f/(float)player.mdl.anim_run->length ;
 
       player.walk_timer += ktimestep * vg_lerpf( walk_norm,run_norm,move_norm );
    }
@@ -719,6 +734,13 @@ static void player_physics(void)
          player.jump = 0.0f;
 
          player.jump_time = vg_time;
+
+         audio_lock();
+         audio_player_set_flags( &audio_player_extra, AUDIO_FLAG_SPACIAL_3D );
+         audio_player_set_position( &audio_player_extra, player.rb.co );
+         audio_player_set_vol( &audio_player_extra, 20.0f );
+         audio_player_playclip( &audio_player_extra, &audio_jumps[rand()%4] );
+         audio_unlock();
       }
    }
    else
@@ -799,9 +821,25 @@ static void player_do_motion(void)
          
          world_routes_activate_gate( i );
          player.rb_gate_frame = player.rb;
+         player.in_air_frame = player.in_air;
+         player.on_board_frame = player.on_board;
 
+         if( !player.on_board )
+         {
+            v3f fwd_dir = {cosf(player.angles[0]),
+                           0.0f,
+                           sinf(player.angles[0])};
+            m3x3_mulv( gate->transport, fwd_dir, fwd_dir );
+
+            player.angles[0] = atan2f( fwd_dir[2], fwd_dir[0] );
+         }
+         
          m3x3_copy( player.vr, player.gate_vr_frame );
          m3x3_copy( player.vr_pstep, player.gate_vr_pstep_frame );
+
+         audio_lock();
+         audio_play_oneshot( &audio_gate_lap, 1.0f );
+         audio_unlock();
          break;
       }
    }
@@ -818,13 +856,13 @@ static void player_animate_offboard(void)
    mdl_keyframe apose[32], bpose[32];
    struct skeleton *sk = &player.mdl.sk;
 
-   float walk_norm = 30.0f/(float)player.mdl.anim_walk->length,
-         run_norm  = 30.0f/(float)player.mdl.anim_run->length,
+   float walk_norm = (float)player.mdl.anim_walk->length/30.0f,
+         run_norm  = (float)player.mdl.anim_run->length/30.0f,
          t = player.walk_timer,
          l = vg_get_axis("grabr") * 0.5f + 0.5f;
 
    skeleton_sample_anim( sk, player.mdl.anim_walk, t*walk_norm, apose );
-   skeleton_sample_anim( sk, player.mdl.anim_run,  t*run_norm,  bpose );
+   skeleton_sample_anim( sk, player.mdl.anim_run,  t*run_norm, bpose );
 
    skeleton_lerp_pose( sk, apose, bpose, l, apose );
 
@@ -898,7 +936,6 @@ static void player_animate(void)
 
    offset[0] = vg_clampf( offset[0], -0.8f, 0.8f );
    offset[1] = vg_clampf( offset[1], -0.5f, 0.0f );
-   offset[1] = 0.0f;
 
    /* 
     * Animation blending
@@ -998,7 +1035,7 @@ static void player_animate(void)
 
    skeleton_lerp_pose( sk, ground_pose, air_pose, player.ffly, apose );
 
-   float add_grab_mod = player.ffly * player.grab;
+   float add_grab_mod = 1.0f - player.ffly*player.grab;
 
    /* additive effects */
    apose[player.mdl.id_hip-1].co[0] += offset[0]*add_grab_mod;
@@ -1027,9 +1064,13 @@ static void player_animate(void)
 static void player_camera_update(void)
 {
    /* Update camera matrices */
-   m4x3_identity( player.camera );
-   m4x3_rotate_y( player.camera, -player.angles[0] );
-   m4x3_rotate_x( player.camera, -player.angles[1] );
+   v4f qyaw, qpitch, qcam;
+   q_axis_angle( qyaw, (v3f){ 0.0f, 1.0f, 0.0f }, -player.angles[0] ); 
+   q_axis_angle( qpitch, (v3f){ 1.0f, 0.0f, 0.0f }, -player.angles[1] ); 
+
+   q_mul( qyaw, qpitch, qcam );
+   q_m3x3( qcam, player.camera );
+
    v3_copy( player.camera_pos, player.camera[3] );
    m4x3_invert_affine( player.camera, player.camera_inverse );
 }
@@ -1137,53 +1178,151 @@ static void player_animate_camera(void)
  */
 static void player_audio(void)
 {
-   audio_sample_occlusion( player.camera[3] );
+   static int _ding = 0;
+   
+   int last = _ding;
+   _ding = glfwGetKey(vg_window, GLFW_KEY_C);
 
-   float speed = vg_minf(v3_length( player.rb.v )*0.1f,1.0f),
-         attn = v3_dist( player.rb.co, player.camera[3] )+1.0f;
-   attn = (1.0f/(attn*attn)) * speed;
+   int trigger_ding = 0;
+   if( _ding && !last )
+      trigger_ding = 1;
+
+   static int _air = 0;
+
+   int l2 = _air;
+   _air = player.in_air;
+
+   static double last_revert = -2000.0;
+
+
+
+
+   audio_lock();
+   
+   double revert_delta = vg_time - last_revert;
+   if( player.on_board && (!_air && l2) && (fabsf(player.slip) > 0.5f) && 
+         (revert_delta > 0.7) )
+   {
+      audio_player_set_position( &audio_player_extra, player.rb.co );
+      audio_player_set_flags( &audio_player_extra, AUDIO_FLAG_SPACIAL_3D );
+      audio_player_set_vol( &audio_player_extra, 2.0f );
+      audio_player_playclip( &audio_player_extra, &audio_lands[rand()%5] );
+
+      last_revert = vg_time;
+   }
 
    static float air = 0.0f;
    air = vg_lerpf(air, player.in_air? 1.0f: 0.0f, 5.0f*ktimestep);
-   
+
+   /* Spacial info */
    v3f ears = { 1.0f,0.0f,0.0f };
    v3f delta;
 
+   float *cam = player.camera[3],
+         *pos = player.rb.co;
+   
+   if( trigger_ding )
+      audio_player_playclip( &audio_player_extra, &audio_ding );
+
+   audio_player_set_position( &audio_player0, player.rb.co );
+   audio_player_set_position( &audio_player1, player.rb.co );
+   audio_player_set_position( &audio_player2, player.rb.co );
+   audio_player_set_position( &audio_player_gate, world.render_gate_pos );
+
    v3_sub( player.rb.co, player.camera[3], delta );
    v3_normalize( delta );
    m3x3_mulv( player.camera, ears, ears );
-   
-   float pan = v3_dot( ears, delta );
-   audio_player0.pan = pan;
-   audio_player1.pan = pan;
-   audio_player2.pan = pan;
 
-   audio_player3.pan = 0.0f;
+   /* TODO, Make function */
+   v3_copy( ears, vg_audio.listener_ears );
+   v3_copy( player.camera[3], vg_audio.listener_pos );
 
-   if( freecam )
+   /* Tunnel / occlusion */
+   audio_sample_occlusion( player.camera[3] );
+
+   int sprite_avail = -1;
+   for( int i=0; i<vg_list_size(ambient_sprites); i++ )
    {
-      audio_player0.vol = 0.0f;
-      audio_player1.vol = 0.0f;
-      audio_player2.vol = 0.0f;
+      if( !audio_player_is_playing( &ambient_sprites[i] ) )
+      {
+         sprite_avail = i;
+         break;
+      }
    }
-   else
+   
+   if( sprite_avail != -1 )
    {
-      if( player.is_dead )
+      v3f waterpos;
+      enum audio_sprite_type sprite_type = 
+         audio_sample_sprite_random( player.rb.co, waterpos );
+
+      if( sprite_type != k_audio_sprite_type_none )
       {
-         audio_player0.vol = 0.0f;
-         audio_player1.vol = 0.0f;
-         audio_player2.vol = 0.0f;
+         audio_player *avail = &ambient_sprites[ sprite_avail ];
+
+         audio_player_set_vol( avail, 20.0f );
+         audio_player_set_flags( avail, AUDIO_FLAG_SPACIAL_3D );
+         audio_player_set_position( avail, waterpos );
+
+         if( sprite_type == k_audio_sprite_type_grass )
+         {
+            audio_player_playclip( avail, &audio_grass[rand()%4] );
+         }
+         else if( sprite_type == k_audio_sprite_type_water )
+         {
+            audio_player_playclip( avail, &audio_water[rand()%6] );
+         }
       }
+   }
+   
+   if( freecam || player.is_dead || !player.on_board )
+   {
+      audio_player_set_vol( &audio_player0, 0.0f );
+      audio_player_set_vol( &audio_player1, 0.0f );
+      audio_player_set_vol( &audio_player2, 0.0f );
+
+      int walk_phase = 0;
+      if( vg_fractf(player.walk_timer) > 0.5f )
+         walk_phase = 1;
       else
+         walk_phase = 0;
+
+      if( (player.step_phase != walk_phase) && !player.in_air )
       {
-         float slide = vg_clampf( fabsf(player.slip), 0.0f, 1.0f );
-         audio_player0.vol = (1.0f-air)*attn*(1.0f-slide);
-         audio_player1.vol =       air *attn;
-         audio_player2.vol = (1.0f-air)*attn*slide;
+         v3_copy( player.rb.co, player.last_step_pos );
+
+         audio_player_set_flags( &audio_player_extra, AUDIO_FLAG_SPACIAL_3D );
+         audio_player_set_position( &audio_player_extra, player.rb.co );
+         audio_player_set_vol( &audio_player_extra, 6.0f );
+         audio_player_playclip( &audio_player_extra, 
+                                          &audio_footsteps[rand()%4] );
       }
+
+      player.step_phase = walk_phase;
    }
+   else
+   {
+      /* Composite */
+      float speed = vg_minf(v3_length( player.rb.v )*0.1f,1.0f),
+            attn  = speed,
+            slide = vg_clampf( fabsf(player.slip), 0.0f, 1.0f ),
+            vol0  = (1.0f-air)*attn*(1.0f-slide),
+            vol1  =       air *attn,
+            vol2  = (1.0f-air)*attn*slide;
+      
+      audio_player_set_vol( &audio_player0, vol0 );
+      audio_player_set_vol( &audio_player1, vol1 );
+      audio_player_set_vol( &audio_player2, vol2 );
 
-   audio_player3.vol = audio_player0.vol * audio_occlusion_current * 2.0f;
+      float reverb_amt = vol0 * audio_occlusion_current * 0.5f;
+      audio_player_set_pan( &audio_player3, 0.0f );
+      audio_player_set_vol( &audio_player3, reverb_amt );
+   }
+   
+#if 0
+   world_audio_update( cam, ears );
+#endif
+   audio_unlock();
 }
 
 /*
@@ -1259,6 +1398,8 @@ static int reset_player( int argc, char const *argv[] )
    m3x3_identity( player.gate_vr_pstep_frame );
 
    player.rb_gate_frame = player.rb;
+   player.on_board_frame = player.on_board;
+   player.in_air_frame = player.in_air;
    return 1;
 }
 
@@ -1271,10 +1412,20 @@ static void player_update(void)
    if( vg_get_axis("grabl")>0.0f)
    {
       player.rb = player.rb_gate_frame;
+      player.on_board = player.on_board_frame;
+      player.in_air = player.in_air_frame;
       m3x3_copy( player.gate_vr_frame, player.vr );
       m3x3_copy( player.gate_vr_pstep_frame, player.vr_pstep );
       player.is_dead = 0;
       player.in_air = 1;
+
+
+      if( !player.on_board )
+      {
+         player.angles[0] = atan2f( -player.rb.forward[2], 
+                                    -player.rb.forward[0] );
+      }
+
       m3x3_identity( player.vr );
 
       player.mdl.shoes[0] = 1;