Skip to content

Commit

Permalink
Engine: implement ShakeScreenState
Browse files Browse the repository at this point in the history
  • Loading branch information
ivan-mogilko committed Mar 1, 2024
1 parent e0d64d5 commit d22f6fa
Showing 1 changed file with 77 additions and 37 deletions.
114 changes: 77 additions & 37 deletions Engine/ac/global_screen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,64 +43,104 @@ void FlipScreen(int amount) {
play.screen_flipped=amount;
}

void ShakeScreen(int severe) {
EndSkippingUntilCharStops();

if (play.fast_forward)
return;

severe = data_to_game_coord(severe);
class ShakeScreenState : public GameState
{
public:
ShakeScreenState(int severe)
: _severe(severe) {}

// Begin the state, initialize and prepare any resources;
// returns if the state should continue, or ends instantly
bool Begin() override
{
// TODO: support shaking room viewport separately
// TODO: rely on game speed setting? and/or provide frequency and duration args
// TODO: unify blocking and non-blocking shake update

// TODO: support shaking room viewport separately
// TODO: rely on game speed setting? and/or provide frequency and duration args
// TODO: unify blocking and non-blocking shake update
// FIXME: keeping hardcoded 40 shakes with ~50 ms delay between shakes for now,
// only use this is a factor, and calculate delay and duration params from this.
int compat_shake_delay = static_cast<int>(50.f / (1000.f / GetGameSpeed()));
int compat_duration = static_cast<int>(40 * (50.f / (1000.f / GetGameSpeed())));

// FIXME: keeping hardcoded 40 shakes with ~50 ms delay between shakes for now,
// only use this is a factor, and calculate delay and duration params from this.
int compat_shake_delay = static_cast<int>(50.f / (1000.f / GetGameSpeed()));
int compat_duration = static_cast<int>(40 * (50.f / (1000.f / GetGameSpeed())));
play.shakesc_length = compat_duration;
play.shakesc_delay = 2 * compat_shake_delay;
play.shakesc_amount = _severe;
play.mouse_cursor_hidden++;

play.shakesc_length = compat_duration;
play.shakesc_delay = 2 * compat_shake_delay;
play.shakesc_amount = severe;
play.mouse_cursor_hidden++;
// Optimized variant for software render: create game scene once and shake it
// TODO: split implementations into two state classes?
if (!gfxDriver->RequiresFullRedrawEachFrame())
{
gfxDriver->ClearDrawLists();
construct_game_scene();
gfxDriver->RenderToBackBuffer();
}
return true;
}
// End the state, does final actions, releases all resources;
// should NOT be called if Begin returned FALSE.
void End() override
{
if (!gfxDriver->RequiresFullRedrawEachFrame())
{
clear_letterbox_borders();
render_to_screen();
}

// FIXME: we have to sync audio here explicitly, because ShakeScreen
// does not call any game update function while it works
sync_audio_playback();
if (gfxDriver->RequiresFullRedrawEachFrame())
play.mouse_cursor_hidden--;
play.shakesc_length = 0;
play.shakesc_delay = 0;
play.shakesc_amount = 0;
}
// Draw the state
void Draw() override
{
for (int hh = 0; hh < play.shakesc_length; hh++)
}
// Update the state during a game tick;
// returns whether should continue to run state loop, or stop
bool Run() override
{
// TODO: split implementations into two state classes?
if (gfxDriver->RequiresFullRedrawEachFrame())
{
loopcounter++;
render_graphics();
update_polled_stuff();
WaitForNextFrame();
}
}
else
{
// Optimized variant for software render: create game scene once and shake it
gfxDriver->ClearDrawLists();
construct_game_scene();
gfxDriver->RenderToBackBuffer();
for (int hh = 0; hh < play.shakesc_length; hh++)
else
{
loopcounter++;
update_shakescreen();
render_to_screen();
update_polled_stuff();
WaitForNextFrame();
}
clear_letterbox_borders();
render_to_screen();
return ++_step < play.shakesc_length;
}

private:
int _severe = 0;
int _step = 0;
};

void ShakeScreen(int severe) {
EndSkippingUntilCharStops();

if (play.fast_forward)
return;

severe = data_to_game_coord(severe);
// FIXME: we have to sync audio here explicitly, because ShakeScreen
// does not call any game update function while it works
sync_audio_playback();

play.mouse_cursor_hidden--;
play.shakesc_length = 0;
play.shakesc_delay = 0;
play.shakesc_amount = 0;
ShakeScreenState shake(severe);
shake.Begin();
while (shake.Run());
shake.End();

sync_audio_playback();
}

void ShakeScreenBackground (int delay, int amount, int length) {
Expand Down

0 comments on commit d22f6fa

Please sign in to comment.