mirror of
https://github.com/libretro/scummvm.git
synced 2025-03-03 08:40:59 +00:00
348 lines
9.0 KiB
C++
348 lines
9.0 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 "common/intrinsics.h"
|
|
|
|
#include "dgds/shell_game.h"
|
|
#include "dgds/dgds.h"
|
|
#include "dgds/globals.h"
|
|
#include "dgds/font.h"
|
|
#include "dgds/includes.h"
|
|
#include "dgds/sound.h"
|
|
|
|
namespace Dgds {
|
|
|
|
ShellGame::ShellGame() : _swapStatus(0), _revealPeaStep(0),
|
|
_currentPeaPosition(0), _lastPass(0), _distractStep(0),
|
|
_distractDelay(0), _state13Counter(0), _swapPea1(0), _swapPea2(0),
|
|
_lastSwapPea1(0), _swapMoveDist(0), _swapMoveStep(0), _swapCount(0),
|
|
_reverseDirection(0), _clockwise(false)
|
|
{
|
|
}
|
|
|
|
void ShellGame::init() {
|
|
DgdsEngine *engine = DgdsEngine::getInstance();
|
|
HocGlobals *globals = static_cast<HocGlobals *>(engine->getGameGlobals());
|
|
assert(globals);
|
|
_shellGameImg.reset(new Image(engine->getResourceManager(), engine->getDecompressor()));
|
|
_shellGameImg->loadBitmap("SHELLGM2.BMP");
|
|
globals->setShellPea(engine->getRandom().getRandomNumber(2));
|
|
_distractStep = 14;
|
|
_distractDelay = 0;
|
|
_state13Counter = 0;
|
|
}
|
|
|
|
static int16 _getState() {
|
|
HocGlobals *globals = static_cast<HocGlobals *>(DgdsEngine::getInstance()->getGameGlobals());
|
|
return globals->getNativeGameState();
|
|
}
|
|
|
|
static void _setState(int16 val) {
|
|
HocGlobals *globals = static_cast<HocGlobals *>(DgdsEngine::getInstance()->getGameGlobals());
|
|
globals->setNativeGameState(val);
|
|
}
|
|
|
|
static int16 _getPeaPosition() {
|
|
HocGlobals *globals = static_cast<HocGlobals *>(DgdsEngine::getInstance()->getGameGlobals());
|
|
return globals->getShellPea();
|
|
}
|
|
|
|
static void _setPeaPosition(int16 val) {
|
|
HocGlobals *globals = static_cast<HocGlobals *>(DgdsEngine::getInstance()->getGameGlobals());
|
|
globals->setShellPea(val);
|
|
}
|
|
|
|
|
|
void ShellGame::drawShellGameStr(int16 count, int16 x, int16 y) const {
|
|
const Common::String countStr = Common::String::format("%d", count);
|
|
DgdsEngine *engine = DgdsEngine::getInstance();
|
|
const DgdsFont *fnt = engine->getFontMan()->getFont(FontManager::k4x5Font);
|
|
fnt->drawString(&engine->getStoredAreaBuffer(), countStr, x, y, 50, 13);
|
|
}
|
|
|
|
void ShellGame::drawShells() const {
|
|
const Common::Rect screenRect(SCREEN_WIDTH, SCREEN_HEIGHT);
|
|
for (uint i = 0; i < 3; i++)
|
|
_shellGameImg->drawBitmap(0, 98 + i * 55, 153, screenRect, DgdsEngine::getInstance()->getStoredAreaBuffer());
|
|
}
|
|
|
|
void ShellGame::shellGameTick() {
|
|
DgdsEngine *engine = DgdsEngine::getInstance();
|
|
HocGlobals *globals = static_cast<HocGlobals *>(engine->getGameGlobals());
|
|
assert(globals);
|
|
|
|
if (!_shellGameImg)
|
|
init();
|
|
|
|
// copy the background to the saved buffer (hack.. but the original does it too)
|
|
engine->getStoredAreaBuffer().blitFrom(engine->getBackgroundBuffer());
|
|
|
|
// Draw the shekels.
|
|
drawShellGameStr(globals->getSheckels(), 131, 123);
|
|
|
|
// Draw the bet
|
|
drawShellGameStr(globals->getShellBet(), 201, 123);
|
|
|
|
update();
|
|
|
|
if (_revealPeaStep) {
|
|
revealPea(false);
|
|
} else {
|
|
if (_swapStatus)
|
|
swapShells(false);
|
|
else
|
|
drawShells();
|
|
}
|
|
}
|
|
|
|
|
|
void ShellGame::update() {
|
|
int16 state = _getState();
|
|
if (state == 1 || state == 7) {
|
|
_currentPeaPosition = _getPeaPosition();
|
|
if (state == 7)
|
|
_currentPeaPosition = _currentPeaPosition / 16;
|
|
_setPeaPosition(_getPeaPosition() & 0xf);
|
|
_revealPeaStep = 1;
|
|
state++;
|
|
} else if (state == 4 || state == 10) {
|
|
_swapStatus = 1;
|
|
_swapCount = 0;
|
|
state++;
|
|
} else if (state == 13) {
|
|
if (_state13Counter) {
|
|
_state13Counter--;
|
|
if (!_state13Counter)
|
|
state = 10;
|
|
} else {
|
|
_state13Counter = 20;
|
|
}
|
|
}
|
|
_setState(state);
|
|
}
|
|
|
|
|
|
void ShellGame::revealPea(bool flag) {
|
|
DgdsEngine *engine = DgdsEngine::getInstance();
|
|
const Common::Rect screenRect(SCREEN_WIDTH, SCREEN_HEIGHT);
|
|
|
|
if (_revealPeaStep == 1)
|
|
engine->_soundPlayer->playSFX(147);
|
|
|
|
uint16 x_offset = 55 * _currentPeaPosition;
|
|
uint16 y_offset;
|
|
if (_revealPeaStep > 40) {
|
|
y_offset = 60 - _revealPeaStep;
|
|
} else if (_revealPeaStep > 20) {
|
|
y_offset = 20;
|
|
} else {
|
|
y_offset = _revealPeaStep;
|
|
}
|
|
|
|
// Draw the pea
|
|
if (_currentPeaPosition == _getPeaPosition())
|
|
_shellGameImg->drawBitmap(1, 112 + x_offset, 166, screenRect, engine->getStoredAreaBuffer());
|
|
|
|
// Draw the shell revealing the pea
|
|
_shellGameImg->drawBitmap(0, 98 + x_offset, 153 - y_offset, screenRect, engine->getStoredAreaBuffer());
|
|
|
|
// Draw the other shells
|
|
for (int i = 0; i < 3; i++) {
|
|
if (i != _currentPeaPosition)
|
|
_shellGameImg->drawBitmap(0, 98 + i * 55, 153, screenRect, engine->getStoredAreaBuffer());
|
|
}
|
|
|
|
if (!flag) {
|
|
if (_lastPass) {
|
|
_lastPass = false;
|
|
_revealPeaStep = 0;
|
|
_setState(_getState() + 1);
|
|
} else {
|
|
if (y_offset == 0)
|
|
_lastPass = true;
|
|
else
|
|
_revealPeaStep++;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
bool ShellGame::checkDistract() {
|
|
DgdsEngine *engine = DgdsEngine::getInstance();
|
|
HocGlobals *globals = static_cast<HocGlobals *>(engine->getGameGlobals());
|
|
|
|
int16 sheckels = globals->getSheckels();
|
|
int16 bet = globals->getShellBet();
|
|
if ((sheckels + bet >= 300)
|
|
|| (sheckels + bet >= 150 && (engine->getRandom().getRandomNumber(256) & 0xc0))
|
|
|| bet > 95
|
|
|| (bet > 45 && (engine->getRandom().getRandomNumber(3)))) {
|
|
_distractStep++;
|
|
if (_distractStep > 21)
|
|
_distractStep = 14;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
void ShellGame::setupSwap() {
|
|
DgdsEngine *engine = DgdsEngine::getInstance();
|
|
do {
|
|
_swapPea1 = engine->getRandom().getRandomNumber(2);
|
|
} while (_swapPea1 == _lastSwapPea1);
|
|
|
|
_lastSwapPea1 = _swapPea1;
|
|
|
|
if (_swapPea1 == 0) {
|
|
_swapPea2 = 1;
|
|
} else if (_swapPea1 == 1) {
|
|
_swapPea2 = 2;
|
|
} else {
|
|
_swapPea1 = 0;
|
|
_swapPea2 = 2;
|
|
}
|
|
|
|
if (_getPeaPosition() == _swapPea1) {
|
|
_setPeaPosition(_swapPea2);
|
|
} else if (_getPeaPosition() == _swapPea2) {
|
|
_setPeaPosition(_swapPea1);
|
|
}
|
|
|
|
_swapMoveDist = (_swapPea2 - _swapPea1) * 55;
|
|
_lastPass = false;
|
|
_swapMoveStep = 0;
|
|
_swapStatus = 2;
|
|
}
|
|
|
|
|
|
void ShellGame::swapShells(bool flag) {
|
|
DgdsEngine *engine = DgdsEngine::getInstance();
|
|
const Common::Rect screenRect(SCREEN_WIDTH, SCREEN_HEIGHT);
|
|
|
|
if (!flag) {
|
|
if (_swapStatus == 1) {
|
|
engine->_soundPlayer->playSFX(145);
|
|
setupSwap();
|
|
_clockwise = (bool)(engine->getRandom().getRandomNumber(255) & 0x40);
|
|
_reverseDirection = 0;
|
|
}
|
|
|
|
uint16 move_speed = (2 << engine->getDifficulty()) + 2;
|
|
if (_getState() >= 10 && _getState() <= 12)
|
|
move_speed++;
|
|
if (!_lastPass) {
|
|
_swapMoveStep += move_speed;
|
|
if (abs(_swapPea1 - _swapPea2) != 1)
|
|
_swapMoveStep += move_speed;
|
|
if (_swapMoveStep > _swapMoveDist)
|
|
_swapMoveStep = _swapMoveDist;
|
|
}
|
|
}
|
|
|
|
uint16 xbase1 = 98 + _swapPea1 * 55;
|
|
uint16 xbase2 = 98 + _swapPea2 * 55;
|
|
|
|
double move = ((double)_swapMoveStep / _swapMoveDist) * M_PI;
|
|
uint16 y_offset;
|
|
if (abs(_swapPea1 - _swapPea2) == 1)
|
|
y_offset = 26;
|
|
else
|
|
y_offset = 28;
|
|
|
|
y_offset = (int16)(y_offset * sin(move));
|
|
|
|
for (int i = 0; i < 3; i++) {
|
|
if (i != _swapPea1 && i != _swapPea2)
|
|
_shellGameImg->drawBitmap(0, 98 + i * 55, 153, screenRect, engine->getStoredAreaBuffer());
|
|
}
|
|
|
|
if (!flag) {
|
|
if ((_reverseDirection == 0) && (_swapMoveStep >= (_swapMoveDist / 2))) {
|
|
if (engine->getRandom().getRandomNumber(7)) {
|
|
_reverseDirection = -1;
|
|
} else {
|
|
_reverseDirection = 1;
|
|
if (_getPeaPosition() == _swapPea1)
|
|
_setPeaPosition(_swapPea2);
|
|
else if (_getPeaPosition() == _swapPea2)
|
|
_setPeaPosition(_swapPea1);
|
|
}
|
|
}
|
|
}
|
|
|
|
uint16 x1,x2,y1,y2;
|
|
if (_reverseDirection <= 0) {
|
|
x1 = xbase1 + _swapMoveStep;
|
|
x2 = xbase2 - _swapMoveStep;
|
|
} else {
|
|
x1 = xbase2 - _swapMoveStep;
|
|
x2 = xbase1 + _swapMoveStep;
|
|
}
|
|
|
|
if (_clockwise) {
|
|
y1 = 153 - y_offset;
|
|
y2 = 153 + y_offset;
|
|
} else {
|
|
y1 = 153 + y_offset;
|
|
y2 = 153 - y_offset;
|
|
}
|
|
|
|
_shellGameImg->drawBitmap(0, x1, y1, screenRect, engine->getStoredAreaBuffer());
|
|
_shellGameImg->drawBitmap(0, x2, y2, screenRect, engine->getStoredAreaBuffer());
|
|
|
|
if (!flag) {
|
|
int16 state = _getState();
|
|
if (_lastPass) {
|
|
_lastPass = false;
|
|
if (state == 11)
|
|
_setState(0);
|
|
else
|
|
_setState(6);
|
|
_swapStatus = 0;
|
|
} else if (_distractDelay) {
|
|
_distractDelay--;
|
|
} else if (_swapMoveStep == _swapMoveDist) {
|
|
_swapCount++;
|
|
if (state == 11) {
|
|
_lastPass = true;
|
|
} else if (_swapCount == 8 && checkDistract()) {
|
|
_setState(_distractStep);
|
|
_distractDelay = 20;
|
|
} else {
|
|
if (_swapCount < 12 || engine->getRandom().getRandomNumber(7) || state >= 14)
|
|
_swapStatus = 1;
|
|
else
|
|
_lastPass = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void ShellGame::shellGameEnd() {
|
|
_shellGameImg.reset();
|
|
}
|
|
|
|
} // end namespace Dgds
|