2 * Copyright (C) 2021-2022 Mt.ZERO Software, Harry Godden - All Rights Reserved
6 * TODO: Tilt camera down to face borde when its behind you or out of vision
12 #define PLAYER_REWIND_FRAMES 60*4
23 k_air_accelerate
= 20.0f
,
25 k_board_radius
= 0.3f
,
26 k_board_length
= 0.45f
,
27 k_board_allowance
= 0.04f
,
28 //k_friction_lat = 8.8f,
29 k_friction_lat
= 12.0f
,
30 k_friction_resistance
= 0.01f
,
31 k_max_push_speed
= 16.0f
,
33 k_push_cycle_rate
= 8.0f
,
34 k_steer_ground
= 2.5f
,
36 k_steer_air_lerp
= 0.3f
,
39 k_walk_downforce
= 8.0f
,
40 k_jump_charge_speed
= (1.0f
/1.0f
),
44 k_walk_accel
= 150.0f
,
45 k_walk_friction
= 8.0f
,
49 k_cog_mass_ratio
= 0.9f
,
51 k_mmthrow_scale
= 6.0f
,
52 k_mmcollect_lat
= 2.0f
,
53 k_mmcollect_vert
= 0.0f
,
55 k_spring_angular
= 1.7f
,
57 k_spring_force
= 15.0f
,
58 k_spring_dampener
= 5.0f
;
60 VG_STATIC
int freecam
= 0;
61 VG_STATIC
int walk_grid_iterations
= 1;
62 VG_STATIC
float fc_speed
= 10.0f
;
63 VG_STATIC
int cl_thirdperson
= 0;
66 * -----------------------------------------------------------------------------
68 * -----------------------------------------------------------------------------
71 VG_STATIC
struct gplayer
74 rigidbody collide_front
, collide_back
;
78 rigidbody rb
, rb_gate_frame
;
79 float iY
, siY
; /* Yaw inertia */
81 v3f a
, v_last
, m
, bob
, vl
;
84 float vswitch
, slip
, slip_last
, reverse
;
85 float grab
, jump
, pushing
, push_time
, rise
;
95 int in_air
, on_board
, jump_charge
, jump_dir
, grind
;
102 float normal_pressure
;
103 v3f debug_mmcollect_lat
,
104 debug_mmcollect_vert
;
106 m4x3f visual_transform
,
107 inv_visual_transform
;
109 int is_dead
, death_tick_allowance
, rewinding
;
110 int rewind_sound_wait
;
112 struct land_prediction
130 u32 prediction_count
;
132 v3f handl_target
, handr_target
,
136 struct input_binding
*input_js1h
,
153 v3f camera_pos
, smooth_localcam
;
162 u32 rewind_incrementer
,
165 float rewind_time
, rewind_total_length
, rewind_predicted_time
;
166 double diag_rewind_start
, diag_rewind_time
;
189 enum mdl_surface_prop surface_prop
;
194 glmesh player_meshes
[3];
198 struct skeleton_anim
*anim_stand
,
202 *anim_push
, *anim_push_reverse
,
203 *anim_ollie
, *anim_ollie_reverse
,
204 *anim_grabs
, *anim_stop
,
205 *anim_walk
, *anim_run
, *anim_idle
,
225 /* Collider transform relative to bone */
239 rb_constr_pos position_constraints
[32];
240 u32 position_constraints_count
;
242 rb_constr_swingtwist cone_constraints
[32];
243 u32 cone_constraints_count
;
251 .collide_front
= { .type
= k_rb_shape_sphere
, .inf
.sphere
.radius
= 0.3f
},
252 .collide_back
= { .type
= k_rb_shape_sphere
, .inf
.sphere
.radius
= 0.3f
}
258 VG_STATIC
float *player_get_pos(void);
259 VG_STATIC
void player_kill(void);
260 VG_STATIC
float *player_cam_pos(void);
261 VG_STATIC
void player_save_frame(void);
262 VG_STATIC
void player_restore_frame(void);
263 VG_STATIC
void player_save_rewind_frame(void);
268 VG_STATIC
void player_mouseview(void);
270 #include "player_physics.h"
271 #include "player_ragdoll.h"
272 #include "player_model.h"
273 #include "player_animation.h"
274 #include "player_audio.h"
277 * -----------------------------------------------------------------------------
279 * -----------------------------------------------------------------------------
281 VG_STATIC
int kill_player( int argc
, char const *argv
[] );
282 VG_STATIC
int reset_player( int argc
, char const *argv
[] );
283 VG_STATIC
void reset_player_poll( int argc
, char const *argv
[] );
285 VG_STATIC
void player_init(void) /* 1 */
287 player
.input_js1h
= vg_create_named_input( "steer-h", k_input_type_axis
);
288 player
.input_js1v
= vg_create_named_input( "steer-v", k_input_type_axis
);
289 player
.input_grab
= vg_create_named_input( "grab", k_input_type_axis_norm
);
290 player
.input_js2h
= vg_create_named_input( "grab-h", k_input_type_axis
);
291 player
.input_js2v
= vg_create_named_input( "grab-v", k_input_type_axis
);
292 player
.input_jump
= vg_create_named_input( "jump", k_input_type_button
);
293 player
.input_push
= vg_create_named_input( "push", k_input_type_button
);
294 player
.input_walk
= vg_create_named_input( "walk", k_input_type_button
);
296 player
.input_walkh
= vg_create_named_input( "walk-h",
298 player
.input_walkv
= vg_create_named_input( "walk-v",
302 player
.input_switch_mode
= vg_create_named_input( "switch-mode",
303 k_input_type_button
);
304 player
.input_reset
= vg_create_named_input( "reset", k_input_type_button
);
306 const char *default_cfg
[] =
308 "bind steer-h gp-ls-h",
312 "bind steer-v gp-ls-v",
318 "bind grab-h gp-rs-h",
319 "bind grab-v gp-rs-v",
330 "bind walk-h gp-ls-h",
331 "bind walk-v -gp-ls-v",
340 "bind switch-mode gp-y",
341 "bind switch-mode e",
344 for( int i
=0; i
<vg_list_size(default_cfg
); i
++ )
345 vg_execute_console_input(default_cfg
[i
]);
347 rb_init( &player
.phys
.rb
);
348 rb_init( &player
.collide_front
);
349 rb_init( &player
.collide_back
);
351 VG_VAR_F32( k_walkspeed
);
352 VG_VAR_F32( k_air_accelerate
);
353 VG_VAR_F32( k_runspeed
);
354 VG_VAR_F32( k_walk_accel
);
356 VG_VAR_I32( freecam
);
357 VG_VAR_I32( cl_thirdperson
);
358 VG_VAR_F32_PERSISTENT( fc_speed
);
360 /* TODO: NOT PERSISTENT */
361 VG_VAR_F32_PERSISTENT( k_ragdoll_limit_scale
);
362 VG_VAR_I32_PERSISTENT( k_ragdoll_div
);
363 VG_VAR_I32_PERSISTENT( k_ragdoll_debug_collider
);
364 VG_VAR_I32_PERSISTENT( k_ragdoll_debug_constraints
);
366 VG_VAR_F32_PERSISTENT( k_friction_lat
);
368 VG_VAR_F32_PERSISTENT( k_cog_spring
);
369 VG_VAR_F32_PERSISTENT( k_cog_damp
);
371 VG_VAR_F32_PERSISTENT( k_cog_mass_ratio
);
372 VG_VAR_F32_PERSISTENT( k_downforce
);
374 VG_VAR_F32_PERSISTENT( k_spring_force
);
375 VG_VAR_F32_PERSISTENT( k_spring_dampener
);
376 VG_VAR_F32_PERSISTENT( k_spring_angular
);
378 VG_VAR_F32_PERSISTENT( k_mmthrow_scale
);
379 VG_VAR_F32_PERSISTENT( k_mmcollect_lat
);
380 VG_VAR_F32_PERSISTENT( k_mmcollect_vert
);
381 VG_VAR_F32_PERSISTENT( k_mmdecay
);
383 vg_function_push( (struct vg_cmd
){
385 .function
= reset_player
,
386 .poll_suggest
= reset_player_poll
389 vg_function_push( (struct vg_cmd
){
391 .function
= kill_player
397 player
.rewind_length
= 0;
398 player
.rewind_buffer
=
399 vg_linear_alloc( vg_mem
.rtmemory
,
400 sizeof(struct rewind_frame
) * PLAYER_REWIND_FRAMES
);
408 VG_STATIC
void player_save_rewind_frame(void)
410 if( player
.rewind_length
< PLAYER_REWIND_FRAMES
)
412 struct rewind_frame
*fr
=
413 &player
.rewind_buffer
[ player
.rewind_length
++ ];
415 v2_copy( player
.angles
, fr
->ang
);
416 v3_copy( player
.camera_pos
, fr
->pos
);
418 player
.rewind_incrementer
= 0;
420 if( player
.rewind_length
> 1 )
422 player
.rewind_total_length
+=
423 v3_dist( player
.rewind_buffer
[player
.rewind_length
-1].pos
,
424 player
.rewind_buffer
[player
.rewind_length
-2].pos
);
431 VG_STATIC
int menu_enabled(void);
435 * Free camera movement
437 VG_STATIC
void player_mouseview(void)
442 v2_muladds( player
.angles
, vg
.mouse_delta
, 0.0025f
, player
.angles
);
444 if( vg_input
.controller_should_use_trackpad_look
)
446 static v2f last_input
;
448 static v2f vel_smooth
;
450 v2f input
= { player
.input_js2h
->axis
.value
,
451 player
.input_js2v
->axis
.value
};
453 if( (v2_length2(last_input
) > 0.001f
) && (v2_length2(input
) > 0.001f
) )
455 v2_sub( input
, last_input
, vel
);
456 v2_muls( vel
, 1.0f
/vg
.time_delta
, vel
);
463 v2_lerp( vel_smooth
, vel
, vg
.time_delta
*8.0f
, vel_smooth
);
465 v2_muladds( player
.angles
, vel_smooth
, vg
.time_delta
, player
.angles
);
466 v2_copy( input
, last_input
);
470 player
.angles
[0] += player
.input_js2h
->axis
.value
* vg
.time_delta
* 4.0f
;
471 player
.angles
[1] += player
.input_js2v
->axis
.value
* vg
.time_delta
* 4.0f
;
474 player
.angles
[1] = vg_clampf( player
.angles
[1], -VG_PIf
*0.5f
, VG_PIf
*0.5f
);
477 /* Deal with input etc */
478 VG_STATIC
void player_update_pre(void)
480 struct player_phys
*phys
= &player
.phys
;
485 v3_copy( main_camera
.pos
, ra
);
486 v3_muladds( ra
, main_camera
.transform
[2], -10.0f
, rb
);
489 if( spherecast_world( ra
, rb
, 0.4f
, &t
, rx
) != -1 )
492 m3x3_identity( mtx
);
493 v3_lerp( ra
, rb
, t
, mtx
[3] );
495 debug_sphere( mtx
, 0.4f
, 0xff00ff00 );
498 v3_muladds( mtx
[3], rx
, 0.4f
, x1
);
499 vg_line( mtx
[3], x1
, 0xffffffff );
504 vg_line_pt3( phys
->cog
, 0.10f
, 0xffffffff );
505 vg_line_pt3( phys
->cog
, 0.09f
, 0xffffffff );
506 vg_line_pt3( phys
->cog
, 0.08f
, 0xffffffff );
507 vg_line( phys
->cog
, phys
->rb
.co
, 0xff000000 );
510 v3f throw_end
, p0
, p1
;
511 v3_muladds( phys
->rb
.co
, phys
->rb
.up
, 1.0f
, spring_end
);
512 v3_muladds( spring_end
, phys
->throw_v
, 1.0f
, throw_end
);
513 v3_muladds( spring_end
, player
.debug_mmcollect_lat
, 1.0f
, p0
);
514 v3_muladds( spring_end
, player
.debug_mmcollect_vert
, 1.0f
, p1
);
515 vg_line( spring_end
, throw_end
, VG__RED
);
516 vg_line( spring_end
, p0
, VG__GREEN
);
517 vg_line( spring_end
, p1
, VG__BLUE
);
519 if( player
.rewinding
)
522 if( vg_input_button_down( player
.input_reset
) && !menu_enabled() )
524 double delta
= world
.time
- world
.last_use
;
526 if( (delta
<= RESET_MAX_TIME
) && (world
.last_use
!= 0.0) )
528 player
.rewinding
= 1;
529 player
.rewind_sound_wait
= 1;
530 player
.rewind_time
= (float)player
.rewind_length
- 0.0001f
;
531 player_save_rewind_frame();
533 audio_play_oneshot( &audio_rewind
[0], 1.0f
);
536 /* based on analytical testing. DONT CHANGE!
538 * time taken: y = (x^(4/5)) * 74.5
539 * inverse : x = (2/149)^(4/5) * y^(4/5)
542 float constant
= powf( 2.0f
/149.0f
, 4.0f
/5.0f
),
543 curve
= powf( player
.rewind_total_length
, 4.0f
/5.0f
);
545 player
.rewind_predicted_time
= constant
* curve
;
546 player
.diag_rewind_start
= vg
.time
;
547 player
.diag_rewind_time
= player
.rewind_time
;
550 player
.death_tick_allowance
= 30;
551 player_restore_frame();
553 if( !phys
->on_board
)
555 player
.angles
[0] = atan2f( -phys
->rb
.forward
[2],
556 -phys
->rb
.forward
[0] );
559 player
.mdl
.shoes
[0] = 1;
560 player
.mdl
.shoes
[1] = 1;
562 world_routes_notify_reset();
564 /* apply 1 frame of movement */
571 reset_player( 0, NULL
);
577 audio_play_oneshot( &audio_rewind
[4], 1.0f
);
583 if( vg_input_button_down( player
.input_switch_mode
) && !menu_enabled() )
585 phys
->on_board
^= 0x1;
590 v3_muladds( phys
->rb
.v
, phys
->rb
.forward
, 0.2f
, phys
->rb
.v
);
591 audio_play_oneshot( &audio_lands
[6], 1.0f
);
595 audio_play_oneshot( &audio_lands
[5], 1.0f
);
601 if( !phys
->on_board
)
605 VG_STATIC
void player_update_fixed(void) /* 2 */
607 if( player
.rewinding
)
610 if( player
.death_tick_allowance
)
611 player
.death_tick_allowance
--;
613 struct player_phys
*phys
= &player
.phys
;
617 player_ragdoll_iter();
621 player
.rewind_incrementer
++;
623 if( player
.rewind_incrementer
> (u32
)(0.25/VG_TIMESTEP_FIXED
) )
625 player_save_rewind_frame();
632 VG_STATIC
void player_update_post(void)
634 for( int i
=0; i
<player
.prediction_count
; i
++ )
636 struct land_prediction
*p
= &player
.predictions
[i
];
638 for( int j
=0; j
<p
->log_length
- 1; j
++ )
639 vg_line( p
->log
[j
], p
->log
[j
+1], p
->colour
);
641 vg_line_cross( p
->log
[p
->log_length
-1], p
->colour
, 0.25f
);
644 v3_add( p
->log
[p
->log_length
-1], p
->n
, p1
);
645 vg_line( p
->log
[p
->log_length
-1], p1
, 0xffffffff );
650 player_debug_ragdoll();
653 player_animate_death_cam();
662 player_animate_camera_thirdperson();
664 player_animate_camera();
671 /* CAMERA POSITIONING: LAYER 0 */
672 v2_copy( player
.angles
, main_camera
.angles
);
673 v3_copy( player
.camera_pos
, main_camera
.pos
);
675 if( player
.rewinding
)
677 if( player
.rewind_time
<= 0.0f
)
679 double taken
= vg
.time
- player
.diag_rewind_start
;
680 vg_success( "Rewind took (rt, pl, tl): %f, %f, %f\n",
681 taken
, player
.diag_rewind_time
,
682 player
.rewind_total_length
);
684 player
.rewinding
= 0;
685 player
.rewind_length
= 1;
686 player
.rewind_total_length
= 0.0f
;
687 player
.rewind_incrementer
= 0;
688 world
.sky_target_rate
= 1.0;
692 world
.sky_target_rate
= -100.0;
693 assert( player
.rewind_length
> 0 );
698 float budget
= vg
.time_delta
,
699 overall_length
= player
.rewind_length
;
701 world_routes_rollback_time( player
.rewind_time
/ overall_length
);
703 for( int i
=0; (i
<10)&&(player
.rewind_time
>0.0f
)&&(budget
>0.0f
); i
++ )
705 /* Interpolate frames */
706 int i0
= floorf( player
.rewind_time
),
707 i1
= VG_MIN( i0
+1, player
.rewind_length
-1 );
709 struct rewind_frame
*fr
= &player
.rewind_buffer
[i0
],
710 *fr1
= &player
.rewind_buffer
[i1
];
712 float dist
= vg_maxf( v3_dist( fr
->pos
, fr1
->pos
), 0.001f
),
713 subl
= vg_fractf( player
.rewind_time
) + 0.001f
,
715 sramp
= 3.0f
-(1.0f
/(0.4f
+0.4f
*player
.rewind_time
)),
716 speed
= sramp
*28.0f
+ 0.5f
*player
.rewind_time
,
717 mod
= speed
* (budget
/ dist
),
719 advl
= vg_minf( mod
, subl
),
720 advt
= (advl
/ mod
) * budget
;
722 player
.dist_accum
+= speed
* advt
;
723 player
.rewind_time
-= advl
;
727 player
.rewind_time
= vg_maxf( 0.0f
, player
.rewind_time
);
729 float current_time
= vg
.time
- player
.diag_rewind_start
,
730 remaining
= player
.rewind_predicted_time
- current_time
;
732 if( player
.rewind_sound_wait
)
734 if( player
.rewind_predicted_time
>= 6.5f
)
736 if( remaining
<= 6.5f
)
739 audio_play_oneshot( &audio_rewind
[3], 1.0f
);
741 player
.rewind_sound_wait
= 0;
744 else if( player
.rewind_predicted_time
>= 2.5f
)
746 if( remaining
<= 2.5f
)
749 audio_play_oneshot( &audio_rewind
[2], 1.0f
);
751 player
.rewind_sound_wait
= 0;
754 else if( player
.rewind_predicted_time
>= 1.5f
)
756 if( remaining
<= 1.5f
)
759 audio_play_oneshot( &audio_rewind
[1], 1.0f
);
761 player
.rewind_sound_wait
= 0;
766 int i0
= floorf( player
.rewind_time
),
767 i1
= VG_MIN( i0
+1, player
.rewind_length
-1 );
769 struct rewind_frame
*fr
= &player
.rewind_buffer
[i0
],
770 *fr1
= &player
.rewind_buffer
[i1
];
772 float sub
= vg_fractf(player
.rewind_time
);
774 v3_lerp( fr
->pos
, fr1
->pos
, sub
, override_pos
);
775 override_angles
[0] = vg_alerpf( fr
->ang
[0], fr1
->ang
[0], sub
);
776 override_angles
[1] = vg_lerpf ( fr
->ang
[1], fr1
->ang
[1], sub
);
778 /* CAMERA POSITIONING: LAYER 1 */
779 float blend
= (4.0f
-player
.rewind_time
) * 0.25f
,
780 c
= vg_clampf( blend
, 0.0f
, 1.0f
);
782 main_camera
.angles
[0] =
783 vg_alerpf(override_angles
[0], player
.angles
[0], c
);
784 main_camera
.angles
[1] =
785 vg_lerpf (override_angles
[1], player
.angles
[1], c
);
786 v3_lerp( override_pos
, player
.camera_pos
, c
, main_camera
.pos
);
790 camera_update_transform( &main_camera
);
794 VG_STATIC
void draw_player( camera
*cam
)
797 player_model_copy_ragdoll();
799 shader_viewchar_use();
800 vg_tex2d_bind( &tex_characters
, 0 );
801 shader_viewchar_uTexMain( 0 );
802 shader_viewchar_uCamera( cam
->transform
[3] );
803 shader_viewchar_uPv( cam
->mtx
.pv
);
804 shader_link_standard_ub( _shader_viewchar
.id
, 2 );
805 glUniformMatrix4x3fv( _uniform_viewchar_uTransforms
,
806 player
.mdl
.sk
.bone_count
,
808 (float *)player
.mdl
.sk
.final_mtx
);
810 mesh_bind( &player
.mdl
.player_meshes
[cl_playermdl_id
] );
811 mesh_draw( &player
.mdl
.player_meshes
[cl_playermdl_id
] );
815 * -----------------------------------------------------------------------------
817 * -----------------------------------------------------------------------------
820 VG_STATIC
float *player_get_pos(void)
822 return player
.phys
.rb
.co
;
825 VG_STATIC
void player_kill(void)
827 if( player
.death_tick_allowance
== 0 )
830 player_ragdoll_copy_model( player
.phys
.rb
.v
);
834 VG_STATIC
float *player_cam_pos(void)
836 return player
.camera_pos
;
840 #endif /* PLAYER_H */