scummvm/engines/xeen/cutscenes.cpp
Paul Gilbert 8fc4a08e04 XEEN: Refactor to merge Sound and Music classes
The existing structure didn't make sense, as Sound only handled
sound files, but Music handled both music and short FX decoding.
I've merged Sound & MUsic into a single Sound class, and moved
the music driver to their own file, renamed to SoundDriver
2018-02-19 10:17:33 -05:00

215 lines
5.4 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 2
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include "xeen/cutscenes.h"
#include "xeen/xeen.h"
namespace Xeen {
static const char *SUBTITLE_LINE = "\xC" "35\x3" "c\xB" "190\x9" "000%s";
void Cutscenes::resetSubtitles(uint lineNum, uint defaultSize) {
_subtitleLineNum = lineNum;
_subtitleSize = defaultSize;
recordTime();
}
void Cutscenes::showSubtitles(uint windowIndex) {
Screen &screen = *_vm->_screen;
Sound &sound = *_vm->_sound;
Windows &windows = *_vm->_windows;
if (sound._soundOn || _vm->shouldExit()) {
// Sound is on, so subtitles aren't needed
resetSubtitles(0, 0);
} else {
if (timeElapsed() > 1) {
++_subtitleSize;
const Common::String &line = _subtitles[_subtitleLineNum];
Common::String lineStr(line.c_str(), line.c_str() + _subtitleSize);
_subtitleLine = Common::String::format(SUBTITLE_LINE, lineStr.c_str());
// If displayed a full line, then move to the next line
if (_subtitleSize == line.size()) {
_subtitleSize = 0;
if (++_subtitleLineNum == _subtitles.size())
_subtitleLineNum = 0;
}
}
// Draw the box sprite
if (!_boxSprites)
// Not already loaded, so load it
_boxSprites = new SpriteResource("box.vga");
_boxSprites->draw(0, 0, Common::Point(36, 189));
// Write the subtitle line
windows[windowIndex].writeString(_subtitleLine);
}
screen.update();
}
void Cutscenes::freeSubtitles() {
delete _boxSprites;
_boxSprites = nullptr;
_subtitles.clear();
}
bool Cutscenes::subtitlesWait(uint minTime) {
EventsManager &events = *_vm->_events;
events.updateGameCounter();
recordTime();
while (events.timeElapsed() < minTime || _subtitleSize != 0) {
events.pollEventsAndWait();
if (events.isKeyMousePressed())
return false;
showSubtitles();
}
return true;
}
bool Cutscenes::waitForLineOrSound() {
while (_vm->_sound->isSoundPlaying() || _subtitleSize) {
showSubtitles();
_vm->_events->pollEventsAndWait();
if (_vm->_events->isKeyMousePressed())
return false;
}
return true;
}
void Cutscenes::recordTime() {
_vm->_events->timeMark1();
}
uint Cutscenes::timeElapsed() {
return _vm->_events->timeElapsed1();
}
uint Cutscenes::getSpeakingFrame(uint minFrame, uint maxFrame) {
uint interval = g_system->getMillis() / 100;
return minFrame + interval % (maxFrame + 1 - minFrame);
}
bool Cutscenes::doScroll(bool rollUp, bool fadeIn) {
Screen &screen = *_vm->_screen;
EventsManager &events = *_vm->_events;
const int SCROLL_L[8] = { 29, 23, 15, -5, -11, -23, -49, -71 };
const int SCROLL_R[8] = { 165, 171, 198, 218, 228, 245, 264, 281 };
if (_vm->_files->_isDarkCc) {
if (fadeIn)
screen.fadeIn(2);
return _vm->shouldExit();
}
screen.saveBackground();
// Load hand sprites
SpriteResource *hand[16];
for (int i = 0; i < 16; ++i) {
Common::String name = Common::String::format("hand%02d.vga", i);
hand[i] = new SpriteResource(name);
}
// Load marb sprites
SpriteResource *marb[5];
for (int i = 0; i < 4; ++i) {
Common::String name = Common::String::format("marb%02d.vga", i + 1);
marb[i] = new SpriteResource(name);
}
if (rollUp) {
for (int i = 22, ctr = 7; i > 0 && !events.isKeyMousePressed()
&& !_vm->shouldExit(); --i) {
events.updateGameCounter();
screen.restoreBackground();
if (i > 14) {
hand[14]->draw(0, 0, Common::Point(SCROLL_L[ctr], 0), SPRFLAG_800);
hand[15]->draw(0, 0, Common::Point(SCROLL_R[ctr], 0), SPRFLAG_800);
--ctr;
} else if (i != 0) {
hand[i - 1]->draw(0, 0);
}
if (i <= 20)
marb[(i - 1) / 5]->draw(0, (i - 1) % 5);
screen.update();
while (!_vm->shouldExit() && events.timeElapsed() == 0)
events.pollEventsAndWait();
if (i == 0 && fadeIn)
screen.fadeIn(2);
}
} else {
for (int i = 0, ctr = 0; i < 22 && !events.isKeyMousePressed()
&& !_vm->shouldExit(); ++i) {
events.updateGameCounter();
screen.restoreBackground();
if (i < 14) {
hand[i]->draw(0, 0);
} else {
hand[14]->draw(0, 0, Common::Point(SCROLL_L[ctr], 0), SPRFLAG_800);
hand[15]->draw(0, 0, Common::Point(SCROLL_R[ctr], 0), SPRFLAG_800);
++ctr;
}
if (i < 20) {
marb[i / 5]->draw(0, i % 5);
}
screen.update();
while (!_vm->shouldExit() && events.timeElapsed() == 0)
events.pollEventsAndWait();
if (i == 0 && fadeIn)
screen.fadeIn(2);
}
}
if (rollUp) {
hand[0]->draw(0, 0);
marb[0]->draw(0, 0);
} else {
screen.restoreBackground();
}
screen.update();
// Free resources
for (int i = 0; i < 4; ++i)
delete marb[i];
for (int i = 0; i < 16; ++i)
delete hand[i];
return _vm->shouldExit() || events.isKeyMousePressed();
}
} // End of namespace Xeen