Talk while time is stopped, fix anim change when time stopped

main
parent 74247b2f30
commit 622380f077

133
main.c

@ -897,7 +897,7 @@ void init(void)
{ {
.usage = SG_USAGE_STREAM, .usage = SG_USAGE_STREAM,
//.data = SG_RANGE(vertices), //.data = SG_RANGE(vertices),
.size = 1024*500, .size = 1024*900,
.label = "quad-vertices" .label = "quad-vertices"
}); });
@ -2136,7 +2136,6 @@ void draw_dialog_panel(Entity *talking_to, float alpha)
dbgrect(dialog_panel); dbgrect(dialog_panel);
} }
} }
} }
#define ROLL_KEY SAPP_KEYCODE_LEFT_SHIFT #define ROLL_KEY SAPP_KEYCODE_LEFT_SHIFT
@ -2145,6 +2144,7 @@ double last_frame_processing_time = 0.0;
uint64_t last_frame_time; uint64_t last_frame_time;
Vec2 mouse_pos = {0}; // in screen space Vec2 mouse_pos = {0}; // in screen space
bool interact_just_pressed = false; bool interact_just_pressed = false;
bool mouse_just_clicked = false;
float learned_shift = 0.0; float learned_shift = 0.0;
float learned_space = 0.0; float learned_space = 0.0;
float learned_e = 0.0; float learned_e = 0.0;
@ -2155,16 +2155,17 @@ void frame(void)
{ {
static float speed_factor = 1.0f; static float speed_factor = 1.0f;
// elapsed_time // elapsed_time
double dt_double = 0.0; double unwarped_dt_double = 0.0;
{ {
dt_double = stm_sec(stm_diff(stm_now(), last_frame_time)); unwarped_dt_double = stm_sec(stm_diff(stm_now(), last_frame_time));
dt_double = fmin(dt_double, 5.0 / 60.0); // clamp dt at maximum 5 frames, avoid super huge dt unwarped_dt_double = fmin(unwarped_dt_double, MINIMUM_TIMESTEP * 5.0); // clamp dt at maximum 5 frames, avoid super huge dt
elapsed_time += dt_double*speed_factor; elapsed_time += unwarped_dt_double*speed_factor;
last_frame_time = stm_now(); last_frame_time = stm_now();
} }
double dt_double = unwarped_dt_double*speed_factor;
float unwarped_dt = (float)unwarped_dt_double;
float dt = (float)dt_double; float dt = (float)dt_double;
#if 0 #if 0
{ {
printf("Frametime: %.1f ms\n", dt*1000.0); printf("Frametime: %.1f ms\n", dt*1000.0);
@ -2330,23 +2331,31 @@ void frame(void)
static Entity *interacting_with = 0; // used by rendering to figure out who to draw dialog box on static Entity *interacting_with = 0; // used by rendering to figure out who to draw dialog box on
static bool player_in_combat = false; static bool player_in_combat = false;
const float dialog_interact_size = 2.5f * TILE_SIZE; const float dialog_interact_size = 2.5f * TILE_SIZE;
if(player->has_paused_time)
float speed_target;
if(player->in_conversation_mode)
{ {
speed_factor = Lerp(speed_factor, dt*10.0f, 0.0f); speed_target = 0.0f;
} }
else else
{ {
speed_factor = Lerp(speed_factor, dt*10.0f, 1.0f); speed_target = 1.0f;
}
speed_factor = Lerp(speed_factor, unwarped_dt*15.0f, speed_target);
if(fabsf(speed_factor - speed_target) <= 0.05f)
{
speed_factor = speed_target;
} }
int num_timestep_loops = 0; int num_timestep_loops = 0;
{ {
unprocessed_gameplay_time += dt; unprocessed_gameplay_time += unwarped_dt;
float timestep = fminf(dt, (float)MINIMUM_TIMESTEP); float timestep = fminf(unwarped_dt, (float)MINIMUM_TIMESTEP);
while(unprocessed_gameplay_time >= timestep) while(unprocessed_gameplay_time >= timestep)
{ {
num_timestep_loops++; num_timestep_loops++;
unprocessed_gameplay_time -= timestep; unprocessed_gameplay_time -= timestep;
float dt = timestep*speed_factor; float unwarped_dt = timestep;
float dt = unwarped_dt*speed_factor;
// process gs.entities // process gs.entities
player_in_combat = false; // in combat set by various enemies when they fight the player player_in_combat = false; // in combat set by various enemies when they fight the player
@ -2420,6 +2429,8 @@ void frame(void)
} }
} }
#endif #endif
if(fabsf(it->vel.x) > 0.01f) if(fabsf(it->vel.x) > 0.01f)
it->facing_left = it->vel.x < 0.0f; it->facing_left = it->vel.x < 0.0f;
@ -2428,6 +2439,21 @@ void frame(void)
it->dead_time += dt; it->dead_time += dt;
} }
it->being_hovered = false;
if(player->in_conversation_mode)
{
if(has_point(entity_aabb(it), screen_to_world(mouse_pos)))
{
it->being_hovered = true;
if(mouse_just_clicked)
{
player->talking_to = frome(it);
player->state = CHARACTER_TALKING;
}
}
}
if(it->is_npc) if(it->is_npc)
{ {
// character speech animation text input // character speech animation text input
@ -2440,7 +2466,7 @@ void frame(void)
if(last_said_sentence(it)) length = last_said_sentence(it)->cur_index; if(last_said_sentence(it)) length = last_said_sentence(it)->cur_index;
if((int)before < length) if((int)before < length)
{ {
it->characters_said += characters_per_sec*dt; it->characters_said += characters_per_sec*unwarped_dt;
} }
else else
{ {
@ -2763,6 +2789,7 @@ void frame(void)
PROFILE_SCOPE("process player") PROFILE_SCOPE("process player")
{ {
// do dialog // do dialog
Entity *closest_interact_with = 0; Entity *closest_interact_with = 0;
{ {
@ -2817,7 +2844,11 @@ void frame(void)
if(interact) if(interact)
{ {
if(closest_interact_with) if(player->in_conversation_mode)
{
player->in_conversation_mode = false;
}
else if(closest_interact_with)
{ {
if(closest_interact_with->is_npc) if(closest_interact_with->is_npc)
{ {
@ -2835,7 +2866,6 @@ void frame(void)
{ {
assert(false); assert(false);
} }
} }
else else
{ {
@ -2850,16 +2880,18 @@ void frame(void)
} }
else else
{ {
player->has_paused_time = !player->has_paused_time; player->in_conversation_mode = true;
} }
} }
} }
float speed = 0.0f;
{
if(roll && !player->is_rolling && player->time_not_rolling > 0.3f && (player->state == CHARACTER_IDLE || player->state == CHARACTER_WALKING)) if(roll && !player->is_rolling && player->time_not_rolling > 0.3f && (player->state == CHARACTER_IDLE || player->state == CHARACTER_WALKING))
{ {
player->is_rolling = true; player->is_rolling = true;
player->roll_progress = 0.0; player->roll_progress = 0.0;
} }
if(attack && (player->state == CHARACTER_IDLE || player->state == CHARACTER_WALKING)) if(attack && (player->state == CHARACTER_IDLE || player->state == CHARACTER_WALKING))
{ {
player->state = CHARACTER_ATTACK; player->state = CHARACTER_ATTACK;
@ -2897,7 +2929,6 @@ void frame(void)
} }
Vec2 target_vel = {0}; Vec2 target_vel = {0};
float speed = 0.0f;
if(LenV2(movement) > 0.01f) player->to_throw_direction = NormV2(movement); if(LenV2(movement) > 0.01f) player->to_throw_direction = NormV2(movement);
if(player->state == CHARACTER_WALKING) if(player->state == CHARACTER_WALKING)
@ -2944,6 +2975,7 @@ void frame(void)
{ {
assert(false); // unknown character state? not defined how to process assert(false); // unknown character state? not defined how to process
} }
} // not time stopped
// velocity processing // velocity processing
{ {
@ -2958,6 +2990,7 @@ void frame(void)
} }
} }
interact_just_pressed = false; interact_just_pressed = false;
mouse_just_clicked = false;
interact = false; interact = false;
} // while loop } // while loop
} }
@ -3023,6 +3056,14 @@ void frame(void)
draw_quad((DrawParams){false, (Quad){.ul=V2(0.0f, screen_size().Y), .ur = screen_size(), .lr = V2(screen_size().X, 0.0f)}, image_hurt_vignette, full_region(image_hurt_vignette), (Color){1.0f, 1.0f, 1.0f, player->damage}, .y_coord_sorting = Y_COORD_IN_FRONT, .queue_for_translucent = true}); draw_quad((DrawParams){false, (Quad){.ul=V2(0.0f, screen_size().Y), .ur = screen_size(), .lr = V2(screen_size().X, 0.0f)}, image_hurt_vignette, full_region(image_hurt_vignette), (Color){1.0f, 1.0f, 1.0f, player->damage}, .y_coord_sorting = Y_COORD_IN_FRONT, .queue_for_translucent = true});
} }
player->anim_change_timer += dt;
if(player->anim_change_timer >= 0.05f)
{
player->anim_change_timer = 0.0f;
player->cur_animation = to_draw.anim;
}
to_draw.anim = player->cur_animation;
Vec2 target_sprite_pos = to_draw.pos; Vec2 target_sprite_pos = to_draw.pos;
BUFF_ITER(PlayerAfterImage, &player->after_images) BUFF_ITER(PlayerAfterImage, &player->after_images)
{ {
@ -3069,38 +3110,6 @@ void frame(void)
} }
#endif #endif
// draw drop shadow
//if(it->is_character || it->is_npc || it->is_prop)
if(false)
{
//if(it->npc_kind != DEATH)
{
float shadow_size = GET_TABLE(sprites, ANIM_knight_rolling).region_size.x * 0.5f;
Vec2 shadow_offset = V2(0.0f, -20.0f);
if(npc_is_knight_sprite(it))
{
shadow_offset = V2(0.5f, -10.0f);
}
#if 0
if(it->npc_kind == MERCHANT)
{
shadow_offset = V2(-4.5f, -15.0f);
}
else if(it->npc_kind == OLD_MAN)
{
shadow_offset = V2(-1.5f, -8.0f);
shadow_size *= 0.5f;
}
#endif
if(it->is_prop)
{
shadow_size *= 2.5f;
shadow_offset = V2(-5.0f, -8.0f);
}
draw_quad((DrawParams){true, quad_centered(AddV2(it->pos, shadow_offset), V2(shadow_size, shadow_size)),IMG(image_drop_shadow), (Color){1.0f,1.0f,1.0f,0.5f}});
}
}
Color col = LerpV4(WHITE, it->damage, RED); Color col = LerpV4(WHITE, it->damage, RED);
if(it->is_npc) if(it->is_npc)
{ {
@ -3111,7 +3120,14 @@ void frame(void)
float max_dist = dialog_interact_size/2.0f; float max_dist = dialog_interact_size/2.0f;
float alpha = 1.0f - (float)clamp(dist/max_dist, 0.0, 1.0); float alpha = 1.0f - (float)clamp(dist/max_dist, 0.0, 1.0);
if(gete(player->talking_to) == it && player->state == CHARACTER_TALKING) alpha = 1.0f; if(gete(player->talking_to) == it && player->state == CHARACTER_TALKING) alpha = 1.0f;
draw_dialog_panel(it, alpha); if(it->being_hovered)
{
draw_quad((DrawParams){true, quad_centered(it->pos, V2(TILE_SIZE, TILE_SIZE)), IMG(image_hovering_circle), WHITE});
alpha = 1.0f;
}
it->dialog_panel_opacity = Lerp(it->dialog_panel_opacity, unwarped_dt*10.0f, alpha);
draw_dialog_panel(it, it->dialog_panel_opacity);
} }
if(it->npc_kind == NPC_OldMan) if(it->npc_kind == NPC_OldMan)
@ -3326,7 +3342,7 @@ void frame(void)
} }
else else
{ {
cam.pos = LerpV2(cam.pos, dt*8.0f, target); cam.pos = LerpV2(cam.pos, unwarped_dt*8.0f, target);
} }
} }
@ -3466,7 +3482,18 @@ void event(const sapp_event *e)
} }
} }
if(e->type == SAPP_EVENTTYPE_MOUSE_DOWN)
{
if(e->mouse_button == SAPP_MOUSEBUTTON_LEFT)
{
mouse_just_clicked = true;
}
}
if(e->type == SAPP_EVENTTYPE_KEY_DOWN) if(e->type == SAPP_EVENTTYPE_KEY_DOWN)
#ifdef DESKTOP
if(!receiving_text_input)
#endif
{ {
mobile_controls = false; mobile_controls = false;
assert(e->key_code < sizeof(keydown)/sizeof(*keydown)); assert(e->key_code < sizeof(keydown)/sizeof(*keydown));

@ -179,9 +179,11 @@ typedef struct Entity
// npcs // npcs
bool is_npc; bool is_npc;
bool being_hovered;
bool perceptions_dirty; bool perceptions_dirty;
BUFF(Perception, REMEMBERED_PERCEPTIONS) remembered_perceptions; BUFF(Perception, REMEMBERED_PERCEPTIONS) remembered_perceptions;
bool direction_of_spiral_pattern; bool direction_of_spiral_pattern;
float dialog_panel_opacity;
double characters_said; double characters_said;
NPCPlayerStanding standing; NPCPlayerStanding standing;
NpcKind npc_kind; NpcKind npc_kind;
@ -199,12 +201,18 @@ typedef struct Entity
// character // character
bool is_character; bool is_character;
EntityRef holding_item; EntityRef holding_item;
bool has_paused_time; bool in_conversation_mode;
Vec2 to_throw_direction; Vec2 to_throw_direction;
CharacterState state; CharacterState state;
EntityRef talking_to; // Maybe should be generational index, but I dunno. No death yet EntityRef talking_to; // Maybe should be generational index, but I dunno. No death yet
bool is_rolling; // can only roll in idle or walk states bool is_rolling; // can only roll in idle or walk states
double time_not_rolling; // for cooldown for roll, so you can't just hold it and be invincible double time_not_rolling; // for cooldown for roll, so you can't just hold it and be invincible
// so doesn't change animations while time is stopped
AnimKind cur_animation;
float anim_change_timer;
BUFF(PlayerAfterImage, MAX_AFTERIMAGES) after_images; BUFF(PlayerAfterImage, MAX_AFTERIMAGES) after_images;
double after_image_timer; double after_image_timer;
double roll_progress; double roll_progress;

Loading…
Cancel
Save