Revamp screen shake system (#225)
This commit is contained in:
parent
00e4837827
commit
7072fe447d
11 changed files with 88 additions and 95 deletions
25
src/boss.c
25
src/boss.c
|
@ -1050,20 +1050,18 @@ void process_boss(Boss **pboss) {
|
|||
float p = (boss->current->endtime - global.frames)/(float)ATTACK_END_DELAY_EXTRA;
|
||||
float a = fmax((base + ampl * s) * p * 0.5, 5 * pow(1 - p, 3));
|
||||
if(a < 2) {
|
||||
global.shake_view = 3 * a;
|
||||
stage_shake_view(3 * a);
|
||||
boss_rule_extra(boss, a);
|
||||
if(a > 1) {
|
||||
boss_rule_extra(boss, a * 0.5);
|
||||
if(a > 1.3) {
|
||||
global.shake_view = 5 * a;
|
||||
stage_shake_view(5 * a);
|
||||
if(a > 1.7)
|
||||
global.shake_view += 2 * a;
|
||||
stage_shake_view(2 * a);
|
||||
boss_rule_extra(boss, 0);
|
||||
boss_rule_extra(boss, 0.1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
global.shake_view_fade = 0.15;
|
||||
}
|
||||
} else if(time < 0) {
|
||||
boss_rule_extra(boss, 1+time/(float)ATTACK_START_DELAY_EXTRA);
|
||||
|
@ -1074,12 +1072,10 @@ void process_boss(Boss **pboss) {
|
|||
boss_rule_extra(boss, fmax(1-time/300.0, base + ampl * s) * q);
|
||||
if(o) {
|
||||
boss_rule_extra(boss, fmax(1-time/300.0, base + ampl * s) - o);
|
||||
if(!global.shake_view) {
|
||||
global.shake_view = 5;
|
||||
global.shake_view_fade = 0.9;
|
||||
} else if(o > -0.05) {
|
||||
global.shake_view = 10;
|
||||
global.shake_view_fade = 0.5;
|
||||
|
||||
stage_shake_view(5);
|
||||
if(o > -0.05) {
|
||||
stage_shake_view(10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1131,11 +1127,7 @@ void process_boss(Boss **pboss) {
|
|||
);
|
||||
|
||||
if(!extra) {
|
||||
if(t == 1) {
|
||||
global.shake_view_fade = 0.2;
|
||||
} else {
|
||||
global.shake_view = 5 * (t + t*t + t*t*t);
|
||||
}
|
||||
stage_shake_view(5 * (t + t*t + t*t*t));
|
||||
}
|
||||
|
||||
if(t == 1) {
|
||||
|
@ -1277,6 +1269,7 @@ void boss_death(Boss **boss) {
|
|||
|
||||
if(!fleed) {
|
||||
stage_clear_hazards(CLEAR_HAZARDS_ALL | CLEAR_HAZARDS_FORCE);
|
||||
stage_shake_view(100);
|
||||
|
||||
PARTICLE(
|
||||
.pos = (*boss)->pos,
|
||||
|
|
|
@ -126,9 +126,6 @@ typedef struct {
|
|||
ReplayMode replaymode;
|
||||
ReplayStage *replay_stage;
|
||||
|
||||
float shake_view;
|
||||
float shake_view_fade;
|
||||
|
||||
uint voltage_threshold;
|
||||
|
||||
RandomState rand_game;
|
||||
|
|
|
@ -533,11 +533,11 @@ TASK(marisa_laser_masterspark, { MarisaAController *ctrl; }) {
|
|||
marisa_laser_masterspark_damage(ms);
|
||||
|
||||
if(bomb_progress >= 3.0/4.0) {
|
||||
global.shake_view = 8 * (1 - bomb_progress * 4 + 3);
|
||||
stage_shake_view(8 * (1 - bomb_progress * 4 + 3));
|
||||
goto skip_particles;
|
||||
}
|
||||
|
||||
global.shake_view = 8;
|
||||
stage_shake_view(8);
|
||||
|
||||
uint pflags = PFLAG_NOREFLECT | PFLAG_MANUALANGLE;
|
||||
|
||||
|
@ -581,8 +581,6 @@ skip_particles:
|
|||
YIELD;
|
||||
} while(player_is_bomb_active(plr));
|
||||
|
||||
global.shake_view = 0;
|
||||
|
||||
while(ms->alpha > 0) {
|
||||
approach_p(&ms->alpha, 0, 0.2);
|
||||
YIELD;
|
||||
|
|
|
@ -436,7 +436,7 @@ TASK(marisa_star_bomb_controller, { MarisaBController *ctrl; }) {
|
|||
}
|
||||
|
||||
do {
|
||||
global.shake_view = fmax(8, global.shake_view);
|
||||
stage_shake_view(8);
|
||||
player_placeholder_bomb_logic(plr);
|
||||
|
||||
float tb = player_get_bomb_progress(plr);
|
||||
|
@ -457,8 +457,6 @@ TASK(marisa_star_bomb_controller, { MarisaBController *ctrl; }) {
|
|||
++beams->time;
|
||||
YIELD;
|
||||
} while(player_is_bomb_active(plr));
|
||||
|
||||
global.shake_view = 0;
|
||||
}
|
||||
|
||||
TASK(marisa_star_bomb_handler, { MarisaBController *ctrl; }) {
|
||||
|
|
|
@ -217,8 +217,7 @@ TASK(reimu_spirit_bomb_orb_impact, { BoxedProjectile orb; }) {
|
|||
play_sound("boom");
|
||||
play_sound("spellend");
|
||||
|
||||
global.shake_view = 20;
|
||||
global.shake_view_fade = 0.6;
|
||||
stage_shake_view(200);
|
||||
|
||||
real damage = 2000;
|
||||
real range = 300;
|
||||
|
@ -429,7 +428,6 @@ TASK(reimu_spirit_bomb_handler, { ReimuAController *ctrl; }) {
|
|||
WAIT_EVENT_OR_DIE(&plr->events.bomb_used);
|
||||
INVOKE_SUBTASK(reimu_spirit_bomb_background, ctrl);
|
||||
|
||||
global.shake_view = 4;
|
||||
play_sound("bomb_reimu_a");
|
||||
play_sound("bomb_marisa_b");
|
||||
|
||||
|
|
|
@ -171,7 +171,7 @@ TASK(reimu_dream_bomb_barrage, { ReimuBController *ctrl; }) {
|
|||
);
|
||||
}
|
||||
|
||||
global.shake_view += 6;
|
||||
stage_shake_view(4);
|
||||
t += WAIT(BOMB_PROJECTILE_FIRE_DELAY);
|
||||
} while(player_is_bomb_active(plr));
|
||||
}
|
||||
|
@ -611,7 +611,7 @@ TASK(reimu_dream_controller_tick, { ReimuBController *ctrl; }) {
|
|||
|
||||
for(;;) {
|
||||
if(player_is_bomb_active(plr)) {
|
||||
global.shake_view_fade = fmax(global.shake_view_fade, 2);
|
||||
stage_shake_view(1);
|
||||
approach_p(&ctrl->bomb_alpha, 1.0, 0.1);
|
||||
} else {
|
||||
approach_p(&ctrl->bomb_alpha, 0.0, 0.025);
|
||||
|
|
40
src/stage.c
40
src/stage.c
|
@ -31,7 +31,6 @@ static void stage_start(StageInfo *stage) {
|
|||
global.timer = 0;
|
||||
global.frames = 0;
|
||||
global.gameover = 0;
|
||||
global.shake_view = 0;
|
||||
global.voltage_threshold = 0;
|
||||
|
||||
player_stage_pre_init(&global.plr);
|
||||
|
@ -579,8 +578,11 @@ typedef struct StageFrameState {
|
|||
int transition_delay;
|
||||
int logic_calls;
|
||||
uint16_t last_replay_fps;
|
||||
float view_shake;
|
||||
} StageFrameState;
|
||||
|
||||
static StageFrameState *_current_stage_state; // TODO remove this shitty hack
|
||||
|
||||
static void stage_update_fps(StageFrameState *fstate) {
|
||||
if(global.replaymode == REPLAY_RECORD) {
|
||||
uint16_t replay_fps = (uint16_t)rint(global.fps.logic.fps);
|
||||
|
@ -638,17 +640,8 @@ static LogicFrameAction stage_logic_frame(void *arg) {
|
|||
global.plr.iddqd = true;
|
||||
}
|
||||
|
||||
if(global.shake_view > 30) {
|
||||
global.shake_view = 30;
|
||||
}
|
||||
|
||||
if(global.shake_view_fade) {
|
||||
global.shake_view -= global.shake_view_fade;
|
||||
|
||||
if(global.shake_view <= 0) {
|
||||
global.shake_view = global.shake_view_fade = 0;
|
||||
}
|
||||
}
|
||||
fapproach_p(&fstate->view_shake, 0, 1);
|
||||
fapproach_asymptotic_p(&fstate->view_shake, 0, 0.05, 1e-2);
|
||||
|
||||
((global.replaymode == REPLAY_PLAY) ? replay_input : stage_input)();
|
||||
|
||||
|
@ -688,6 +681,7 @@ static LogicFrameAction stage_logic_frame(void *arg) {
|
|||
}
|
||||
|
||||
if(global.gameover > 0) {
|
||||
log_warn("RESTART");
|
||||
return LFRAME_STOP;
|
||||
}
|
||||
|
||||
|
@ -822,6 +816,8 @@ void stage_enter(StageInfo *stage, CallChain next) {
|
|||
fstate->stage = stage;
|
||||
fstate->cc = next;
|
||||
|
||||
_current_stage_state = fstate;
|
||||
|
||||
#ifdef DEBUG
|
||||
_skip_to_dialog = env_get_int("TAISEI_SKIP_TO_DIALOG", 0);
|
||||
_skip_to_bookmark = env_get_string_nonempty("TAISEI_SKIP_TO_BOOKMARK", NULL);
|
||||
|
@ -840,6 +836,7 @@ void stage_enter(StageInfo *stage, CallChain next) {
|
|||
|
||||
void stage_end_loop(void* ctx) {
|
||||
StageFrameState *s = ctx;
|
||||
assert(s == _current_stage_state);
|
||||
|
||||
if(global.replaymode == REPLAY_RECORD) {
|
||||
replay_stage_event(global.replay_stage, global.frames, EV_OVER, 0);
|
||||
|
@ -868,8 +865,12 @@ void stage_end_loop(void* ctx) {
|
|||
global.gameover = GAMEOVER_ABORT;
|
||||
}
|
||||
|
||||
run_call_chain(&s->cc, NULL);
|
||||
_current_stage_state = NULL;
|
||||
|
||||
CallChain cc = s->cc;
|
||||
free(s);
|
||||
|
||||
run_call_chain(&cc, NULL);
|
||||
}
|
||||
|
||||
void stage_unlock_bgm(const char *bgm) {
|
||||
|
@ -877,3 +878,16 @@ void stage_unlock_bgm(const char *bgm) {
|
|||
progress_unlock_bgm(bgm);
|
||||
}
|
||||
}
|
||||
|
||||
void stage_shake_view(float strength) {
|
||||
assume(strength >= 0);
|
||||
_current_stage_state->view_shake += strength;
|
||||
}
|
||||
|
||||
float stage_get_view_shake_strength(void) {
|
||||
if(_current_stage_state) {
|
||||
return _current_stage_state->view_shake;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -101,6 +101,9 @@ void stage_unlock_bgm(const char *bgm);
|
|||
|
||||
void stage_begin_dialog(Dialog *d) attr_nonnull_all;
|
||||
|
||||
void stage_shake_view(float strength);
|
||||
float stage_get_view_shake_strength(void);
|
||||
|
||||
#ifdef DEBUG
|
||||
void _stage_bookmark(const char *name);
|
||||
#define STAGE_BOOKMARK(name) _stage_bookmark(#name)
|
||||
|
|
|
@ -46,23 +46,22 @@ static struct {
|
|||
ShaderProgram *copy_depth;
|
||||
} shaders;
|
||||
|
||||
struct {
|
||||
float alpha;
|
||||
float target_alpha;
|
||||
} clear_screen;
|
||||
|
||||
PostprocessShader *viewport_pp;
|
||||
FBPair fb_pairs[NUM_FBPAIRS];
|
||||
FBPair powersurge_fbpair;
|
||||
FBPair *current_postprocess_fbpair;
|
||||
|
||||
ManagedFramebufferGroup *mfb_group;
|
||||
StageDrawEvents events;
|
||||
|
||||
struct {
|
||||
float alpha;
|
||||
float target_alpha;
|
||||
} clear_screen;
|
||||
|
||||
bool framerate_graphs;
|
||||
bool objpool_stats;
|
||||
|
||||
ManagedFramebufferGroup *mfb_group;
|
||||
|
||||
StageDrawEvents events;
|
||||
|
||||
#ifdef DEBUG
|
||||
Sprite dummy;
|
||||
#endif
|
||||
|
@ -906,28 +905,33 @@ static void postprocess_prepare(Framebuffer *fb, ShaderProgram *s, void *arg) {
|
|||
}
|
||||
|
||||
static inline void begin_viewport_shake(void) {
|
||||
if(global.shake_view) {
|
||||
float s = stage_get_view_shake_strength();
|
||||
|
||||
if(s > 0) {
|
||||
// s = log1pf(s);
|
||||
s = sqrtf(s);
|
||||
|
||||
r_mat_mv_push();
|
||||
r_mat_mv_translate(
|
||||
global.shake_view * sin(global.frames),
|
||||
global.shake_view * sin(global.frames * 1.1 + 3),
|
||||
s * sin(global.frames),
|
||||
s * sin(global.frames * 1.1 + 3),
|
||||
0
|
||||
);
|
||||
r_mat_mv_scale(
|
||||
1 + 2 * global.shake_view / VIEWPORT_W,
|
||||
1 + 2 * global.shake_view / VIEWPORT_H,
|
||||
1 + 2 * s / VIEWPORT_W,
|
||||
1 + 2 * s / VIEWPORT_H,
|
||||
1
|
||||
);
|
||||
r_mat_mv_translate(
|
||||
-global.shake_view,
|
||||
-global.shake_view,
|
||||
-s,
|
||||
-s,
|
||||
0
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void end_viewport_shake(void) {
|
||||
if(global.shake_view) {
|
||||
if(stage_get_view_shake_strength() > 0) {
|
||||
r_mat_mv_pop();
|
||||
}
|
||||
}
|
||||
|
@ -942,7 +946,7 @@ void stage_draw_begin_noshake(void) {
|
|||
assert(!shake_suppressed);
|
||||
shake_suppressed = 1;
|
||||
|
||||
if(global.shake_view) {
|
||||
if(stage_get_view_shake_strength() > 0) {
|
||||
shake_suppressed = 2;
|
||||
r_mat_mv_push_identity();
|
||||
}
|
||||
|
@ -951,7 +955,7 @@ void stage_draw_begin_noshake(void) {
|
|||
void stage_draw_end_noshake(void) {
|
||||
assert(shake_suppressed);
|
||||
|
||||
if(global.shake_view) {
|
||||
if(stage_get_view_shake_strength() > 0) {
|
||||
// make sure shake_view doesn't change in-between the begin/end calls;
|
||||
// that would've been *really* nasty to debug.
|
||||
assert(shake_suppressed == 2);
|
||||
|
|
|
@ -1094,8 +1094,7 @@ static int iku_extra_trigger_bullet(Projectile *p, int t) {
|
|||
.args = { dir, 10 },
|
||||
);
|
||||
}
|
||||
global.shake_view += 5;
|
||||
global.shake_view_fade = 0.2;
|
||||
stage_shake_view(40);
|
||||
aniplayer_hard_switch(&global.boss->ani,"main_mirror",0);
|
||||
play_sound("boom");
|
||||
return ACTION_DESTROY;
|
||||
|
@ -1195,9 +1194,6 @@ static int iku_extra_slave(Enemy *e, int t) {
|
|||
Laser *l;
|
||||
int cnt = 6 + 2 * global.diff, i;
|
||||
|
||||
global.shake_view = 0;
|
||||
global.shake_view_fade = 0.2;
|
||||
|
||||
e->args[2] = 1;
|
||||
|
||||
for(o = global.enemies.first; o; o = o->next) {
|
||||
|
@ -1217,7 +1213,7 @@ static int iku_extra_slave(Enemy *e, int t) {
|
|||
o->args[1] = 0;
|
||||
o->args[2] = 0;
|
||||
|
||||
global.shake_view += 1;
|
||||
stage_shake_view(5);
|
||||
}
|
||||
|
||||
for(l = global.lasers.first; l; l = l->next) {
|
||||
|
|
|
@ -925,7 +925,7 @@ static int scythe_explode(Enemy *e, int t) {
|
|||
|
||||
if(t == 100) {
|
||||
petal_explosion(100, e->pos);
|
||||
global.shake_view = 16;
|
||||
stage_shake_view(16);
|
||||
play_sound("boom");
|
||||
|
||||
scythe_common(e, t);
|
||||
|
@ -990,8 +990,14 @@ static void elly_paradigm_shift(Boss *b, int t) {
|
|||
elly_spawn_baryons(b->pos);
|
||||
}
|
||||
|
||||
/*
|
||||
if(t > 120)
|
||||
global.shake_view = fmax(0, 16-0.26*(t-120));
|
||||
*/
|
||||
|
||||
AT(120) {
|
||||
stage_shake_view(200);
|
||||
}
|
||||
}
|
||||
|
||||
static void set_baryon_rule(EnemyLogicRule r) {
|
||||
|
@ -1160,8 +1166,7 @@ static int broglie_charge(Projectile *p, int t) {
|
|||
play_sound_ex("laser1", 10, true);
|
||||
play_sound("boom");
|
||||
|
||||
global.shake_view = 5.0;
|
||||
global.shake_view_fade = 0.25;
|
||||
stage_shake_view(20);
|
||||
|
||||
Color clr = p->color;
|
||||
clr.a = 0;
|
||||
|
@ -1747,7 +1752,6 @@ void elly_lhc(Boss *b, int t) {
|
|||
set_baryon_rule(baryon_lhc);
|
||||
AT(EVENT_DEATH) {
|
||||
set_baryon_rule(baryon_reset);
|
||||
global.shake_view_fade=1;
|
||||
}
|
||||
|
||||
FROM_TO(260, 10000, 400) {
|
||||
|
@ -1759,7 +1763,7 @@ void elly_lhc(Boss *b, int t) {
|
|||
int c = 30+10*global.diff;
|
||||
cmplx pos = VIEWPORT_W/2 + 100.0*I+400.0*I*((t/400)&1);
|
||||
|
||||
global.shake_view = 16;
|
||||
stage_shake_view(160);
|
||||
play_sound("boom");
|
||||
|
||||
for(i = 0; i < c; i++) {
|
||||
|
@ -1810,10 +1814,6 @@ void elly_lhc(Boss *b, int t) {
|
|||
.args = { cexp(2.0*I*_i), 3 },
|
||||
);
|
||||
}
|
||||
|
||||
FROM_TO(300, 10000, 400) {
|
||||
global.shake_view = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int baryon_explode(Enemy *e, int t) {
|
||||
|
@ -1822,7 +1822,7 @@ static int baryon_explode(Enemy *e, int t) {
|
|||
free_ref(e->args[1]);
|
||||
petal_explosion(24, e->pos);
|
||||
play_sound("boom");
|
||||
global.shake_view = fmaxf(15, global.shake_view);
|
||||
stage_shake_view(15);
|
||||
|
||||
for(uint i = 0; i < 3; ++i) {
|
||||
PARTICLE(
|
||||
|
@ -2071,8 +2071,6 @@ static void elly_baryon_explode(Boss *b, int t) {
|
|||
|
||||
GO_TO(b, BOSS_DEFAULT_GO_POS, 0.05);
|
||||
|
||||
global.shake_view_fade = 0.5;
|
||||
|
||||
AT(20) {
|
||||
set_baryon_rule(baryon_explode);
|
||||
}
|
||||
|
@ -2084,7 +2082,8 @@ static void elly_baryon_explode(Boss *b, int t) {
|
|||
FROM_TO(0, 200, 1) {
|
||||
// tsrand_fill(2);
|
||||
// petal_explosion(1, b->pos + 100*afrand(0)*cexp(2.0*I*M_PI*afrand(1)));
|
||||
global.shake_view = fmaxf(global.shake_view, 5 * _i / 200.0f);
|
||||
// global.shake_view = fmaxf(global.shake_view, 5 * _i / 200.0f);
|
||||
stage_shake_view(_i / 200.0f);
|
||||
|
||||
if(_i > 30) {
|
||||
play_loop("charge_generic");
|
||||
|
@ -2093,8 +2092,7 @@ static void elly_baryon_explode(Boss *b, int t) {
|
|||
|
||||
AT(200) {
|
||||
tsrand_fill(2);
|
||||
global.shake_view += 30;
|
||||
global.shake_view_fade = 0.05;
|
||||
stage_shake_view(40);
|
||||
play_sound("boom");
|
||||
petal_explosion(100, b->pos + 100*afrand(0)*cexp(2.0*I*M_PI*afrand(1)));
|
||||
enemy_kill_all(&global.enemies);
|
||||
|
@ -2635,7 +2633,7 @@ static void elly_toe_laser_logic(Laser *l, int t) {
|
|||
//
|
||||
void elly_theory(Boss *b, int time) {
|
||||
if(time == EVENT_BIRTH) {
|
||||
global.shake_view = 10;
|
||||
stage_shake_view(50);
|
||||
boss_set_portrait(b, "elly", "beaten", "shouting");
|
||||
return;
|
||||
}
|
||||
|
@ -2650,7 +2648,6 @@ void elly_theory(Boss *b, int time) {
|
|||
AT(0) {
|
||||
assert(cabs(b->pos - ELLY_TOE_TARGET_POS) < 1);
|
||||
b->pos = ELLY_TOE_TARGET_POS;
|
||||
global.shake_view = 0;
|
||||
elly_clap(b,50000);
|
||||
}
|
||||
|
||||
|
@ -2737,16 +2734,14 @@ void elly_theory(Boss *b, int time) {
|
|||
|
||||
AT(fermiontime) {
|
||||
play_sound("charge_generic");
|
||||
global.shake_view=10;
|
||||
global.shake_view_fade=1;
|
||||
stage_shake_view(10);
|
||||
}
|
||||
|
||||
AT(symmetrytime) {
|
||||
play_sound("charge_generic");
|
||||
play_sound("boom");
|
||||
stagetext_add("Symmetry broken!", VIEWPORT_W/2+I*VIEWPORT_H/4, ALIGN_CENTER, get_font("big"), RGB(1,1,1), 0,100,10,20);
|
||||
global.shake_view=10;
|
||||
global.shake_view_fade=1;
|
||||
stage_shake_view(10);
|
||||
|
||||
PARTICLE(
|
||||
.sprite = "blast",
|
||||
|
@ -2774,16 +2769,14 @@ void elly_theory(Boss *b, int time) {
|
|||
AT(yukawatime) {
|
||||
play_sound("charge_generic");
|
||||
stagetext_add("Coupling the Higgs!", VIEWPORT_W/2+I*VIEWPORT_H/4, ALIGN_CENTER, get_font("big"), RGB(1,1,1), 0,100,10,20);
|
||||
global.shake_view=10;
|
||||
global.shake_view_fade=1;
|
||||
stage_shake_view(10);
|
||||
}
|
||||
|
||||
AT(breaktime) {
|
||||
play_sound("charge_generic");
|
||||
stagetext_add("Perturbation theory", VIEWPORT_W/2+I*VIEWPORT_H/4, ALIGN_CENTER, get_font("big"), RGB(1,1,1), 0,100,10,20);
|
||||
stagetext_add("breaking down!", VIEWPORT_W/2+I*VIEWPORT_H/4+30*I, ALIGN_CENTER, get_font("big"), RGB(1,1,1), 0,100,10,20);
|
||||
global.shake_view=10;
|
||||
global.shake_view_fade=1;
|
||||
stage_shake_view(10);
|
||||
}
|
||||
|
||||
FROM_TO(higgstime,yukawatime+100,4+4*(time>symmetrytime)) {
|
||||
|
@ -2962,7 +2955,6 @@ static void elly_begin_toe(Boss *b, int t) {
|
|||
start_fall_over();
|
||||
stage_unlock_bgm("stage6boss_phase2");
|
||||
stage_start_bgm("stage6boss_phase3");
|
||||
global.shake_view_fade = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue