diff --git a/src/config.h b/src/config.h index 2c3576dc..c7219261 100644 --- a/src/config.h +++ b/src/config.h @@ -28,5 +28,3 @@ #define AUDIO_ENABLED 0 #define VSYNC_ENABLED 0 - -#define MOUSE_SENSITIVITY 1 diff --git a/src/entity.h b/src/entity.h index 4d52330c..97a59649 100644 --- a/src/entity.h +++ b/src/entity.h @@ -60,7 +60,7 @@ struct entity { /* ENTITY_PROP_PLAYER_CONTROLLED */ f32 player_max_speed; f32 player_acceleration; - struct v2 player_focus_dir; + struct v2 player_aim; /* ====================================================================== */ /* Sprite */ diff --git a/src/game.c b/src/game.c index d9d35041..b0856c1d 100644 --- a/src/game.c +++ b/src/game.c @@ -121,7 +121,7 @@ INTERNAL void game_update(void) entity_enable_prop(e, ENTITY_PROP_PLAYER_CONTROLLED); e->player_max_speed = 4.f; e->player_acceleration = 20.0f; - e->player_focus_dir = V2(0, -1); + e->player_aim = V2(0, -1); entity_enable_prop(e, ENTITY_PROP_ANIMATING); @@ -238,8 +238,6 @@ INTERNAL void game_update(void) * Process game cmds * ========================== */ - L.world.player_focus_move_dir = V2(0, 0); - struct game_cmd_array game_cmds = pop_cmds(scratch.arena); for (u64 cmd_index = 0; cmd_index < game_cmds.count; ++cmd_index) { struct game_cmd cmd = game_cmds.cmds[cmd_index]; @@ -248,7 +246,7 @@ INTERNAL void game_update(void) /* Movement */ case GAME_CMD_KIND_PLAYER_MOVE: { L.world.player_move_dir = cmd.move_dir; - L.world.player_focus_move_dir = v2_add(L.world.player_focus_move_dir, cmd.focus_move_dir); + L.world.player_aim = cmd.aim; } break; /* Clear level */ @@ -385,16 +383,16 @@ INTERNAL void game_update(void) } /* ========================== * - * Player focus + * Player aim * ========================== */ if (entity_has_prop(ent, ENTITY_PROP_PLAYER_CONTROLLED)) { - /* Update focus */ - ent->player_focus_dir = v2_add(ent->player_focus_dir, L.world.player_focus_move_dir); + /* Update aim */ + ent->player_aim = L.world.player_aim; /* Update view angle */ struct v2 ent_pos = ent->rel_xform.og; - struct v2 look_pos = v2_add(ent_pos, ent->player_focus_dir); + struct v2 look_pos = v2_add(ent_pos, ent->player_aim); f32 r = v2_angle_to_point(ent_pos, look_pos) + PI / 2; ent->rel_xform = xform_with_rotation(ent->rel_xform, r); } @@ -460,26 +458,27 @@ INTERNAL void game_update(void) ent->camera_target_xform = xform_with_scale(ent->camera_target_xform, V2(1, 1)); if (entity_has_prop(follow, ENTITY_PROP_PLAYER_CONTROLLED)) { -#if 1 +#if 0 /* Regular style camera */ f32 target_dist_x = 0.5; - f32 target_dist_y = target_dist_x * (16.0f / 9.0f); - struct v2 focus_dir = follow->player_focus_dir; - struct v2 target_dir = v2_mul_v2(v2_norm(focus_dir), V2(target_dist_x, target_dist_y)); + //f32 target_dist_y = target_dist_x * (16.0f / 9.0f); + f32 target_dist_y = target_dist_x; + struct v2 target_dir = v2_mul_v2(v2_norm(follow->player_aim), V2(target_dist_x, target_dist_y)); struct v2 target_pos = v2_add(ent->camera_target_xform.og, target_dir); ent->camera_target_xform.og = target_pos; #else /* "Look" style camera */ - struct v2 focus_dir = follow->player_focus_dir; - struct v2 focus_half_dir = v2_mul(focus_dir, 0.5f); - struct v2 focus_half_pos = v2_add(follow->world_xform.og, focus_half_dir); - ent->camera_target_xform.og = focus_half_pos; + f32 ratio_x = 0.33f; + f32 ratio_y = 0.33f; + struct v2 camera_focus_dir = v2_mul_v2(follow->player_aim, V2(ratio_x, ratio_y)); + struct v2 camera_focus_pos = v2_add(follow->world_xform.og, camera_focus_dir); + ent->camera_target_xform.og = camera_focus_pos; #endif } /* Lerp camera */ if (ent->camera_applied_lerp_gen_plus_one == ent->camera_lerp_gen + 1) { - f32 t = 1 - math_pow(2.f, -10.f * (f32)L.world.dt); + f32 t = 1 - math_pow(2.f, -20.f * (f32)L.world.dt); ent->rel_xform = xform_lerp(ent->rel_xform, ent->camera_target_xform, t); } else { /* Skip lerp */ diff --git a/src/game.h b/src/game.h index 5ecb0d98..7b34178a 100644 --- a/src/game.h +++ b/src/game.h @@ -19,7 +19,7 @@ struct game_cmd { /* GAME_CMD_KIND_PLAYER_MOVE */ struct v2 move_dir; - struct v2 focus_move_dir; + struct v2 aim; }; struct game_cmd_array { diff --git a/src/user.c b/src/user.c index e8c1559e..fb2e0d0c 100644 --- a/src/user.c +++ b/src/user.c @@ -14,9 +14,6 @@ #include "sys.h" #include "world.h" #include "entity.h" - -/* FIXME: remove this (testing) */ -#include "sound.h" #include "mixer.h" struct bind_state { @@ -67,7 +64,6 @@ GLOBAL struct { struct v2 screen_cursor; struct v2 world_cursor; struct v2 mouse_delta; - struct v2 last_focus_screen_pos; } L = { 0 }, DEBUG_LVAR(L_user); /* ========================== * @@ -406,7 +402,7 @@ INTERNAL void user_update(void) e->acceleration = v2_lerp(e0->acceleration, e1->acceleration, tick_blend); e->velocity = v2_lerp(e0->velocity, e1->velocity, tick_blend); e->player_acceleration = math_lerp(e0->player_acceleration, e1->player_acceleration, tick_blend); - e->player_focus_dir = v2_lerp(e0->player_focus_dir, e1->player_focus_dir, tick_blend); + e->player_aim = v2_lerp(e0->player_aim, e1->player_aim, tick_blend); e->sprite_xform = xform_lerp(e0->sprite_xform, e1->sprite_xform, tick_blend); e->animation_time_in_frame = math_lerp_f64(e0->animation_time_in_frame, e1->animation_time_in_frame, (f64)tick_blend); @@ -421,9 +417,30 @@ INTERNAL void user_update(void) tick_is_first_frame = L.world.tick_id == 0; #endif } - struct entity_array entities_array = entity_store_as_array(&L.world.entity_store); + /* ========================== * + * Find important entities + * ========================== */ + + struct entity *player = entity_nil(); + struct entity *active_camera = entity_nil(); + + for (u64 entity_index = 0; entity_index < entities_array.count; ++entity_index) { + struct entity *ent = &entities_array.entities[entity_index]; + if (!ent->valid) continue; + + /* Player */ + if (entity_has_prop(ent, ENTITY_PROP_PLAYER_CONTROLLED)) { + player = ent; + } + + /* Active camera */ + if (entity_has_prop(ent, ENTITY_PROP_CAMERA) && entity_has_prop(ent, ENTITY_PROP_CAMERA_ACTIVE)) { + active_camera = ent; + } + } + /* ========================== * * Read sys events * ========================== */ @@ -460,21 +477,6 @@ INTERNAL void user_update(void) #endif } -#if 0 - /* Text */ - if (event->kind == SYS_EVENT_KIND_TEXT) { - /* TODO: remove this (sound test) */ - { - //u32 flags = SOUND_FLAG_STEREO; - u32 flags = 0; - struct sound *sound = sound_load(STR("res/sounds/test.mp3"), flags); - if (sound) { - mixer_play_ex(sound, MIXER_DESC(.volume = 1.0, .speed = 1.0)); - } - } - } -#endif - /* Update mouse pos */ if (event->kind == SYS_EVENT_KIND_CURSOR_MOVE) { L.screen_cursor = event->cursor_position; @@ -527,10 +529,6 @@ INTERNAL void user_update(void) } if (L.bind_states[USER_BIND_KIND_DEBUG_CAMERA].num_presses > 0) { - if (!L.debug_camera) { - /* Move cursor to last crosshair pos */ - sys_window_cursor_set_pos(L.window, L.last_focus_screen_pos); - } L.debug_camera = !L.debug_camera; } @@ -579,16 +577,9 @@ INTERNAL void user_update(void) sys_window_cursor_hide(L.window); sys_window_cursor_enable_keep_in_window(L.window); - enum entity_prop props[] = { ENTITY_PROP_CAMERA, ENTITY_PROP_CAMERA_ACTIVE }; - struct entity_prop_array props_array = { - .props = props, - .count = ARRAY_COUNT(props) - }; - struct entity *ent = entity_find_first_match_all(&L.world.entity_store, props_array); - - struct v2 center = ent->world_xform.og; - f32 rot = xform_get_rotation(ent->world_xform); - f32 zoom = ent->camera_zoom; + struct v2 center = active_camera->world_xform.og; + f32 rot = xform_get_rotation(active_camera->world_xform); + f32 zoom = active_camera->camera_zoom; zoom = zoom > 0 ? zoom : 1; struct trs trs = TRS( @@ -615,57 +606,6 @@ INTERNAL void user_update(void) mixer_set_listener(listener_pos, listener_dir); } - /* ========================== * - * Construct movement input - * ========================== */ - - /* Movement */ - { - struct v2 player_move_dir = { 0 }; - for (enum user_bind_kind bind = 0; bind < (i32)ARRAY_COUNT(L.bind_states); ++bind) { - struct bind_state state = L.bind_states[bind]; - - if (!state.is_held && state.num_presses <= 0) { - continue; - } - - switch (bind) { - /* Movement */ - case USER_BIND_KIND_MOVE_UP: { - player_move_dir.y -= 1; - } break; - - case USER_BIND_KIND_MOVE_DOWN: { - player_move_dir.y += 1; - } break; - - case USER_BIND_KIND_MOVE_LEFT: { - player_move_dir.x -= 1; - } break; - - case USER_BIND_KIND_MOVE_RIGHT: { - player_move_dir.x += 1; - } break; - - default: break; - } - } - - player_move_dir = xform_basis_invert_mul_v2(L.world_view, player_move_dir); /* Make move dir relative to world view */ - player_move_dir = v2_norm(player_move_dir); - - struct game_cmd cmd = (struct game_cmd) { - .kind = GAME_CMD_KIND_PLAYER_MOVE, - .move_dir = player_move_dir - }; - if (!L.debug_camera) { - struct v2 focus_move_dir = xform_basis_invert_mul_v2(L.world_view, L.mouse_delta); /* Make focus relative to world view direction */ - focus_move_dir = v2_mul(focus_move_dir, MOUSE_SENSITIVITY); - cmd.focus_move_dir = focus_move_dir; - } - queue_game_cmd(&cmd_list, cmd); - } - /* ========================== * * Draw test grid * ========================== */ @@ -718,7 +658,7 @@ INTERNAL void user_update(void) struct entity *ent = &entities_array.entities[entity_index]; if (!ent->valid) continue; - b32 is_camera = entity_has_prop(ent, ENTITY_PROP_CAMERA); + b32 skip_debug_draw = entity_has_prop(ent, ENTITY_PROP_CAMERA); /* Draw sprite */ if (ent->sprite_name.len > 0) { @@ -759,7 +699,7 @@ INTERNAL void user_update(void) draw_texture_quad(L.world_canvas, params, quad); #if 0 - if (L.debug_draw && !is_camera) { + if (L.debug_draw && !skip_debug_draw) { /* Debug draw sprite quad */ { f32 thickness = 2.f; @@ -782,24 +722,8 @@ INTERNAL void user_update(void) } } - /* Draw crosshair */ - if (!L.debug_camera && entity_has_prop(ent, ENTITY_PROP_PLAYER_CONTROLLED)) { - struct v2 focus_pos = v2_add(ent->world_xform.og, ent->player_focus_dir); - struct v2 focus_pos_screen = xform_mul_v2(L.world_view, focus_pos); - u32 tint = RGBA_F(1, 1, 1, 0.5); - - struct texture *t = texture_load_async(STR("res/graphics/crosshair.ase")); - if (t) { - struct xform xf = XFORM_TRS(.t = focus_pos_screen, .s = t->size); - struct quad quad = quad_mul_xform(QUAD_UNIT_SQUARE_CENTERED, xf); - draw_texture_quad(L.screen_canvas, DRAW_TEXTURE_PARAMS(.texture = t, .tint = tint), quad); - } - - L.last_focus_screen_pos = focus_pos_screen; - } - /* Debug draw info */ - if (L.debug_draw && !is_camera) { + if (L.debug_draw && !skip_debug_draw) { struct temp_arena temp = arena_temp_begin(scratch.arena); #if 0 @@ -854,20 +778,87 @@ INTERNAL void user_update(void) draw_solid_arrow_line(L.screen_canvas, start, end, thickness, arrow_height, color); } - /* Draw focus */ + /* Draw aim */ if (entity_has_prop(ent, ENTITY_PROP_PLAYER_CONTROLLED)) { u32 color = RGBA_F(0.75, 0, 0.75, 0.5); f32 thickness = 3; f32 arrow_height = 10; struct v2 pos = xform_mul_v2(L.world_view, ent->world_xform.og); - struct v2 focus_ray = xform_basis_mul_v2(L.world_view, ent->player_focus_dir); - draw_solid_arrow_ray(L.screen_canvas, pos, focus_ray, thickness, arrow_height, color); + struct v2 aim_ray = xform_basis_mul_v2(L.world_view, ent->player_aim); + draw_solid_arrow_ray(L.screen_canvas, pos, aim_ray, thickness, arrow_height, color); } arena_temp_end(temp); } } + /* Draw crosshair */ + if (!L.debug_camera) { + struct v2 crosshair_pos = L.screen_cursor; + u32 tint = RGBA_F(1, 1, 1, 0.5); + + struct texture *t = texture_load_async(STR("res/graphics/crosshair.ase")); + if (t) { + struct xform xf = XFORM_TRS(.t = crosshair_pos, .s = t->size); + struct quad quad = quad_mul_xform(QUAD_UNIT_SQUARE_CENTERED, xf); + draw_texture_quad(L.screen_canvas, DRAW_TEXTURE_PARAMS(.texture = t, .tint = tint), quad); + } + } + + /* ========================== * + * Construct movement input + * ========================== */ + + /* Movement */ + struct v2 input_move_dir = { 0 }; + { + for (enum user_bind_kind bind = 0; bind < (i32)ARRAY_COUNT(L.bind_states); ++bind) { + struct bind_state state = L.bind_states[bind]; + + if (!state.is_held && state.num_presses <= 0) { + continue; + } + + switch (bind) { + /* Movement */ + case USER_BIND_KIND_MOVE_UP: { + input_move_dir.y -= 1; + } break; + + case USER_BIND_KIND_MOVE_DOWN: { + input_move_dir.y += 1; + } break; + + case USER_BIND_KIND_MOVE_LEFT: { + input_move_dir.x -= 1; + } break; + + case USER_BIND_KIND_MOVE_RIGHT: { + input_move_dir.x += 1; + } break; + + default: break; + } + } + + input_move_dir = xform_basis_invert_mul_v2(L.world_view, input_move_dir); /* Make move dir relative to world view */ + input_move_dir = v2_norm(input_move_dir); + } + + /* Aim */ + struct v2 input_aim = player->player_aim; + if (!L.debug_camera) { + input_aim = v2_sub(L.world_cursor, player->world_xform.og); + } + + /* Queue cmd */ + struct game_cmd movement_cmd = (struct game_cmd) { + .kind = GAME_CMD_KIND_PLAYER_MOVE, + .move_dir = input_move_dir, + .aim = input_aim + }; + queue_game_cmd(&cmd_list, movement_cmd); + /* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */ diff --git a/src/world.h b/src/world.h index 58c4999a..f96c7a5a 100644 --- a/src/world.h +++ b/src/world.h @@ -12,8 +12,8 @@ struct world { f64 dt; f64 time; - struct v2 player_move_dir; /* Player movement direction */ - struct v2 player_focus_move_dir; /* Focus movement direction */ + struct v2 player_move_dir; + struct v2 player_aim; struct entity_store entity_store; };