X-Git-Url: https://harrygodden.com/git/?a=blobdiff_plain;f=player_walk.c;h=692a296acd525e4f32e6652dd7cc1ec9eaf9aa31;hb=eb203257efcfe324217de9e733cc6c1371b99de6;hp=4dd56e391fff9439690cc72f7ab9538cfbe9e645;hpb=41f359a39cd35650bc6ed4dc01989c683409ca68;p=carveJwlIkooP6JGAAIwe30JlM.git diff --git a/player_walk.c b/player_walk.c index 4dd56e3..692a296 100644 --- a/player_walk.c +++ b/player_walk.c @@ -8,12 +8,21 @@ VG_STATIC void player_walk_drop_in_vector( player_instance *player, v3f vec ) struct player_walk *w = &player->_walk; v3f axis, init_dir; - v3_cross( (v3f){0.0f,1.0f,0.0f}, w->state.drop_in_normal, axis ); + v3_cross( player->basis[1], w->state.drop_in_normal, axis ); v3_cross( axis, w->state.drop_in_normal, init_dir ); v3_normalize( init_dir ); v3_muls( init_dir, 7.0f, vec ); } +VG_STATIC float player_xyspeed2( player_instance *player ) +{ + v3f xy; + v3_muladds( player->rb.v, player->basis[1], + -v3_dot( player->basis[1], player->rb.v ), xy ); + + return v3_length2(xy); +} + VG_STATIC void player_walk_generic_to_skate( player_instance *player, enum skate_activity init, float yaw ) @@ -23,12 +32,9 @@ VG_STATIC void player_walk_generic_to_skate( player_instance *player, struct player_walk *w = &player->_walk; struct player_skate *s = &player->_skate; - v3f xy_speed, v; - - v3_copy( player->rb.v, xy_speed ); - xy_speed[1] = 0.0f; + v3f v; - if( v3_length2( xy_speed ) < 0.1f * 0.1f ) + if( player_xyspeed2(player) < 0.1f * 0.1f ) q_mulv( player->rb.q, (v3f){0.0f,0.0f,1.6f}, v ); else v3_copy( player->rb.v, v ); @@ -39,11 +45,15 @@ VG_STATIC void player_walk_generic_to_skate( player_instance *player, v3f dir; v3_copy( v, dir ); v3_normalize( dir ); + m3x3_mulv( player->invbasis, dir, dir ); - q_axis_angle( player->rb.q, (v3f){0.0f,1.0f,0.0f}, - atan2f( -dir[0], -dir[2] ) ); + q_axis_angle( player->rb.q, (v3f){0.0f,1.0f,0.0f}, atan2f(-dir[0],-dir[2]) ); + q_mul( player->qbasis, player->rb.q, player->rb.q ); + q_normalize( player->rb.q ); + + q_mulv( player->rb.q, (v3f){0.0f,1.0f,0.0f}, s->state.cog ); + v3_add( s->state.cog, player->rb.co, s->state.cog ); - v3_muladds( player->rb.co, player->rb.to_world[1], 1.0f, s->state.cog ); v3_copy( v, s->state.cog_v ); v3_copy( v, player->rb.v ); @@ -86,7 +96,7 @@ VG_STATIC void player_walk_drop_in_overhang_transform( player_instance *player, struct player_walk *w = &player->_walk; v3f axis; - v3_cross( (v3f){0.0f,1.0f,0.0f}, w->state.drop_in_normal, axis ); + v3_cross( player->basis[1], w->state.drop_in_normal, axis ); v3_normalize( axis ); float a = acosf( w->state.drop_in_normal[1] ) * t; @@ -108,6 +118,7 @@ VG_STATIC void player_walk_drop_in_overhang_transform( player_instance *player, VG_STATIC int player_walk_scan_for_drop_in( player_instance *player ) { struct player_walk *w = &player->_walk; + world_instance *world = get_active_world(); v3f dir, center; q_mulv( player->rb.q, (v3f){0.0f,0.0f,1.0f}, dir ); @@ -130,7 +141,7 @@ VG_STATIC int player_walk_scan_for_drop_in( player_instance *player ) ray_hit *ray = &samples[ sample_count ]; ray->dist = 2.0f; - if( ray_world( pos, ray_dir, ray ) ) + if( ray_world( world, pos, ray_dir, ray ) ) { vg_line( pos, ray->pos, VG__RED ); vg_line_pt3( ray->pos, 0.025f, VG__BLACK ); @@ -208,7 +219,7 @@ VG_STATIC int player_walk_scan_for_drop_in( player_instance *player ) ray_hit ray; ray.dist = k_board_length*2.0f + 0.6f; - if( ray_world( va, v0, &ray ) ) + if( ray_world( world, va, v0, &ray ) ) { vg_line( va, vb, VG__RED ); vg_line_pt3( ray.pos, 0.1f, VG__RED ); @@ -217,7 +228,7 @@ VG_STATIC int player_walk_scan_for_drop_in( player_instance *player ) } v3_muls( v0, -1.0f, v0 ); - if( ray_world( vb, v0, &ray ) ) + if( ray_world( world, vb, v0, &ray ) ) { vg_line( va, vb, VG__RED ); vg_line_pt3( ray.pos, 0.1f, VG__RED ); @@ -293,11 +304,7 @@ VG_STATIC void player__walk_pre_update( player_instance *player ) w->state.outro_start_time = vg.time; w->state.activity = k_walk_activity_lockedmove; - v3f xy_speed; - v3_copy( player->rb.v, xy_speed ); - xy_speed[1] = 0.0f; - - if( v3_length2( xy_speed ) < 0.1f * 0.1f ) + if( player_xyspeed2(player) < 0.1f * 0.1f ) q_mulv( player->rb.q, (v3f){0.0f,0.0f,1.6f}, player->rb.v ); } } @@ -311,9 +318,9 @@ VG_STATIC void player__walk_pre_update( player_instance *player ) } } -VG_STATIC int player_walk_normal_standable( v3f n ) +VG_STATIC int player_walk_normal_standable( player_instance *player, v3f n ) { - return n[1] > 0.70710678118f; + return v3_dot( n, player->basis[1] ) > 0.70710678118f; } VG_STATIC void player_accelerate( v3f v, v3f movedir, float speed, float accel ) @@ -354,6 +361,8 @@ VG_STATIC void player__walk_update( player_instance *player ) struct player_walk *w = &player->_walk; v3_copy( player->rb.co, w->state.prev_pos ); + enum walk_activity prev_state = w->state.activity; + if( w->state.activity == k_walk_activity_immobile ) return; @@ -361,8 +370,8 @@ VG_STATIC void player__walk_update( player_instance *player ) w->collider.radius = 0.3f; m4x3f mtx; - m3x3_identity( mtx ); - v3_add( player->rb.co, (v3f){0.0f, 1.0f, 0.0f}, mtx[3] ); + m3x3_copy( player->rb.to_world, mtx ); + v3_add( player->rb.co, player->basis[1], mtx[3] ); debug_capsule( mtx, w->collider.radius, w->collider.height, VG__WHITE ); @@ -374,6 +383,10 @@ VG_STATIC void player__walk_update( player_instance *player ) v3f forward_dir = { sinf(yaw), 0.0f, -cosf(yaw) }; v3f right_dir = { -forward_dir[2], 0.0f, forward_dir[0] }; + m3x3_mulv( player->basis, forward_dir, forward_dir ); + m3x3_mulv( player->basis, right_dir, right_dir ); + + v2f walk = { player->input_walkh->axis.value, player->input_walkv->axis.value }; @@ -381,12 +394,14 @@ VG_STATIC void player__walk_update( player_instance *player ) v2_normalize_clamp( walk ); w->move_speed = v2_length( walk ); + world_instance *world = get_active_world(); /* * Collision detection */ + len = rb_capsule__scene( mtx, &w->collider, NULL, - &world.rb_geo.inf.scene, manifold ); + &world->rb_geo.inf.scene, manifold ); rb_manifold_filter_coplanar( manifold, len, 0.01f ); len = rb_manifold_apply_filtered( manifold, len ); @@ -395,17 +410,21 @@ VG_STATIC void player__walk_update( player_instance *player ) if( w->state.activity != k_walk_activity_lockedmove ) w->state.activity = k_walk_activity_air; - for( int i=0; isurface = k_surface_prop_concrete; + + for( int i=0; in ) ) - { + if( player_walk_normal_standable( player, ct->n ) ){ if( w->state.activity != k_walk_activity_lockedmove ) w->state.activity = k_walk_activity_ground; v3_add( surface_avg, ct->n, surface_avg ); + + struct world_surface *surf = world_contact_surface( world, ct ); + if( surf->info.surface_prop > w->surface ) + w->surface = surf->info.surface_prop; } rb_prepare_contact( ct, k_rb_delta ); @@ -419,15 +438,13 @@ VG_STATIC void player__walk_update( player_instance *player ) v3_muls( right_dir, walk[0], movedir ); v3_muladds( movedir, forward_dir, walk[1], movedir ); - if( w->state.activity == k_walk_activity_ground ) - { + if( w->state.activity == k_walk_activity_ground ){ v3_normalize( surface_avg ); v3f tx, ty; rb_tangent_basis( surface_avg, tx, ty ); - if( v2_length2(walk) > 0.001f ) - { + if( v2_length2(walk) > 0.001f ){ /* clip movement to the surface */ float d = v3_dot(surface_avg,movedir); v3_muladds( movedir, surface_avg, -d, movedir ); @@ -437,29 +454,25 @@ VG_STATIC void player__walk_update( player_instance *player ) nominal_speed = k_walkspeed; /* jump */ - if( player->input_jump->button.value ) - { - player->rb.v[1] = 5.0f; + if( player->input_jump->button.value ){ + float d = v3_dot( player->basis[1], player->rb.v ); + v3_muladds( player->rb.v, player->basis[1], -d, player->rb.v ); + v3_muladds( player->rb.v, player->basis[1], 5.0f, player->rb.v ); w->state.activity = k_walk_activity_air; + prev_state = k_walk_activity_air; accel_speed = k_walk_air_accel; nominal_speed = k_airspeed; } - else - { + else{ player_friction( player->rb.v ); - - struct world_material *surface_mat = world_contact_material(manifold); - w->surface = surface_mat->info.surface_prop; } } - else - { + else{ accel_speed = k_walk_air_accel; nominal_speed = k_airspeed; } - if( v2_length2(walk) > 0.001f ) - { + if( v2_length2(walk) > 0.001f ){ player_accelerate( player->rb.v, movedir, nominal_speed, accel_speed ); v3_normalize( movedir ); } @@ -467,10 +480,8 @@ VG_STATIC void player__walk_update( player_instance *player ) /* * Resolve velocity constraints */ - for( int j=0; j<5; j++ ) - { - for( int i=0; irb.co, player->rb.co ); - - /* TODO: Stepping...... - * - * ideas; walkgrid style steps - */ -#if 0 - if( w->state.activity == k_walk_activity_ground ) - { - /* step */ + /* stepping */ + if( w->state.activity == k_walk_activity_ground|| + prev_state == k_walk_activity_ground ){ float max_dist = 0.4f; v3f pa, pb; v3_copy( player->rb.co, pa ); - pa[1] += w->collider.radius + max_dist; - - v3_muladds( pa, (v3f){0.0f,1.0f,0.0f}, -max_dist * 2.0f, pb ); + v3_muladds( pa, player->basis[1], w->collider.radius + max_dist, pa ); + v3_muladds( pa, player->basis[1], -max_dist * 2.0f, pb ); vg_line( pa, pb, 0xff000000 ); v3f n; float t; - if( spherecast_world( pa, pb, w->collider.radius, &t, n ) != -1 ) - { - if( player_walk_normal_standable( n ) ) - { + if( spherecast_world( world, pa, pb, w->collider.radius, &t, n ) != -1 ){ + if( player_walk_normal_standable( player, n ) ){ v3_lerp( pa, pb, t, player->rb.co ); - player->rb.co[1] -= w->collider.radius; + v3_muladds( player->rb.co, player->basis[1], + -w->collider.radius - k_penetration_slop, + player->rb.co ); + w->state.activity = k_walk_activity_ground; + + float d = -v3_dot(n,player->rb.v), + g = -k_gravity * k_rb_delta; + v3_muladds( player->rb.v, n, d, player->rb.v ); + v3_muladds( player->rb.v, player->basis[1], g, player->rb.v ); } } } -#endif + /* + * Depenetrate + */ + v3f dt; + rb_depenetrate( manifold, len, dt ); + v3_add( dt, player->rb.co, player->rb.co ); /* integrate */ - if( w->state.activity == k_walk_activity_air ) - player->rb.v[1] += -k_gravity * k_rb_delta; + if( w->state.activity == k_walk_activity_air ){ + v3_muladds( player->rb.v, player->basis[1], -k_gravity*k_rb_delta, + player->rb.v ); + } v3_muladds( player->rb.co, player->rb.v, k_rb_delta, player->rb.co ); - - - v3_add( player->rb.co, (v3f){0.0f, 1.0f, 0.0f}, mtx[3] ); + v3_add( player->rb.co, player->basis[1], mtx[3] ); debug_capsule( mtx, w->collider.radius, w->collider.height, VG__GREEN ); /* @@ -549,27 +558,30 @@ VG_STATIC void player__walk_update( player_instance *player ) float movedist = v3_length( movedelta ); - if( movedist > 0.3f ) - { + if( movedist > 0.3f ){ float t, sr = w->collider.radius-0.04f; v3f n; - if( spherecast_world( lwr_prev, lwr_now, sr, &t, n ) != -1 ) - { + if( spherecast_world( world, lwr_prev, lwr_now, sr, &t, n ) != -1 ){ v3_lerp( lwr_prev, lwr_now, vg_maxf(0.01f,t), player->rb.co ); player->rb.co[1] -= w->collider.radius; rb_update_transform( &player->rb ); - v3_add( player->rb.co, (v3f){0.0f, 1.0f, 0.0f}, mtx[3] ); + v3_add( player->rb.co, player->basis[1], mtx[3] ); debug_capsule( mtx, w->collider.radius, w->collider.height, VG__RED ); } } - teleport_gate *gate; - if( (gate = world_intersect_gates( player->rb.co, w->state.prev_pos )) ) - { + ent_gate *gate = + world_intersect_gates( world, player->rb.co, w->state.prev_pos ); + if( gate ){ m4x3_mulv( gate->transport, player->rb.co, player->rb.co ); m3x3_mulv( gate->transport, player->rb.v, player->rb.v ); + + v4f transport_rotation; + m3x3_q( gate->transport, transport_rotation ); + q_mul( transport_rotation, player->rb.q, player->rb.q ); + rb_update_transform( &player->rb ); w->state_gate_storage = w->state; @@ -577,13 +589,19 @@ VG_STATIC void player__walk_update( player_instance *player ) } } +VG_STATIC void player__walk_restore( player_instance *player ) +{ + struct player_walk *w = &player->_walk; + w->state = w->state_gate_storage; +} + VG_STATIC void player__walk_post_update( player_instance *player ) { struct player_walk *w = &player->_walk; m4x3f mtx; m3x3_copy( player->rb.to_world, mtx ); - v3_add( player->rb.co, (v3f){0.0f, 1.0f, 0.0f}, mtx[3] ); + v3_add( player->rb.co, player->basis[1], mtx[3] ); float substep = vg_clampf( vg.accumulator / k_rb_delta, 0.0f, 1.0f ); v3_muladds( mtx[3], player->rb.v, k_rb_delta*substep, mtx[3] ); @@ -591,15 +609,16 @@ VG_STATIC void player__walk_post_update( player_instance *player ) /* Calculate header */ - v3f xy_speed, v; - - v3_copy( player->rb.v, xy_speed ); - xy_speed[1] = 0.0f; - - if( v3_length2( xy_speed ) > 0.1f * 0.1f ) + v3f v; + if( player_xyspeed2(player) > 0.1f*0.1f ) { - float a = atan2f( player->rb.v[0], player->rb.v[2] ); + v3f v_xy; + m3x3_mulv( player->invbasis, player->rb.v, v_xy ); + float a = atan2f( v_xy[0], v_xy[2] ); + q_axis_angle( player->rb.q, (v3f){0.0f,1.0f,0.0f}, a ); + q_mul( player->qbasis, player->rb.q, player->rb.q ); + q_normalize( player->rb.q ); } vg_line_pt3( w->state.drop_in_target, 0.1f, VG__GREEN ); @@ -617,9 +636,44 @@ VG_STATIC void player__walk_post_update( player_instance *player ) p1[0] = sinf( a ); p1[1] = 0.0f; p1[2] = cosf( a ); + m3x3_mulv( player->basis, p1, p1 ); v3_add( player->rb.co, p1, p1 ); vg_line( player->rb.co, p1, VG__PINK ); + + + int walk_phase = 0; + if( vg_fractf(w->walk_timer) > 0.5f ) + walk_phase = 1; + else + walk_phase = 0; + + if( (w->step_phase != walk_phase) && + (w->state.activity == k_walk_activity_ground ) ) + { + audio_lock(); + if( w->surface == k_surface_prop_concrete ){ + audio_oneshot_3d( + &audio_footsteps[rand()%vg_list_size(audio_footsteps)], + player->rb.co, 40.0f, 1.0f + ); + } + else if( w->surface == k_surface_prop_grass ){ + audio_oneshot_3d( + &audio_footsteps_grass[rand()%vg_list_size(audio_footsteps_grass)], + player->rb.co, 40.0f, 1.0f + ); + } + else if( w->surface == k_surface_prop_wood ){ + audio_oneshot_3d( + &audio_footsteps_wood[rand()%vg_list_size(audio_footsteps_wood)], + player->rb.co, 40.0f, 1.0f + ); + } + audio_unlock(); + } + + w->step_phase = walk_phase; } VG_STATIC void player__walk_animate( player_instance *player, @@ -646,8 +700,7 @@ VG_STATIC void player__walk_animate( player_instance *player, player_pose apose, bpose; - if( w->move_speed > 0.025f ) - { + if( w->move_speed > 0.025f ){ /* TODO move */ float walk_norm = 30.0f/(float)w->anim_walk->length, run_norm = 30.0f/(float)w->anim_run->length, @@ -655,8 +708,7 @@ VG_STATIC void player__walk_animate( player_instance *player, w->walk_timer += walk_adv * vg.time_delta; } - else - { + else{ w->walk_timer = 0.0f; } @@ -685,8 +737,7 @@ VG_STATIC void player__walk_animate( player_instance *player, float walk_yaw = player_get_heading_yaw( player ); - if( w->state.outro_anim ) - { + if( w->state.outro_anim ){ struct player_avatar *av = player->playeravatar; float outro_length = (float)w->state.outro_anim->length / w->state.outro_anim->rate, @@ -698,8 +749,7 @@ VG_STATIC void player__walk_animate( player_instance *player, outro_time, bpose ); skeleton_lerp_pose( sk, apose, bpose, outro_t * 10.0f, dest->pose ); - if( w->state.outro_type == k_walk_outro_drop_in ) - { + if( w->state.outro_type == k_walk_outro_drop_in ){ float inv_rate = 1.0f / w->state.outro_anim->rate, anim_frames = w->state.outro_anim->length * inv_rate, step_frames = 12.0f * inv_rate, @@ -731,8 +781,7 @@ VG_STATIC void player__walk_animate( player_instance *player, /* the drop in bit */ - if( step_t >= 1.0f ) - { + if( step_t >= 1.0f ){ v4f final_q; player_walk_drop_in_overhang_transform( player, dop_t, player->rb.co, final_q ); @@ -747,8 +796,7 @@ VG_STATIC void player__walk_animate( player_instance *player, } return; } - else - { + else{ v3_muladds( dest->root_co, player->rb.to_world[1], -0.1f * outro_t, dest->root_co ); @@ -756,12 +804,13 @@ VG_STATIC void player__walk_animate( player_instance *player, player->holdout_time = 1.0f; } } - else - { + else{ skeleton_copy_pose( sk, apose, dest->pose ); } q_axis_angle( dest->root_q, (v3f){0.0f,1.0f,0.0f}, walk_yaw + VG_PIf ); + q_mul( player->qbasis, dest->root_q, dest->root_q ); + q_normalize( dest->root_q ); } VG_STATIC void player__walk_post_animate( player_instance *player ) @@ -802,9 +851,15 @@ VG_STATIC void player__walk_im_gui( player_instance *player ) "k_walk_activity_immobile", "k_walk_activity_lockedmove" } [w->state.activity] ); - - if( w->state.outro_anim ) - { + player__debugtext( 1, "surface: %s\n", + (const char *[]){ "concrete", + "wood", + "grass", + "tiles", + "metal" } + [w->surface] ); + + if( w->state.outro_anim ){ float outro_length = (float)w->state.outro_anim->length / w->state.outro_anim->rate, outro_time = vg.time - w->state.outro_start_time; @@ -834,10 +889,22 @@ VG_STATIC void player__walk_transition( player_instance *player, v3f angles ) v3f fwd = { 0.0f, 0.0f, 1.0f }; q_mulv( player->rb.q, fwd, fwd ); + m3x3_mulv( player->invbasis, fwd, fwd ); + + q_axis_angle( player->rb.q, (v3f){0.0f,1.0f,0.0f}, atan2f(fwd[0], fwd[2]) ); + q_mul( player->qbasis, player->rb.q, player->rb.q ); + q_normalize( player->rb.q ); - q_axis_angle( player->rb.q, (v3f){0.0f,1.0f,0.0f}, - atan2f( fwd[0], fwd[2] ) ); rb_update_transform( &player->rb ); } +VG_STATIC void player__walk_reset( player_instance *player, ent_spawn *rp ) +{ + struct player_walk *w = &player->_walk; + w->state.activity = k_walk_activity_air; + w->state.outro_type = k_walk_outro_none; + w->state.outro_anim = NULL; + w->state.outro_start_time = 0.0; +} + #endif /* PLAYER_DEVICE_WALK_H */