Initial commit
This commit is contained in:
402
engines/plumbers/plumbers.cpp
Normal file
402
engines/plumbers/plumbers.cpp
Normal file
@@ -0,0 +1,402 @@
|
||||
/* 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 "plumbers/plumbers.h"
|
||||
#include "plumbers/console.h"
|
||||
|
||||
#include "audio/decoders/aiff.h"
|
||||
#include "audio/decoders/wave.h"
|
||||
#include "audio/audiostream.h"
|
||||
|
||||
#include "common/debug.h"
|
||||
#include "common/debug-channels.h"
|
||||
#include "common/error.h"
|
||||
#include "common/events.h"
|
||||
#include "common/file.h"
|
||||
#include "common/system.h"
|
||||
#include "common/timer.h"
|
||||
|
||||
#include "engines/util.h"
|
||||
|
||||
#include "graphics/cursorman.h"
|
||||
#include "graphics/font.h"
|
||||
#include "graphics/fontman.h"
|
||||
#include "graphics/paletteman.h"
|
||||
#include "graphics/scaler/downscaler.h"
|
||||
#include "graphics/surface.h"
|
||||
|
||||
namespace Plumbers {
|
||||
|
||||
PlumbersGame::PlumbersGame(OSystem *syst, const ADGameDescription *gameDesc) :
|
||||
Engine(syst), _gameDescription(gameDesc), _console(nullptr), _image(nullptr),
|
||||
_compositeSurface(nullptr), _videoDecoder(nullptr), _quit(false) {
|
||||
_timerInstalled = false;
|
||||
_showScoreFl = false;
|
||||
_setDurationFl = false;
|
||||
_leftButtonDownFl = false;
|
||||
_endGameFl = false;
|
||||
_curSceneIdx = -1;
|
||||
_prvSceneIdx = -1;
|
||||
_curBitmapIdx = -1;
|
||||
_curChoice = 0;
|
||||
_totScene = -1;
|
||||
_totScore = 0;
|
||||
}
|
||||
|
||||
PlumbersGame::~PlumbersGame() {
|
||||
delete _image;
|
||||
//_console is deleted by Engine
|
||||
}
|
||||
|
||||
static const byte MOUSECURSOR_SCI[] = {
|
||||
1,1,0,0,0,0,0,0,0,0,0,
|
||||
1,2,1,0,0,0,0,0,0,0,0,
|
||||
1,2,2,1,0,0,0,0,0,0,0,
|
||||
1,2,2,2,1,0,0,0,0,0,0,
|
||||
1,2,2,2,2,1,0,0,0,0,0,
|
||||
1,2,2,2,2,2,1,0,0,0,0,
|
||||
1,2,2,2,2,2,2,1,0,0,0,
|
||||
1,2,2,2,2,2,2,2,1,0,0,
|
||||
1,2,2,2,2,2,2,2,2,1,0,
|
||||
1,2,2,2,2,2,2,2,2,2,1,
|
||||
1,2,2,2,2,2,1,0,0,0,0,
|
||||
1,2,1,0,1,2,2,1,0,0,0,
|
||||
1,1,0,0,1,2,2,1,0,0,0,
|
||||
0,0,0,0,0,1,2,2,1,0,0,
|
||||
0,0,0,0,0,1,2,2,1,0,0,
|
||||
0,0,0,0,0,0,1,2,2,1,0
|
||||
};
|
||||
|
||||
static const byte MOUSECURSOR_AMIGA[] = {
|
||||
1,1,0,0,0,0,0,0,
|
||||
1,2,1,0,0,0,0,0,
|
||||
1,2,2,1,0,0,0,0,
|
||||
1,2,2,2,1,0,0,0,
|
||||
1,2,2,2,2,1,0,0,
|
||||
1,2,2,2,2,2,1,0,
|
||||
1,1,1,2,2,1,1,0,
|
||||
0,0,0,1,2,1,0,0,
|
||||
0,0,0,1,2,2,1,0,
|
||||
0,0,0,0,1,2,1,0,
|
||||
0,0,0,0,1,2,2,1,
|
||||
0,0,0,0,0,1,1,0,
|
||||
};
|
||||
|
||||
static const byte cursorPalette[] = {
|
||||
0, 0, 0, // Black / Transparent
|
||||
0x80, 0x80, 0x80, // Gray
|
||||
0xff, 0xff, 0xff // White
|
||||
};
|
||||
|
||||
void PlumbersGame::handleEvent(const Common::Event &event) {
|
||||
switch (event.type) {
|
||||
case Common::EVENT_QUIT:
|
||||
case Common::EVENT_RETURN_TO_LAUNCHER:
|
||||
_quit = true;
|
||||
break;
|
||||
|
||||
case Common::EVENT_LBUTTONDOWN:
|
||||
if (_leftButtonDownFl) {
|
||||
_curChoice = getMouseHiLite();
|
||||
|
||||
if (_curChoice >= 0 && _curChoice < _scenes[_curSceneIdx]._decisionChoices) {
|
||||
debugC(5, kDebugGeneral, "Accepting mouse click with choice = %d", _curChoice);
|
||||
_totScore += _scenes[_curSceneIdx]._choices[_curChoice]._points;
|
||||
_actions.push(ChangeScene);
|
||||
_leftButtonDownFl = false;
|
||||
}
|
||||
} else if (_console->_allowSkip && _timerInstalled) {
|
||||
// Allows to skip speech by skipping wait delay
|
||||
onTimer(this);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Common::Error PlumbersGame::run() {
|
||||
startGraphics();
|
||||
|
||||
_console = new Console();
|
||||
setDebugger(_console);
|
||||
|
||||
if (_screenW > 320)
|
||||
CursorMan.replaceCursor(MOUSECURSOR_SCI, 11, 16, 0, 0, 0);
|
||||
else
|
||||
CursorMan.replaceCursor(MOUSECURSOR_AMIGA, 8, 12, 0, 0, 0);
|
||||
CursorMan.replaceCursorPalette(cursorPalette, 0, 3);
|
||||
CursorMan.showMouse(true);
|
||||
|
||||
readTables();
|
||||
|
||||
_showScoreFl = false;
|
||||
_leftButtonDownFl = false;
|
||||
_endGameFl = false;
|
||||
_totScore = 0;
|
||||
_curSceneIdx = _prvSceneIdx = 0;
|
||||
_curChoice = 0;
|
||||
_actions.clear();
|
||||
_actions.push(ShowScene);
|
||||
|
||||
_quit = false;
|
||||
|
||||
while (!_quit && !_endGameFl) {
|
||||
Common::Event event;
|
||||
while (g_system->getEventManager()->pollEvent(event)) {
|
||||
handleEvent(event);
|
||||
}
|
||||
|
||||
preActions();
|
||||
|
||||
while (!_actions.empty()) {
|
||||
switch (_actions.pop()) {
|
||||
case Redraw:
|
||||
drawScreen();
|
||||
break;
|
||||
case ShowScene:
|
||||
showScene();
|
||||
break;
|
||||
case UpdateScene:
|
||||
updateScene();
|
||||
break;
|
||||
case ChangeScene:
|
||||
changeScene();
|
||||
break;
|
||||
case PlaySound:
|
||||
playSound(_scenes[_curSceneIdx]._sceneName + "/" + _scenes[_curSceneIdx]._waveFilename);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (_videoDecoder) {
|
||||
if (_videoDecoder->endOfVideo()) {
|
||||
_actions.push(ChangeScene);
|
||||
_videoDecoder->close();
|
||||
delete _videoDecoder;
|
||||
_videoDecoder = nullptr;
|
||||
} else if (_videoDecoder->needsUpdate()) {
|
||||
drawScreen();
|
||||
}
|
||||
}
|
||||
|
||||
g_system->updateScreen();
|
||||
g_system->delayMillis(_videoDecoder ? (1000 / 60) : 10);
|
||||
}
|
||||
|
||||
g_system->getTimerManager()->removeTimerProc(onTimer);
|
||||
stopSound();
|
||||
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
void PlumbersGame::loadImage(const Common::String &name) {
|
||||
debugC(1, kDebugGeneral, "%s : %s", __FUNCTION__, name.c_str());
|
||||
Common::File file;
|
||||
if (!file.open(Common::Path(name)))
|
||||
error("unable to load image %s", name.c_str());
|
||||
|
||||
_image->loadStream(file);
|
||||
delete _compositeSurface;
|
||||
_compositeSurface = nullptr;
|
||||
}
|
||||
|
||||
void PlumbersGame::blitImageSurface(const Graphics::Surface *surface) {
|
||||
int w = CLIP<int>(surface->w, 0, _screenW);
|
||||
int h = CLIP<int>(surface->h, 0, _screenH);
|
||||
|
||||
int x = (_screenW - w) / 2;
|
||||
int y = (_screenH - h) / 2;
|
||||
|
||||
g_system->copyRectToScreen(surface->getPixels(), surface->pitch, x, y, w, h);
|
||||
}
|
||||
|
||||
void PlumbersGame::blitImage() {
|
||||
blitImageSurface(_compositeSurface ? _compositeSurface : _image->getSurface());
|
||||
}
|
||||
|
||||
void PlumbersGame::drawScreen() {
|
||||
debugC(_videoDecoder ? 10 : 1, kDebugGeneral, "%s : %s", __FUNCTION__, _image ? "YES" : "NO");
|
||||
if (_videoDecoder ? _videoDecoder->needsUpdate() : _image || _compositeSurface) {
|
||||
if (_setDurationFl) {
|
||||
g_system->getTimerManager()->removeTimerProc(onTimer);
|
||||
g_system->getTimerManager()->installTimerProc(onTimer, _bitmaps[_curBitmapIdx]._duration * 1000, this, "timer");
|
||||
_timerInstalled = true;
|
||||
_actions.push(UpdateScene);
|
||||
}
|
||||
|
||||
g_system->fillScreen(0);
|
||||
|
||||
blitImage();
|
||||
|
||||
if (_showScoreFl) {
|
||||
Graphics::PixelFormat screenFormat = g_system->getScreenFormat();
|
||||
Common::String score = Common::String::format("Your Score is: %ld", _totScore);
|
||||
const Graphics::Font &font(*FontMan.getFontByUsage(
|
||||
_screenW >= 640 ? Graphics::FontManager::kBigGUIFont : Graphics::FontManager::kGUIFont));
|
||||
int scoreTop = _screenH - _screenH / 12;
|
||||
int scoreMaxWidth = _screenW >= 640 ? 200 : 150;
|
||||
uint scoreColor = screenFormat.bytesPerPixel == 1 ? 0xff : screenFormat.RGBToColor(0xff, 0xff, 0xff);
|
||||
Common::Rect rect(10, scoreTop, scoreMaxWidth, scoreTop + font.getFontHeight());
|
||||
if (getPlatform() != Common::kPlatform3DO)
|
||||
g_system->fillScreen(rect, 0);
|
||||
Graphics::Surface *screen = g_system->lockScreen();
|
||||
font.drawString(screen, score, rect.left, rect.top, scoreMaxWidth - 10,
|
||||
scoreColor, Graphics::kTextAlignCenter);
|
||||
g_system->unlockScreen();
|
||||
_showScoreFl = false;
|
||||
}
|
||||
|
||||
if (_image->hasPalette())
|
||||
g_system->getPaletteManager()->setPalette(_image->getPalette().data(), 0, _image->getPalette().size());
|
||||
g_system->updateScreen();
|
||||
}
|
||||
}
|
||||
|
||||
void PlumbersGame::playSound(const Common::String &name) {
|
||||
debugC(3, kDebugGeneral, "%s : %s", __FUNCTION__, name.c_str());
|
||||
Common::File *file = new Common::File();
|
||||
if (!file->open(Common::Path(name)))
|
||||
error("unable to load sound %s", name.c_str());
|
||||
|
||||
Audio::AudioStream *stream;
|
||||
if (name.hasSuffixIgnoreCase(".aiff"))
|
||||
stream = Audio::makeAIFFStream(file, DisposeAfterUse::YES);
|
||||
else
|
||||
stream = Audio::makeWAVStream(file, DisposeAfterUse::YES);
|
||||
stopSound();
|
||||
_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, stream, -1, Audio::Mixer::kMaxChannelVolume);
|
||||
}
|
||||
|
||||
void PlumbersGame::stopSound() {
|
||||
debugC(3, kDebugGeneral, "%s", __FUNCTION__);
|
||||
if (_mixer->isSoundHandleActive(_soundHandle))
|
||||
_mixer->stopHandle(_soundHandle);
|
||||
}
|
||||
|
||||
void PlumbersGame::showScene() {
|
||||
debugC(1, kDebugGeneral, "%s : %d", __FUNCTION__, _curSceneIdx);
|
||||
_curBitmapIdx = _scenes[_curSceneIdx]._startBitmap - 1;
|
||||
updateScene();
|
||||
if (_scenes[_curSceneIdx]._waveFilename != "")
|
||||
_actions.push(PlaySound);
|
||||
_actions.push(Redraw);
|
||||
}
|
||||
|
||||
int PlumbersGame::getMouseHiLite() {
|
||||
Common::Point mousePos = g_system->getEventManager()->getMousePos();
|
||||
for (int i = 0; i < _scenes[_curSceneIdx]._decisionChoices && i < kMaxChoice; i++) {
|
||||
if (_scenes[_curSceneIdx]._choices[i]._region.contains(mousePos))
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void PlumbersGame::updateScene() {
|
||||
debugC(2, kDebugGeneral, "%s : %d", __FUNCTION__, _curBitmapIdx);
|
||||
_curBitmapIdx++;
|
||||
if (_curBitmapIdx >= _scenes[_curSceneIdx]._startBitmap + _scenes[_curSceneIdx]._bitmapNum) {
|
||||
postSceneBitmaps();
|
||||
} else {
|
||||
loadImage(_scenes[_curSceneIdx]._sceneName + "/" + _bitmaps[_curBitmapIdx]._filename);
|
||||
_setDurationFl = true;
|
||||
}
|
||||
}
|
||||
|
||||
void PlumbersGame::changeScene() {
|
||||
debugC(1, kDebugGeneral, "%s : %d", __FUNCTION__, _curChoice);
|
||||
if (_scenes[_curSceneIdx]._choices[_curChoice]._sceneName == "SC-1") {
|
||||
_curSceneIdx = _prvSceneIdx;
|
||||
_curBitmapIdx = 9999;
|
||||
_actions.push(UpdateScene);
|
||||
_actions.push(Redraw);
|
||||
} else if (_scenes[_curSceneIdx]._choices[_curChoice]._sceneName == "restart") {
|
||||
_curSceneIdx = 0;
|
||||
_totScore = 0;
|
||||
_actions.push(UpdateScene);
|
||||
_actions.push(Redraw);
|
||||
} else if (_scenes[_curSceneIdx]._choices[_curChoice]._sceneName == "SC32767"
|
||||
|| _scenes[_curSceneIdx]._choices[_curChoice]._sceneName == "end") {
|
||||
_endGameFl = true;
|
||||
} else {
|
||||
if (_scenes[_curSceneIdx]._decisionChoices > 1)
|
||||
_prvSceneIdx = _curSceneIdx;
|
||||
if (_scenes[_curSceneIdx]._choices[_curChoice]._skipScene) {
|
||||
_curSceneIdx = getSceneNumb(_scenes[_curSceneIdx]._choices[_curChoice]._sceneName);
|
||||
_curBitmapIdx = 9999;
|
||||
_actions.push(UpdateScene);
|
||||
_actions.push(Redraw);
|
||||
g_system->getTimerManager()->removeTimerProc(onTimer);
|
||||
_timerInstalled = false;
|
||||
} else {
|
||||
_curSceneIdx = getSceneNumb(_scenes[_curSceneIdx]._choices[_curChoice]._sceneName);
|
||||
_actions.push(ShowScene);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PlumbersGame::processTimer() {
|
||||
debugC(7, kDebugGeneral, "%s", __FUNCTION__);
|
||||
_timerInstalled = false;
|
||||
if (!_endGameFl)
|
||||
_actions.push(Redraw);
|
||||
}
|
||||
|
||||
void PlumbersGame::onTimer(void *arg) {
|
||||
g_system->getTimerManager()->removeTimerProc(onTimer);
|
||||
((PlumbersGame*)arg)->processTimer();
|
||||
}
|
||||
|
||||
void PlumbersGame::initTables() {
|
||||
for (uint i = 0; i < ARRAYSIZE(_scenes); i++) {
|
||||
_scenes[i]._bitmapNum = 0;
|
||||
_scenes[i]._startBitmap = 0;
|
||||
_scenes[i]._decisionChoices = 0;
|
||||
_scenes[i]._sceneName = "";
|
||||
_scenes[i]._waveFilename = "";
|
||||
_scenes[i]._decisionBitmap = "";
|
||||
_scenes[i]._style = Scene::STYLE_PC;
|
||||
for (uint j = 0; j < ARRAYSIZE(_scenes[i]._choices); j++) {
|
||||
_scenes[i]._choices[j]._points = 0;
|
||||
_scenes[i]._choices[j]._skipScene = 0;
|
||||
_scenes[i]._choices[j]._region = Common::Rect(0, 0, 0, 0);
|
||||
_scenes[i]._choices[j]._sceneName = "";
|
||||
}
|
||||
}
|
||||
for (uint i = 0; i < ARRAYSIZE(_bitmaps); i++) {
|
||||
_bitmaps[i]._duration = 0;
|
||||
_bitmaps[i]._filename = "";
|
||||
}
|
||||
}
|
||||
|
||||
int PlumbersGame::getSceneNumb(const Common::String &sName) {
|
||||
debugC(1, kDebugGeneral, "%s : %s", __FUNCTION__, sName.c_str());
|
||||
for (int sCurScene = 0; sCurScene < _totScene; sCurScene++) {
|
||||
if (sName == _scenes[sCurScene]._sceneName)
|
||||
return sCurScene;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // End of namespace Plumbers
|
||||
Reference in New Issue
Block a user