use cursor position as aim direction
This commit is contained in:
parent
39f7b09036
commit
744a6f8d65
@ -28,5 +28,3 @@
|
||||
|
||||
#define AUDIO_ENABLED 0
|
||||
#define VSYNC_ENABLED 0
|
||||
|
||||
#define MOUSE_SENSITIVITY 1
|
||||
|
||||
@ -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 */
|
||||
|
||||
33
src/game.c
33
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 */
|
||||
|
||||
@ -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 {
|
||||
|
||||
207
src/user.c
207
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);
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user