equip/fire beginnings. player input cmd change.
This commit is contained in:
parent
eb3c59ac13
commit
f5400b0205
21
src/entity.h
21
src/entity.h
@ -12,6 +12,11 @@ enum entity_prop {
|
|||||||
ENTITY_PROP_CAMERA,
|
ENTITY_PROP_CAMERA,
|
||||||
ENTITY_PROP_CAMERA_ACTIVE,
|
ENTITY_PROP_CAMERA_ACTIVE,
|
||||||
|
|
||||||
|
ENTITY_PROP_EQUIPPER,
|
||||||
|
ENTITY_PROP_EQUIPABLE,
|
||||||
|
|
||||||
|
ENTITY_PROP_FIRING_EQUIPPED,
|
||||||
|
|
||||||
/* Test props */
|
/* Test props */
|
||||||
|
|
||||||
ENTITY_PROP_TEST,
|
ENTITY_PROP_TEST,
|
||||||
@ -58,17 +63,26 @@ struct entity {
|
|||||||
struct entity_handle last;
|
struct entity_handle last;
|
||||||
|
|
||||||
/* ====================================================================== */
|
/* ====================================================================== */
|
||||||
|
/* Position */
|
||||||
|
|
||||||
|
/* Access with xform getters/setters */
|
||||||
struct xform local_xform; /* Transform in relation to parent entity (or the world if entity has no parent) */
|
struct xform local_xform; /* Transform in relation to parent entity (or the world if entity has no parent) */
|
||||||
struct xform cached_global_xform; /* Calculated from entity tree */
|
struct xform cached_global_xform; /* Calculated from entity tree */
|
||||||
b32 cached_global_xform_dirty;
|
b32 cached_global_xform_dirty;
|
||||||
|
|
||||||
|
/* ====================================================================== */
|
||||||
|
/* Control */
|
||||||
|
|
||||||
|
struct {
|
||||||
|
struct v2 move;
|
||||||
|
struct v2 focus;
|
||||||
|
} control;
|
||||||
|
|
||||||
/* ====================================================================== */
|
/* ====================================================================== */
|
||||||
/* Physics */
|
/* Physics */
|
||||||
|
|
||||||
struct v2 acceleration;
|
struct v2 acceleration;
|
||||||
struct v2 velocity;
|
struct v2 velocity;
|
||||||
struct v2 focus; /* Focus is a vector relative to the entity */
|
|
||||||
|
|
||||||
/* ENTITY_PROP_PLAYER_CONTROLLED */
|
/* ENTITY_PROP_PLAYER_CONTROLLED */
|
||||||
f32 player_max_speed;
|
f32 player_max_speed;
|
||||||
@ -90,6 +104,11 @@ struct entity {
|
|||||||
f64 animation_time_in_frame;
|
f64 animation_time_in_frame;
|
||||||
u32 animation_frame;
|
u32 animation_frame;
|
||||||
|
|
||||||
|
/* ====================================================================== */
|
||||||
|
/* Equip */
|
||||||
|
|
||||||
|
struct entity_handle equipped;
|
||||||
|
|
||||||
/* ====================================================================== */
|
/* ====================================================================== */
|
||||||
/* Testing */
|
/* Testing */
|
||||||
|
|
||||||
|
|||||||
146
src/game.c
146
src/game.c
@ -121,9 +121,10 @@ INTERNAL void spawn_test_entities(void)
|
|||||||
entity_enable_prop(e, ENTITY_PROP_PLAYER_CONTROLLED);
|
entity_enable_prop(e, ENTITY_PROP_PLAYER_CONTROLLED);
|
||||||
e->player_max_speed = 4.f;
|
e->player_max_speed = 4.f;
|
||||||
e->player_acceleration = 20.0f;
|
e->player_acceleration = 20.0f;
|
||||||
e->focus = V2(0, -1);
|
e->control.focus = V2(0, -1);
|
||||||
|
|
||||||
entity_enable_prop(e, ENTITY_PROP_ANIMATING);
|
entity_enable_prop(e, ENTITY_PROP_ANIMATING);
|
||||||
|
entity_enable_prop(e, ENTITY_PROP_EQUIPPER);
|
||||||
|
|
||||||
player_ent = e;
|
player_ent = e;
|
||||||
|
|
||||||
@ -132,41 +133,21 @@ INTERNAL void spawn_test_entities(void)
|
|||||||
|
|
||||||
/* Child 1 */
|
/* Child 1 */
|
||||||
{
|
{
|
||||||
struct v2 pos = V2(0.15, -0.05);
|
struct v2 pos = V2(1, -1);
|
||||||
struct v2 size = V2(1, 1);
|
struct v2 size = V2(1, 1);
|
||||||
f32 r = 0;
|
f32 r = 0;
|
||||||
|
|
||||||
struct xform xf = XFORM_TRS(.t = pos, .r = r, .s = size);
|
struct xform xf = XFORM_TRS(.t = pos, .r = r, .s = size);
|
||||||
|
|
||||||
struct entity *e = entity_alloc_child(player_ent);
|
struct entity *e = entity_alloc_top(G.world.entity_store);
|
||||||
entity_set_local_xform(e, xf);
|
entity_set_local_xform(e, xf);
|
||||||
|
|
||||||
e->sprite = sprite_tag_from_path(STR("res/graphics/gun.ase"));
|
e->sprite = sprite_tag_from_path(STR("res/graphics/gun.ase"));
|
||||||
//e->sprite_tint = RGBA_32_F(0, 0, 0, 1);
|
|
||||||
|
|
||||||
entity_enable_prop(e, ENTITY_PROP_ANIMATING);
|
entity_enable_prop(e, ENTITY_PROP_ANIMATING);
|
||||||
|
|
||||||
entity_enable_prop(e, ENTITY_PROP_PLAYER_CONTROLLED);
|
entity_enable_prop(e, ENTITY_PROP_EQUIPABLE);
|
||||||
}
|
player_ent->equipped = e->handle;
|
||||||
|
|
||||||
/* Child 2 */
|
|
||||||
{
|
|
||||||
struct v2 pos = V2(-0.15, -0.05);
|
|
||||||
struct v2 size = V2(-0.25, 0.5);
|
|
||||||
f32 r = 0;
|
|
||||||
|
|
||||||
struct xform xf = XFORM_TRS(.t = pos, .r = r, .s = size);
|
|
||||||
|
|
||||||
struct entity *e = entity_alloc_child(player_ent);
|
|
||||||
entity_set_local_xform(e, xf);
|
|
||||||
|
|
||||||
e->sprite = sprite_tag_from_path(STR("res/graphics/tim.ase"));
|
|
||||||
e->sprite_span_name = STR("idle.two_handed");
|
|
||||||
e->sprite_tint = RGBA_32_F(0, 0, 0, 1);
|
|
||||||
|
|
||||||
entity_enable_prop(e, ENTITY_PROP_ANIMATING);
|
|
||||||
|
|
||||||
entity_enable_prop(e, ENTITY_PROP_PLAYER_CONTROLLED);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Camera ent */
|
/* Camera ent */
|
||||||
@ -203,10 +184,8 @@ INTERNAL void game_update(void)
|
|||||||
|
|
||||||
struct temp_arena scratch = scratch_begin_no_conflict();
|
struct temp_arena scratch = scratch_begin_no_conflict();
|
||||||
|
|
||||||
struct entity_store *store = G.world.entity_store;
|
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Begin frame cache scopes
|
* Begin frame
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct sprite_scope *sprite_frame_scope = sprite_scope_begin();
|
struct sprite_scope *sprite_frame_scope = sprite_scope_begin();
|
||||||
@ -225,23 +204,20 @@ INTERNAL void game_update(void)
|
|||||||
G.world.time += G.world.dt;
|
G.world.time += G.world.dt;
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Process game cmds
|
* Pull cmds
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
|
struct entity_store *store = G.world.entity_store;
|
||||||
struct game_cmd_array game_cmds = pop_cmds(scratch.arena);
|
struct game_cmd_array game_cmds = pop_cmds(scratch.arena);
|
||||||
|
|
||||||
|
/* ========================== *
|
||||||
|
* Pre-sim game cmds
|
||||||
|
* ========================== */
|
||||||
|
|
||||||
for (u64 cmd_index = 0; cmd_index < game_cmds.count; ++cmd_index) {
|
for (u64 cmd_index = 0; cmd_index < game_cmds.count; ++cmd_index) {
|
||||||
struct game_cmd cmd = game_cmds.cmds[cmd_index];
|
struct game_cmd cmd = game_cmds.cmds[cmd_index];
|
||||||
|
|
||||||
switch (cmd.kind) {
|
switch (cmd.kind) {
|
||||||
/* Movement */
|
|
||||||
case GAME_CMD_KIND_PLAYER_MOVE: {
|
|
||||||
G.world.player_move_dir = cmd.move_dir;
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case GAME_CMD_KIND_PLAYER_AIM: {
|
|
||||||
G.world.camera_focus = cmd.aim;
|
|
||||||
} break;
|
|
||||||
|
|
||||||
/* Clear level */
|
/* Clear level */
|
||||||
case GAME_CMD_KIND_CLEAR_ALL: {
|
case GAME_CMD_KIND_CLEAR_ALL: {
|
||||||
logf_info("Clearing level");
|
logf_info("Clearing level");
|
||||||
@ -263,11 +239,6 @@ INTERNAL void game_update(void)
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (v2_len(G.world.player_move_dir) > 1.f) {
|
|
||||||
/* Clamp movement magnitude */
|
|
||||||
G.world.player_move_dir = v2_norm(G.world.player_move_dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
@ -284,7 +255,7 @@ INTERNAL void game_update(void)
|
|||||||
if (sprite_tag_is_nil(ent->sprite)) continue;
|
if (sprite_tag_is_nil(ent->sprite)) continue;
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Update animation
|
* Update sprite animation
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
if (entity_has_prop(ent, ENTITY_PROP_ANIMATING)) {
|
if (entity_has_prop(ent, ENTITY_PROP_ANIMATING)) {
|
||||||
@ -332,31 +303,15 @@ INTERNAL void game_update(void)
|
|||||||
|
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Update entities pre-physics
|
* Update entities pre-simulation
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
/* Find active camera */
|
|
||||||
struct entity *active_camera;
|
|
||||||
{
|
|
||||||
enum entity_prop props[] = { ENTITY_PROP_CAMERA, ENTITY_PROP_CAMERA_ACTIVE };
|
|
||||||
active_camera = entity_find_first_match_all(store, (struct entity_prop_array) { .count = ARRAY_COUNT(props), .props = props });
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Update camera focus */
|
|
||||||
if (active_camera->valid) {
|
|
||||||
active_camera->focus = G.world.camera_focus;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Calculate player aim pos from camera focus */
|
|
||||||
struct v2 player_aim_pos = v2_add(entity_get_xform(active_camera).og, G.world.camera_focus);
|
|
||||||
(UNUSED)player_aim_pos;
|
|
||||||
|
|
||||||
for (u64 entity_index = 0; entity_index < entities_array.count; ++entity_index) {
|
for (u64 entity_index = 0; entity_index < entities_array.count; ++entity_index) {
|
||||||
struct entity *ent = &entities_array.entities[entity_index];
|
struct entity *ent = &entities_array.entities[entity_index];
|
||||||
if (!ent->valid) continue;
|
if (!ent->valid) continue;
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Initialize
|
* Initialize test
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
/* ENTITY_PROP_TEST */
|
/* ENTITY_PROP_TEST */
|
||||||
@ -367,15 +322,50 @@ INTERNAL void game_update(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Calculate player aim angle
|
* Update control from player cmds
|
||||||
|
* ========================== */
|
||||||
|
|
||||||
|
if (entity_has_prop(ent, ENTITY_PROP_PLAYER_CONTROLLED)) {
|
||||||
|
for (u64 i = 0; i < game_cmds.count; ++i) {
|
||||||
|
struct game_cmd cmd = game_cmds.cmds[i];
|
||||||
|
b32 start = cmd.state == 1;
|
||||||
|
b32 stop = cmd.state == -1;
|
||||||
|
|
||||||
|
/* TODO: Combine movement from multiple inputs? E.G. a sudden
|
||||||
|
* start and immediate stop cmd should still move the player a
|
||||||
|
* tad. */
|
||||||
|
|
||||||
|
switch (cmd.kind) {
|
||||||
|
case GAME_CMD_KIND_PLAYER_MOVE: {
|
||||||
|
struct v2 move = cmd.move_dir;
|
||||||
|
if (v2_len_squared(move) > 1) {
|
||||||
|
/* Cap movement vector magnitude at 1 */
|
||||||
|
move = v2_norm(move);
|
||||||
|
}
|
||||||
|
ent->control.move = move;
|
||||||
|
ent->control.focus = v2_sub(cmd.aim_pos, entity_get_xform(ent).og);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case GAME_CMD_KIND_PLAYER_FIRE: {
|
||||||
|
if (start) {
|
||||||
|
entity_enable_prop(ent, ENTITY_PROP_FIRING_EQUIPPED);
|
||||||
|
} else if (stop) {
|
||||||
|
entity_disable_prop(ent, ENTITY_PROP_FIRING_EQUIPPED);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========================== *
|
||||||
|
* Update player angle
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
if (entity_has_prop(ent, ENTITY_PROP_PLAYER_CONTROLLED)) {
|
if (entity_has_prop(ent, ENTITY_PROP_PLAYER_CONTROLLED)) {
|
||||||
struct xform xf = entity_get_xform(ent);
|
struct xform xf = entity_get_xform(ent);
|
||||||
|
|
||||||
/* Update focus */
|
|
||||||
ent->focus = v2_sub(player_aim_pos, xf.og);
|
|
||||||
|
|
||||||
/* Solve for final angle using law of sines */
|
/* Solve for final angle using law of sines */
|
||||||
f32 final_xf_angle;
|
f32 final_xf_angle;
|
||||||
{
|
{
|
||||||
@ -390,7 +380,7 @@ INTERNAL void game_update(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct v2 ent_pos = xf.og;
|
struct v2 ent_pos = xf.og;
|
||||||
struct v2 focus_pos = v2_add(ent_pos, ent->focus);
|
struct v2 focus_pos = v2_add(ent_pos, ent->control.focus);
|
||||||
|
|
||||||
struct v2 hold_pos;
|
struct v2 hold_pos;
|
||||||
{
|
{
|
||||||
@ -451,10 +441,22 @@ INTERNAL void game_update(void)
|
|||||||
xf= xform_with_scale(xf, s);
|
xf= xform_with_scale(xf, s);
|
||||||
entity_set_local_xform(ent, xf);
|
entity_set_local_xform(ent, xf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ENTITY_PROP_FIRING_EQUIPPED */
|
||||||
|
{
|
||||||
|
struct entity *eq = entity_from_handle(store, ent->equipped);
|
||||||
|
if (eq->valid) {
|
||||||
|
if (entity_has_prop(ent, ENTITY_PROP_FIRING_EQUIPPED)) {
|
||||||
|
eq->sprite_tint = RGBA_32_F(1, 0, 0, 1);
|
||||||
|
} else {
|
||||||
|
eq->sprite_tint = RGBA_32_F(1, 1, 1, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Update entity physics
|
* Simulate entities
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
for (u64 entity_index = 0; entity_index < entities_array.count; ++entity_index) {
|
for (u64 entity_index = 0; entity_index < entities_array.count; ++entity_index) {
|
||||||
@ -462,14 +464,14 @@ INTERNAL void game_update(void)
|
|||||||
if (!ent->valid) continue;
|
if (!ent->valid) continue;
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Player movement
|
* Player control
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
if (entity_has_prop(ent, ENTITY_PROP_PLAYER_CONTROLLED)) {
|
if (entity_has_prop(ent, ENTITY_PROP_PLAYER_CONTROLLED)) {
|
||||||
f32 max_speed = ent->player_max_speed;
|
f32 max_speed = ent->player_max_speed;
|
||||||
f32 acceleration_rate = ent->player_acceleration;
|
f32 acceleration_rate = ent->player_acceleration;
|
||||||
acceleration_rate = clamp_f32(acceleration_rate, 0, GAME_FPS); /* Can't integrate acceleration rate higher than FPS */
|
acceleration_rate = clamp_f32(acceleration_rate, 0, GAME_FPS); /* Can't integrate acceleration rate higher than FPS */
|
||||||
struct v2 target_velocity = v2_mul(G.world.player_move_dir, max_speed);
|
struct v2 target_velocity = v2_mul(ent->control.move, max_speed);
|
||||||
struct v2 target_acceleration = v2_sub(target_velocity, ent->velocity);
|
struct v2 target_acceleration = v2_sub(target_velocity, ent->velocity);
|
||||||
ent->acceleration = v2_mul(target_acceleration, acceleration_rate);
|
ent->acceleration = v2_mul(target_acceleration, acceleration_rate);
|
||||||
}
|
}
|
||||||
@ -493,7 +495,7 @@ INTERNAL void game_update(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Update entities post-physics
|
* Update entities post-simulation
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
for (u64 entity_index = 0; entity_index < entities_array.count; ++entity_index) {
|
for (u64 entity_index = 0; entity_index < entities_array.count; ++entity_index) {
|
||||||
@ -521,7 +523,7 @@ INTERNAL void game_update(void)
|
|||||||
}
|
}
|
||||||
f32 ratio_y = 0.33f;
|
f32 ratio_y = 0.33f;
|
||||||
f32 ratio_x = ratio_y / aspect_ratio;
|
f32 ratio_x = ratio_y / aspect_ratio;
|
||||||
struct v2 camera_focus_dir = v2_mul_v2(follow->focus, V2(ratio_x, ratio_y));
|
struct v2 camera_focus_dir = v2_mul_v2(follow->control.focus, V2(ratio_x, ratio_y));
|
||||||
struct v2 camera_focus_pos = v2_add(entity_get_xform(follow).og, camera_focus_dir);
|
struct v2 camera_focus_pos = v2_add(entity_get_xform(follow).og, camera_focus_dir);
|
||||||
ent->camera_xform_target = xf;
|
ent->camera_xform_target = xf;
|
||||||
ent->camera_xform_target.og = camera_focus_pos;
|
ent->camera_xform_target.og = camera_focus_pos;
|
||||||
|
|||||||
@ -10,7 +10,7 @@ enum game_cmd_kind {
|
|||||||
GAME_CMD_KIND_NONE,
|
GAME_CMD_KIND_NONE,
|
||||||
|
|
||||||
GAME_CMD_KIND_PLAYER_MOVE,
|
GAME_CMD_KIND_PLAYER_MOVE,
|
||||||
GAME_CMD_KIND_PLAYER_AIM,
|
GAME_CMD_KIND_PLAYER_FIRE,
|
||||||
|
|
||||||
/* Testing */
|
/* Testing */
|
||||||
GAME_CMD_KIND_CLEAR_ALL,
|
GAME_CMD_KIND_CLEAR_ALL,
|
||||||
@ -22,11 +22,12 @@ enum game_cmd_kind {
|
|||||||
struct game_cmd {
|
struct game_cmd {
|
||||||
enum game_cmd_kind kind;
|
enum game_cmd_kind kind;
|
||||||
|
|
||||||
|
/* 1 = start, -1 = stop */
|
||||||
|
i32 state;
|
||||||
|
|
||||||
/* GAME_CMD_KIND_PLAYER_MOVE */
|
/* GAME_CMD_KIND_PLAYER_MOVE */
|
||||||
struct v2 move_dir;
|
struct v2 move_dir;
|
||||||
|
struct v2 aim_pos;
|
||||||
/* GAME_CMD_KIND_PLAYER_AIM */
|
|
||||||
struct v2 aim;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct game_cmd_array {
|
struct game_cmd_array {
|
||||||
|
|||||||
103
src/user.c
103
src/user.c
@ -80,6 +80,7 @@ GLOBAL READONLY enum user_bind_kind g_binds[SYS_BTN_COUNT] = {
|
|||||||
[SYS_BTN_S] = USER_BIND_KIND_MOVE_DOWN,
|
[SYS_BTN_S] = USER_BIND_KIND_MOVE_DOWN,
|
||||||
[SYS_BTN_A] = USER_BIND_KIND_MOVE_LEFT,
|
[SYS_BTN_A] = USER_BIND_KIND_MOVE_LEFT,
|
||||||
[SYS_BTN_D] = USER_BIND_KIND_MOVE_RIGHT,
|
[SYS_BTN_D] = USER_BIND_KIND_MOVE_RIGHT,
|
||||||
|
[SYS_BTN_M1] = USER_BIND_KIND_FIRE,
|
||||||
|
|
||||||
/* Testing */
|
/* Testing */
|
||||||
|
|
||||||
@ -440,11 +441,13 @@ INTERNAL void user_update(void)
|
|||||||
tick_blend = clamp_f32(tick_blend, 0.0f, 1.0f);
|
tick_blend = clamp_f32(tick_blend, 0.0f, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TODO: Should we actually be basing interpolated tick on t1 rather
|
||||||
|
* than t0? This means un-interpolated values will use the newer frame's
|
||||||
|
* value, while still interpolating from the older frame. */
|
||||||
world_copy_replace(&G.world, t1);
|
world_copy_replace(&G.world, t1);
|
||||||
|
|
||||||
/* Blend world globals */
|
/* Blend world globals */
|
||||||
G.world.time = math_lerp64(t0->time, t1->time, (f64)tick_blend);
|
G.world.time = math_lerp64(t0->time, t1->time, (f64)tick_blend);
|
||||||
G.world.camera_focus = v2_lerp(t0->camera_focus, t1->camera_focus, tick_blend);
|
|
||||||
|
|
||||||
/* Blend entities */
|
/* Blend entities */
|
||||||
struct entity_array t0_entities = entity_store_as_array(t0->entity_store);
|
struct entity_array t0_entities = entity_store_as_array(t0->entity_store);
|
||||||
@ -466,7 +469,9 @@ INTERNAL void user_update(void)
|
|||||||
e->acceleration = v2_lerp(e0->acceleration, e1->acceleration, tick_blend);
|
e->acceleration = v2_lerp(e0->acceleration, e1->acceleration, tick_blend);
|
||||||
e->velocity = v2_lerp(e0->velocity, e1->velocity, 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_acceleration = math_lerp(e0->player_acceleration, e1->player_acceleration, tick_blend);
|
||||||
e->focus = v2_lerp(e0->focus, e1->focus, tick_blend);
|
|
||||||
|
e->control.move = v2_lerp(e0->control.move, e1->control.move, tick_blend);
|
||||||
|
e->control.focus = v2_lerp(e0->control.focus, e1->control.focus, tick_blend);
|
||||||
|
|
||||||
e->sprite_local_xform = xform_lerp(e0->sprite_local_xform, e1->sprite_local_xform, tick_blend);
|
e->sprite_local_xform = xform_lerp(e0->sprite_local_xform, e1->sprite_local_xform, tick_blend);
|
||||||
e->animation_time_in_frame = math_lerp64(e0->animation_time_in_frame, e1->animation_time_in_frame, (f64)tick_blend);
|
e->animation_time_in_frame = math_lerp64(e0->animation_time_in_frame, e1->animation_time_in_frame, (f64)tick_blend);
|
||||||
@ -848,13 +853,13 @@ INTERNAL void user_update(void)
|
|||||||
debug_draw_xform(xf);
|
debug_draw_xform(xf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Draw aim arrow */
|
/* Draw focus arrow */
|
||||||
if (entity_has_prop(ent, ENTITY_PROP_PLAYER_CONTROLLED)) {
|
if (entity_has_prop(ent, ENTITY_PROP_PLAYER_CONTROLLED)) {
|
||||||
struct sprite_sheet *sheet = sprite_sheet_from_tag_async(sprite_frame_scope, ent->sprite);
|
struct sprite_sheet *sheet = sprite_sheet_from_tag_async(sprite_frame_scope, ent->sprite);
|
||||||
struct sprite_sheet_slice slice = sprite_sheet_get_slice(sheet, STR("hold"), ent->animation_frame);
|
struct sprite_sheet_slice slice = sprite_sheet_get_slice(sheet, STR("hold"), ent->animation_frame);
|
||||||
struct v2 start = xform_mul_v2(sprite_xform, slice.center);
|
struct v2 start = xform_mul_v2(sprite_xform, slice.center);
|
||||||
start = xform_mul_v2(G.world_view, start);
|
start = xform_mul_v2(G.world_view, start);
|
||||||
struct v2 end = v2_add(xf.og, ent->focus);
|
struct v2 end = v2_add(xf.og, ent->control.focus);
|
||||||
end = xform_mul_v2(G.world_view, end);
|
end = xform_mul_v2(G.world_view, end);
|
||||||
draw_solid_arrow_line(G.viewport_canvas, start, end, 3, 10, RGBA_32_F(1, 1, 1, 0.5));
|
draw_solid_arrow_line(G.viewport_canvas, start, end, 3, 10, RGBA_32_F(1, 1, 1, 0.5));
|
||||||
}
|
}
|
||||||
@ -946,58 +951,66 @@ INTERNAL void user_update(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Construct movement input
|
* Construct player control cmd
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
/* Movement */
|
/* Movement */
|
||||||
struct v2 input_move_dir = { 0 };
|
|
||||||
{
|
{
|
||||||
for (enum user_bind_kind bind = 0; bind < (i32)ARRAY_COUNT(G.bind_states); ++bind) {
|
struct v2 input_move_dir = { 0 };
|
||||||
struct bind_state state = G.bind_states[bind];
|
{
|
||||||
|
for (enum user_bind_kind bind = 0; bind < (i32)ARRAY_COUNT(G.bind_states); ++bind) {
|
||||||
|
struct bind_state state = G.bind_states[bind];
|
||||||
|
|
||||||
if (!state.is_held && state.num_presses <= 0) {
|
if (!state.is_held && state.num_presses <= 0) {
|
||||||
continue;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (bind) {
|
input_move_dir = xform_basis_invert_mul_v2(G.world_view, input_move_dir); /* Make move dir relative to world view */
|
||||||
/* Movement */
|
input_move_dir = v2_norm(input_move_dir);
|
||||||
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(G.world_view, input_move_dir); /* Make move dir relative to world view */
|
struct v2 input_aim_pos = G.world_cursor;
|
||||||
input_move_dir = v2_norm(input_move_dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Queue move cmd */
|
i32 cmd_fire = (G.bind_states[USER_BIND_KIND_FIRE].num_presses > 0 || G.bind_states[USER_BIND_KIND_FIRE].is_held) ? 1 : -1;
|
||||||
queue_game_cmd(&cmd_list, (struct game_cmd) {
|
|
||||||
.kind = GAME_CMD_KIND_PLAYER_MOVE,
|
|
||||||
.move_dir = input_move_dir,
|
|
||||||
});
|
|
||||||
|
|
||||||
/* Queue aim cmd */
|
if (!G.debug_camera) {
|
||||||
if (!G.debug_camera) {
|
/* Queue player move cmd */
|
||||||
struct v2 input_aim = v2_sub(G.world_cursor, entity_get_xform(active_camera).og);
|
queue_game_cmd(&cmd_list, (struct game_cmd) {
|
||||||
queue_game_cmd(&cmd_list, (struct game_cmd) {
|
.kind = GAME_CMD_KIND_PLAYER_MOVE,
|
||||||
.kind = GAME_CMD_KIND_PLAYER_AIM,
|
.move_dir = input_move_dir,
|
||||||
.aim = input_aim,
|
.aim_pos = input_aim_pos
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/* Queue player fire cmd */
|
||||||
|
if (cmd_fire) {
|
||||||
|
queue_game_cmd(&cmd_list, (struct game_cmd) {
|
||||||
|
.kind = GAME_CMD_KIND_PLAYER_FIRE,
|
||||||
|
.state = cmd_fire
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|||||||
@ -18,6 +18,7 @@ enum user_bind_kind {
|
|||||||
USER_BIND_KIND_MOVE_DOWN,
|
USER_BIND_KIND_MOVE_DOWN,
|
||||||
USER_BIND_KIND_MOVE_LEFT,
|
USER_BIND_KIND_MOVE_LEFT,
|
||||||
USER_BIND_KIND_MOVE_RIGHT,
|
USER_BIND_KIND_MOVE_RIGHT,
|
||||||
|
USER_BIND_KIND_FIRE,
|
||||||
|
|
||||||
/* Testing */
|
/* Testing */
|
||||||
|
|
||||||
|
|||||||
@ -12,9 +12,6 @@ struct world {
|
|||||||
f64 dt;
|
f64 dt;
|
||||||
f64 time;
|
f64 time;
|
||||||
|
|
||||||
struct v2 player_move_dir;
|
|
||||||
struct v2 camera_focus;
|
|
||||||
|
|
||||||
struct entity_store *entity_store;
|
struct entity_store *entity_store;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user