camera shake

This commit is contained in:
jacob 2025-01-14 17:06:25 -06:00
parent 25592d24d3
commit 4c194d3b39
3 changed files with 78 additions and 31 deletions

View File

@ -34,6 +34,8 @@ enum entity_prop {
ENTITY_PROP_BULLET, ENTITY_PROP_BULLET,
ENTITY_PROP_TRACER, ENTITY_PROP_TRACER,
ENTITY_PROP_QUAKE,
ENTITY_PROP_ATTACHED, ENTITY_PROP_ATTACHED,
/* Test props */ /* Test props */
@ -246,6 +248,14 @@ struct entity {
struct v2 tracer_gradient_start; struct v2 tracer_gradient_start;
struct v2 tracer_gradient_end; struct v2 tracer_gradient_end;
/* ====================================================================== */
/* Quake */
/* ENTITY_PROP_QUAKE */
f32 quake_intensity;
f32 quake_fade; /* How much intensity to lose per second */
/* ====================================================================== */ /* ====================================================================== */
/* Testing */ /* Testing */
@ -269,6 +279,8 @@ struct entity {
u32 camera_lerp_continuity_gen; u32 camera_lerp_continuity_gen;
struct xform camera_xform_target; /* Calculated from camera_follow */ struct xform camera_xform_target; /* Calculated from camera_follow */
u32 camera_applied_lerp_continuity_gen_plus_one; /* Calculated */ u32 camera_applied_lerp_continuity_gen_plus_one; /* Calculated */
f32 shake;
}; };
struct entity_array { struct entity_array {

View File

@ -222,7 +222,7 @@ INTERNAL void spawn_test_entities(void)
} }
/* Enemy */ /* Enemy */
#if 0 #if 1
{ {
struct entity *e = entity_alloc(root); struct entity *e = entity_alloc(root);
@ -1144,23 +1144,33 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
tracer->tracer_gradient_end = pos; tracer->tracer_gradient_end = pos;
tracer->tracer_gradient_start = v2_sub(pos, v2_mul(ent->linear_velocity, tracer->tracer_fade_duration)); tracer->tracer_gradient_start = v2_sub(pos, v2_mul(ent->linear_velocity, tracer->tracer_fade_duration));
} }
/* Spawn quake */
{
struct entity *quake = entity_alloc(root);
entity_set_xform(quake, XFORM_POS(pos));
quake->quake_intensity = 0.02f;
quake->quake_fade = quake->quake_intensity / 0.01f;
entity_enable_prop(quake, ENTITY_PROP_QUAKE);
}
} }
} }
/* ========================== * /* ========================== *
* Update camera position * Update cameras
* ========================== */ * ========================== */
for (u64 entity_index = 0; entity_index < store->reserved; ++entity_index) { for (u64 entity_index = 0; entity_index < store->reserved; ++entity_index) {
struct entity *ent = &store->entities[entity_index]; struct entity *ent = &store->entities[entity_index];
if (!entity_is_valid_and_active(ent)) continue; if (!entity_is_valid_and_active(ent)) continue;
if (!entity_has_prop(ent, ENTITY_PROP_CAMERA)) continue;
/* Camera follow */
if (entity_has_prop(ent, ENTITY_PROP_CAMERA)) {
struct entity *follow = entity_from_handle(store, ent->camera_follow);
struct xform xf = entity_get_xform(ent); struct xform xf = entity_get_xform(ent);
/* Camera follow */
{
struct entity *follow = entity_from_handle(store, ent->camera_follow);
f32 aspect_ratio = 1.0; f32 aspect_ratio = 1.0;
{ {
struct xform quad_xf = xform_mul(entity_get_xform(ent), ent->camera_quad_xform); struct xform quad_xf = xform_mul(entity_get_xform(ent), ent->camera_quad_xform);
@ -1185,8 +1195,36 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
xf = ent->camera_xform_target; xf = ent->camera_xform_target;
} }
ent->camera_applied_lerp_continuity_gen_plus_one = ent->camera_lerp_continuity_gen + 1; ent->camera_applied_lerp_continuity_gen_plus_one = ent->camera_lerp_continuity_gen + 1;
}
/* Camera shake */
{
/* TODO: Update based on distance to quake */
ent->shake = 0;
for (u64 quake_ent_index = 0; quake_ent_index < store->reserved; ++quake_ent_index) {
struct entity *quake = &store->entities[quake_ent_index];
if (!entity_is_valid_and_active(quake)) continue;
if (!entity_has_prop(quake, ENTITY_PROP_QUAKE)) continue;
ent->shake += quake->quake_intensity;
}
}
entity_set_xform(ent, xf); entity_set_xform(ent, xf);
} }
/* ========================== *
* Update quakes
* ========================== */
for (u64 entity_index = 0; entity_index < store->reserved; ++entity_index) {
struct entity *ent = &store->entities[entity_index];
if (!entity_is_valid_and_active(ent)) continue;
if (!entity_has_prop(ent, ENTITY_PROP_QUAKE)) continue;
ent->quake_intensity = max_f32(0, ent->quake_intensity - (ent->quake_fade * dt));
if (ent->quake_intensity <= 0) {
entity_enable_prop(ent, ENTITY_PROP_RELEASE_NEXT_TICK);
}
} }
/* ========================== * /* ========================== *

View File

@ -388,10 +388,6 @@ INTERNAL void pubilsh_game_cmds(struct game_cmd_list *list)
scratch_end(scratch); scratch_end(scratch);
} }
/* ========================== *
* Update
* ========================== */
/* TODO: remove this (testing) */ /* TODO: remove this (testing) */
INTERNAL void debug_draw_xform(struct xform xf, u32 color_x, u32 color_y) INTERNAL void debug_draw_xform(struct xform xf, u32 color_x, u32 color_y)
{ {
@ -432,24 +428,9 @@ INTERNAL void debug_draw_movement(struct entity *ent)
draw_solid_arrow_ray(G.viewport_canvas, pos, vel_ray, thickness, arrow_len, color_vel); draw_solid_arrow_ray(G.viewport_canvas, pos, vel_ray, thickness, arrow_len, color_vel);
} }
/* ========================== *
* Update
* ========================== */
INTERNAL void user_update(void) INTERNAL void user_update(void)
{ {
@ -541,6 +522,7 @@ INTERNAL void user_update(void)
e->camera_quad_xform = xform_lerp(e0->camera_quad_xform, e1->camera_quad_xform, tick_blend); e->camera_quad_xform = xform_lerp(e0->camera_quad_xform, e1->camera_quad_xform, tick_blend);
e->camera_xform_target = xform_lerp(e0->camera_xform_target, e1->camera_xform_target, tick_blend); e->camera_xform_target = xform_lerp(e0->camera_xform_target, e1->camera_xform_target, tick_blend);
e->shake = math_lerp(e0->shake, e1->shake, tick_blend);
e->tracer_gradient_start = v2_lerp(e0->tracer_gradient_start, e1->tracer_gradient_start, tick_blend); e->tracer_gradient_start = v2_lerp(e0->tracer_gradient_start, e1->tracer_gradient_start, tick_blend);
e->tracer_gradient_end = v2_lerp(e0->tracer_gradient_end, e1->tracer_gradient_end, tick_blend); e->tracer_gradient_end = v2_lerp(e0->tracer_gradient_end, e1->tracer_gradient_end, tick_blend);
@ -693,9 +675,24 @@ INTERNAL void user_update(void)
G.debug_camera = !G.debug_camera; G.debug_camera = !G.debug_camera;
} }
/* ========================== *
* Apply shake
* ========================== */
for (u64 entity_index = 0; entity_index < store->reserved; ++entity_index) {
struct entity *ent = &store->entities[entity_index];
if (!entity_is_valid_and_active(ent)) continue;
if (ent->shake <= 0) continue;
f32 shake = ent->shake;
struct xform xf = entity_get_xform(ent);
xf.og = v2_add(xf.og, v2_mul(v2_from_angle(sys_rand_f32(0, TAU)), shake));
entity_set_xform(ent, xf);
}
/* ========================== * /* ========================== *
* Update viewport * Update viewport from camera
* ========================== */ * ========================== */
/* Calculate screen viewport dimensions */ /* Calculate screen viewport dimensions */
@ -734,7 +731,7 @@ INTERNAL void user_update(void)
G.viewport_cursor = v2_sub(G.screen_cursor, G.viewport_screen_offset); G.viewport_cursor = v2_sub(G.screen_cursor, G.viewport_screen_offset);
/* ========================== * /* ========================== *
* Update view * Update view from camera
* ========================== */ * ========================== */
if (G.debug_camera) { if (G.debug_camera) {
@ -798,7 +795,7 @@ INTERNAL void user_update(void)
G.world_cursor = xform_invert_mul_v2(G.world_view, G.viewport_cursor); G.world_cursor = xform_invert_mul_v2(G.world_view, G.viewport_cursor);
/* ========================== * /* ========================== *
* Update listener * Update listener from view
* ========================== */ * ========================== */
{ {