210 lines
6.1 KiB
C++
210 lines
6.1 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include "ags/shared/ac/common.h"
|
|
#include "ags/engine/ac/game_setup.h"
|
|
#include "ags/engine/ac/draw.h"
|
|
#include "ags/engine/ac/game_setup.h"
|
|
#include "ags/shared/ac/game_setup_struct.h"
|
|
#include "ags/engine/ac/game_state.h"
|
|
#include "ags/engine/ac/global_game.h"
|
|
#include "ags/engine/ac/global_screen.h"
|
|
#include "ags/engine/ac/runtime_defines.h"
|
|
#include "ags/engine/ac/screen.h"
|
|
#include "ags/engine/debugging/debug_log.h"
|
|
#include "ags/engine/main/game_run.h"
|
|
#include "ags/engine/media/audio/audio.h"
|
|
#include "ags/engine/platform/base/ags_platform_driver.h"
|
|
#include "ags/engine/gfx/graphics_driver.h"
|
|
#include "ags/shared/gfx/bitmap.h"
|
|
|
|
namespace AGS3 {
|
|
|
|
using namespace AGS::Shared;
|
|
using namespace AGS::Engine;
|
|
|
|
|
|
void FlipScreen(int amount) {
|
|
if ((amount < 0) || (amount > 3))
|
|
quit("!FlipScreen: invalid argument (0-3)");
|
|
_GP(play).screen_flipped = amount;
|
|
}
|
|
|
|
void ShakeScreen(int severe) {
|
|
EndSkippingUntilCharStops();
|
|
|
|
if (_GP(play).fast_forward)
|
|
return;
|
|
|
|
severe = data_to_game_coord(severe);
|
|
|
|
// 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
|
|
|
|
_GP(play).shakesc_length = 10;
|
|
_GP(play).shakesc_delay = 2;
|
|
_GP(play).shakesc_amount = severe;
|
|
_GP(play).mouse_cursor_hidden++;
|
|
|
|
// FIXME: we have to sync audio here explicitly, because ShakeScreen
|
|
// does not call any game update function while it works
|
|
sync_audio_playback();
|
|
if (_G(gfxDriver)->RequiresFullRedrawEachFrame()) {
|
|
for (int hh = 0; hh < 40; hh++) {
|
|
_G(loopcounter)++;
|
|
_G(platform)->Delay(50);
|
|
|
|
render_graphics();
|
|
|
|
update_polled_stuff();
|
|
}
|
|
} else {
|
|
// Optimized variant for software render: create game scene once and shake it
|
|
construct_game_scene();
|
|
_G(gfxDriver)->RenderToBackBuffer();
|
|
for (int hh = 0; hh < 40; hh++) {
|
|
_G(platform)->Delay(50);
|
|
const int yoff = hh % 2 == 0 ? 0 : severe;
|
|
_GP(play).shake_screen_yoff = yoff;
|
|
render_to_screen();
|
|
update_polled_stuff();
|
|
}
|
|
clear_letterbox_borders();
|
|
render_to_screen();
|
|
}
|
|
sync_audio_playback();
|
|
|
|
_GP(play).mouse_cursor_hidden--;
|
|
_GP(play).shakesc_length = 0;
|
|
_GP(play).shakesc_delay = 0;
|
|
_GP(play).shakesc_amount = 0;
|
|
}
|
|
|
|
void ShakeScreenBackground(int delay, int amount, int length) {
|
|
if (delay < 2)
|
|
quit("!ShakeScreenBackground: invalid delay parameter");
|
|
|
|
amount = data_to_game_coord(amount);
|
|
|
|
if (amount < _GP(play).shakesc_amount) {
|
|
// from a bigger to smaller shake, clear up the borders
|
|
clear_letterbox_borders();
|
|
}
|
|
|
|
_GP(play).shakesc_amount = amount;
|
|
_GP(play).shakesc_delay = delay;
|
|
_GP(play).shakesc_length = length;
|
|
}
|
|
|
|
void TintScreen(int red, int grn, int blu) {
|
|
if ((red < 0) || (grn < 0) || (blu < 0) || (red > 100) || (grn > 100) || (blu > 100))
|
|
quit("!TintScreen: RGB values must be 0-100");
|
|
|
|
invalidate_screen();
|
|
|
|
if ((red == 0) && (grn == 0) && (blu == 0)) {
|
|
_GP(play).screen_tint = -1;
|
|
return;
|
|
}
|
|
red = (red * 25) / 10;
|
|
grn = (grn * 25) / 10;
|
|
blu = (blu * 25) / 10;
|
|
_GP(play).screen_tint = red + (grn << 8) + (blu << 16);
|
|
}
|
|
|
|
void FadeOut(int sppd) {
|
|
EndSkippingUntilCharStops();
|
|
|
|
if (_GP(play).fast_forward) {
|
|
_GP(play).screen_is_faded_out = 1;
|
|
return;
|
|
}
|
|
|
|
// FIXME: we have to sync audio here explicitly, because FadeOut
|
|
// does not call any game update function while it works
|
|
sync_audio_playback();
|
|
fadeout_impl(sppd);
|
|
sync_audio_playback();
|
|
|
|
// Older engines did not mark the screen as "faded out" specifically for
|
|
// the 8-bit games, for unknown reasons. There's at least one game where
|
|
// this was accidentally useful, as it did not run FadeIn after FadeOut.
|
|
if ((_G(loaded_game_file_version) < kGameVersion_361) && _GP(game).color_depth == 1) {
|
|
_GP(play).screen_is_faded_out = 0;
|
|
}
|
|
}
|
|
|
|
void fadeout_impl(int spdd) {
|
|
if (_GP(play).screen_is_faded_out == 0) {
|
|
_G(gfxDriver)->FadeOut(spdd, _GP(play).fade_to_red, _GP(play).fade_to_green, _GP(play).fade_to_blue, RENDER_SHOT_SKIP_ON_FADE);
|
|
_GP(play).screen_is_faded_out = 1;
|
|
}
|
|
}
|
|
|
|
void SetScreenTransition(int newtrans) {
|
|
if ((newtrans < 0) || (newtrans > FADE_LAST))
|
|
quit("!SetScreenTransition: invalid transition type");
|
|
|
|
_GP(play).fade_effect = newtrans;
|
|
|
|
debug_script_log("Screen transition changed");
|
|
}
|
|
|
|
void SetNextScreenTransition(int newtrans) {
|
|
if ((newtrans < 0) || (newtrans > FADE_LAST))
|
|
quit("!SetNextScreenTransition: invalid transition type");
|
|
|
|
_GP(play).next_screen_transition = newtrans;
|
|
|
|
debug_script_log("SetNextScreenTransition engaged");
|
|
}
|
|
|
|
void SetFadeColor(int red, int green, int blue) {
|
|
if ((red < 0) || (red > 255) || (green < 0) || (green > 255) ||
|
|
(blue < 0) || (blue > 255))
|
|
quit("!SetFadeColor: Red, Green and Blue must be 0-255");
|
|
|
|
_GP(play).fade_to_red = red;
|
|
_GP(play).fade_to_green = green;
|
|
_GP(play).fade_to_blue = blue;
|
|
}
|
|
|
|
void FadeIn(int sppd) {
|
|
EndSkippingUntilCharStops();
|
|
|
|
if (_GP(play).fast_forward) {
|
|
_GP(play).screen_is_faded_out = 0;
|
|
return;
|
|
}
|
|
|
|
// Update drawables, prepare them for the transition-in
|
|
// in case this is called after the game state change but before any update was run
|
|
SyncDrawablesState();
|
|
// FIXME: we have to sync audio here explicitly, because FadeIn
|
|
// does not call any game update function while it works
|
|
sync_audio_playback();
|
|
fadein_impl(_G(palette), sppd);
|
|
sync_audio_playback();
|
|
}
|
|
|
|
} // namespace AGS3
|