2015-03-15 16:52:55 -04:00
|
|
|
/* 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.
|
2015-05-09 18:04:13 +02:00
|
|
|
*
|
2015-03-15 16:52:55 -04:00
|
|
|
* 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.
|
2015-05-09 18:04:13 +02:00
|
|
|
*
|
2015-03-15 16:52:55 -04:00
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2015-08-06 20:40:20 -04:00
|
|
|
#include "sherlock/scalpel/scalpel_darts.h"
|
2015-03-18 23:01:47 -04:00
|
|
|
#include "sherlock/scalpel/scalpel.h"
|
2015-03-15 16:52:55 -04:00
|
|
|
|
|
|
|
namespace Sherlock {
|
|
|
|
|
2015-03-18 23:01:47 -04:00
|
|
|
namespace Scalpel {
|
|
|
|
|
2015-04-20 01:07:54 -05:00
|
|
|
enum {
|
|
|
|
STATUS_INFO_X = 218,
|
|
|
|
STATUS_INFO_Y = 53,
|
|
|
|
DART_INFO_X = 218,
|
|
|
|
DART_INFO_Y = 103,
|
|
|
|
DARTBARHX = 35,
|
|
|
|
DARTHORIZY = 190,
|
|
|
|
DARTBARVX = 1,
|
|
|
|
DARTHEIGHTY = 25,
|
|
|
|
DARTBARSIZE = 150,
|
|
|
|
DART_BAR_FORE = 8
|
|
|
|
};
|
|
|
|
|
|
|
|
enum {
|
|
|
|
DART_COL_FORE = 5,
|
|
|
|
PLAYER_COLOR = 11
|
|
|
|
};
|
2015-05-18 19:15:17 -04:00
|
|
|
#define OPPONENTS_COUNT 4
|
2015-04-20 01:07:54 -05:00
|
|
|
|
2015-05-18 19:15:17 -04:00
|
|
|
const char *const OPPONENT_NAMES[OPPONENTS_COUNT] = {
|
|
|
|
"Skipper", "Willy", "Micky", "Tom"
|
2015-04-20 01:07:54 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
/*----------------------------------------------------------------*/
|
|
|
|
|
|
|
|
Darts::Darts(ScalpelEngine *vm) : _vm(vm) {
|
|
|
|
_dartImages = nullptr;
|
|
|
|
_level = 0;
|
|
|
|
_computerPlayer = 1;
|
|
|
|
_playerDartMode = false;
|
|
|
|
_dartScore1 = _dartScore2 = 0;
|
|
|
|
_roundNumber = 0;
|
|
|
|
_playerDartMode = false;
|
|
|
|
_roundScore = 0;
|
2015-04-29 18:02:08 -10:00
|
|
|
_oldDartButtons = false;
|
2015-04-20 01:07:54 -05:00
|
|
|
}
|
|
|
|
|
2015-03-18 23:01:47 -04:00
|
|
|
void Darts::playDarts() {
|
2015-04-21 01:12:16 -05:00
|
|
|
Events &events = *_vm->_events;
|
2015-04-20 01:07:54 -05:00
|
|
|
Screen &screen = *_vm->_screen;
|
|
|
|
int playerNumber = 0;
|
|
|
|
int lastDart;
|
|
|
|
|
|
|
|
// Change the font
|
|
|
|
int oldFont = screen.fontNumber();
|
2015-04-29 18:02:08 -10:00
|
|
|
screen.setFont(2);
|
2015-04-20 01:07:54 -05:00
|
|
|
|
|
|
|
loadDarts();
|
|
|
|
initDarts();
|
|
|
|
|
2015-04-21 01:12:16 -05:00
|
|
|
bool done = false;
|
2015-04-20 01:07:54 -05:00
|
|
|
do {
|
2015-05-07 19:21:55 +02:00
|
|
|
int score, roundStartScore;
|
2015-04-20 01:07:54 -05:00
|
|
|
roundStartScore = score = playerNumber == 0 ? _dartScore1 : _dartScore2;
|
2015-05-07 19:33:44 +02:00
|
|
|
|
2015-04-20 01:07:54 -05:00
|
|
|
// Show player details
|
|
|
|
showNames(playerNumber);
|
|
|
|
showStatus(playerNumber);
|
|
|
|
_roundScore = 0;
|
|
|
|
|
2015-04-29 18:02:08 -10:00
|
|
|
if (_vm->shouldQuit())
|
|
|
|
return;
|
|
|
|
|
2015-04-20 01:07:54 -05:00
|
|
|
for (int idx = 0; idx < 3; ++idx) {
|
|
|
|
// Throw a single dart
|
|
|
|
if (_computerPlayer == 1)
|
|
|
|
lastDart = throwDart(idx + 1, playerNumber * 2);
|
|
|
|
else if (_computerPlayer == 2)
|
|
|
|
lastDart = throwDart(idx + 1, playerNumber + 1);
|
|
|
|
else
|
|
|
|
lastDart = throwDart(idx + 1, 0);
|
|
|
|
|
|
|
|
score -= lastDart;
|
|
|
|
_roundScore += lastDart;
|
|
|
|
|
2016-03-10 21:51:47 -05:00
|
|
|
screen._backBuffer1.SHblitFrom(screen._backBuffer2, Common::Point(DART_INFO_X, DART_INFO_Y - 1),
|
2015-04-21 01:12:16 -05:00
|
|
|
Common::Rect(DART_INFO_X, DART_INFO_Y - 1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
|
|
|
|
screen.print(Common::Point(DART_INFO_X, DART_INFO_Y), DART_COL_FORE, "Dart # %d", idx + 1);
|
|
|
|
screen.print(Common::Point(DART_INFO_X, DART_INFO_Y + 10), DART_COL_FORE, "Scored %d points", lastDart);
|
|
|
|
|
|
|
|
if (score != 0 && playerNumber == 0)
|
|
|
|
screen.print(Common::Point(DART_INFO_X, DART_INFO_Y + 30), DART_COL_FORE, "Press a key");
|
|
|
|
|
|
|
|
if (score == 0) {
|
|
|
|
// Some-one has won
|
|
|
|
screen.print(Common::Point(DART_INFO_X, DART_INFO_Y + 20), PLAYER_COLOR, "GAME OVER!");
|
|
|
|
|
|
|
|
if (playerNumber == 0) {
|
|
|
|
screen.print(Common::Point(DART_INFO_X, DART_INFO_Y + 30), PLAYER_COLOR, "Holmes Wins!");
|
2015-05-18 19:15:17 -04:00
|
|
|
if (_level < OPPONENTS_COUNT)
|
2015-06-11 08:32:31 -04:00
|
|
|
_vm->setFlagsDirect(318 + _level);
|
2015-04-21 01:12:16 -05:00
|
|
|
} else {
|
|
|
|
screen.print(Common::Point(DART_INFO_X, DART_INFO_Y + 30), PLAYER_COLOR, "%s Wins!", _opponent.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
screen.print(Common::Point(DART_INFO_X, DART_INFO_Y + 4), DART_COL_FORE, "Press a key");
|
|
|
|
|
|
|
|
idx = 10;
|
|
|
|
done = true;
|
|
|
|
} else if (score < 0) {
|
|
|
|
screen.print(Common::Point(DART_INFO_X, DART_INFO_Y + 20), PLAYER_COLOR, "BUSTED!");
|
|
|
|
|
|
|
|
idx = 10;
|
|
|
|
score = roundStartScore;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (playerNumber == 0)
|
|
|
|
_dartScore1 = score;
|
|
|
|
else
|
|
|
|
_dartScore2 = score;
|
|
|
|
|
|
|
|
showStatus(playerNumber);
|
|
|
|
events.clearKeyboard();
|
2015-04-20 01:07:54 -05:00
|
|
|
|
2015-04-21 01:12:16 -05:00
|
|
|
if ((playerNumber == 0 && _computerPlayer == 1) || _computerPlayer == 0 || done) {
|
|
|
|
int dartKey;
|
|
|
|
while (!(dartKey = dartHit()) && !_vm->shouldQuit())
|
|
|
|
events.delay(10);
|
|
|
|
|
|
|
|
if (dartKey == Common::KEYCODE_ESCAPE) {
|
|
|
|
idx = 10;
|
|
|
|
done = true;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
events.wait(20);
|
|
|
|
}
|
|
|
|
|
2016-03-10 21:51:47 -05:00
|
|
|
screen._backBuffer1.SHblitFrom(screen._backBuffer2, Common::Point(DART_INFO_X, DART_INFO_Y - 1),
|
2015-04-21 01:12:16 -05:00
|
|
|
Common::Rect(DART_INFO_X, DART_INFO_Y - 1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
|
|
|
|
screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
|
2015-04-20 01:07:54 -05:00
|
|
|
}
|
|
|
|
|
2015-04-21 01:12:16 -05:00
|
|
|
playerNumber ^= 1;
|
|
|
|
if (!playerNumber)
|
|
|
|
++_roundNumber;
|
|
|
|
|
|
|
|
done |= _vm->shouldQuit();
|
2015-04-20 01:07:54 -05:00
|
|
|
|
2015-04-21 01:12:16 -05:00
|
|
|
if (!done) {
|
2016-03-10 21:51:47 -05:00
|
|
|
screen._backBuffer2.SHblitFrom((*_dartImages)[0], Common::Point(0, 0));
|
|
|
|
screen._backBuffer1.SHblitFrom(screen._backBuffer2);
|
2015-04-21 01:12:16 -05:00
|
|
|
screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
|
|
|
|
}
|
|
|
|
} while (!done);
|
|
|
|
|
|
|
|
closeDarts();
|
|
|
|
screen.fadeToBlack();
|
|
|
|
|
|
|
|
// Restore font
|
|
|
|
screen.setFont(oldFont);
|
2015-03-15 16:52:55 -04:00
|
|
|
}
|
|
|
|
|
2015-04-20 01:07:54 -05:00
|
|
|
void Darts::loadDarts() {
|
|
|
|
Screen &screen = *_vm->_screen;
|
|
|
|
|
|
|
|
_dartImages = new ImageFile("darts.vgs");
|
2015-04-29 18:02:08 -10:00
|
|
|
screen.setPalette(_dartImages->_palette);
|
|
|
|
|
2016-03-10 21:51:47 -05:00
|
|
|
screen._backBuffer1.SHblitFrom((*_dartImages)[0], Common::Point(0, 0));
|
2015-04-20 01:07:54 -05:00
|
|
|
screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Darts::initDarts() {
|
|
|
|
_dartScore1 = _dartScore2 = 301;
|
|
|
|
_roundNumber = 1;
|
|
|
|
|
|
|
|
if (_level == 9) {
|
|
|
|
// No computer players
|
|
|
|
_computerPlayer = 0;
|
|
|
|
_level = 0;
|
|
|
|
} else if (_level == 8) {
|
|
|
|
_level = _vm->getRandomNumber(3);
|
|
|
|
_computerPlayer = 2;
|
|
|
|
} else {
|
|
|
|
// Check flags for opponents
|
2015-05-18 19:15:17 -04:00
|
|
|
for (int idx = 0; idx < OPPONENTS_COUNT; ++idx) {
|
2015-04-20 01:07:54 -05:00
|
|
|
if (_vm->readFlags(314 + idx))
|
|
|
|
_level = idx;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_opponent = OPPONENT_NAMES[_level];
|
|
|
|
}
|
|
|
|
|
2015-04-21 01:12:16 -05:00
|
|
|
void Darts::closeDarts() {
|
|
|
|
delete _dartImages;
|
|
|
|
_dartImages = nullptr;
|
|
|
|
}
|
|
|
|
|
2015-04-20 01:07:54 -05:00
|
|
|
void Darts::showNames(int playerNum) {
|
|
|
|
Screen &screen = *_vm->_screen;
|
|
|
|
byte color = playerNum == 0 ? PLAYER_COLOR : DART_COL_FORE;
|
|
|
|
|
|
|
|
// Print Holmes first
|
|
|
|
if (playerNum == 0)
|
|
|
|
screen.print(Common::Point(STATUS_INFO_X, STATUS_INFO_Y), PLAYER_COLOR + 3, "Holmes");
|
|
|
|
else
|
|
|
|
screen.print(Common::Point(STATUS_INFO_X, STATUS_INFO_Y), color, "Holmes");
|
|
|
|
|
|
|
|
screen._backBuffer1.fillRect(Common::Rect(STATUS_INFO_X, STATUS_INFO_Y + 10,
|
|
|
|
STATUS_INFO_X + 31, STATUS_INFO_Y + 12), color);
|
|
|
|
screen.slamArea(STATUS_INFO_X, STATUS_INFO_Y + 10, 31, 12);
|
|
|
|
|
|
|
|
// Second player
|
|
|
|
color = playerNum == 1 ? PLAYER_COLOR : DART_COL_FORE;
|
|
|
|
|
|
|
|
if (playerNum != 0)
|
2015-04-29 18:02:08 -10:00
|
|
|
screen.print(Common::Point(STATUS_INFO_X + 50, STATUS_INFO_Y), PLAYER_COLOR + 3,
|
2015-05-20 08:28:12 -04:00
|
|
|
"%s", _opponent.c_str());
|
2015-04-20 01:07:54 -05:00
|
|
|
else
|
2015-04-29 18:02:08 -10:00
|
|
|
screen.print(Common::Point(STATUS_INFO_X + 50, STATUS_INFO_Y), color,
|
2015-05-20 08:28:12 -04:00
|
|
|
"%s", _opponent.c_str());
|
2015-04-20 01:07:54 -05:00
|
|
|
|
|
|
|
screen._backBuffer1.fillRect(Common::Rect(STATUS_INFO_X + 50, STATUS_INFO_Y + 10,
|
2015-04-29 18:02:08 -10:00
|
|
|
STATUS_INFO_X + 81, STATUS_INFO_Y + 12), color);
|
2015-04-20 01:07:54 -05:00
|
|
|
screen.slamArea(STATUS_INFO_X + 50, STATUS_INFO_Y + 10, 81, 12);
|
|
|
|
|
|
|
|
// Make a copy of the back buffer to the secondary one
|
2016-03-10 21:51:47 -05:00
|
|
|
screen._backBuffer2.SHblitFrom(screen._backBuffer1);
|
2015-04-20 01:07:54 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void Darts::showStatus(int playerNum) {
|
|
|
|
Screen &screen = *_vm->_screen;
|
|
|
|
byte color;
|
|
|
|
|
2015-04-29 18:02:08 -10:00
|
|
|
// Copy scoring screen from secondary back buffer. This will erase any previously displayed status/score info
|
2016-03-10 21:51:47 -05:00
|
|
|
screen._backBuffer1.SHblitFrom(screen._backBuffer2, Common::Point(STATUS_INFO_X, STATUS_INFO_Y + 10),
|
2015-04-29 18:02:08 -10:00
|
|
|
Common::Rect(STATUS_INFO_X, STATUS_INFO_Y + 10, SHERLOCK_SCREEN_WIDTH, STATUS_INFO_Y + 48));
|
2015-04-20 01:07:54 -05:00
|
|
|
|
|
|
|
color = (playerNum == 0) ? PLAYER_COLOR : DART_COL_FORE;
|
|
|
|
screen.print(Common::Point(STATUS_INFO_X + 6, STATUS_INFO_Y + 13), color, "%d", _dartScore1);
|
|
|
|
|
|
|
|
color = (playerNum == 1) ? PLAYER_COLOR : DART_COL_FORE;
|
|
|
|
screen.print(Common::Point(STATUS_INFO_X + 56, STATUS_INFO_Y + 13), color, "%d", _dartScore2);
|
|
|
|
screen.print(Common::Point(STATUS_INFO_X, STATUS_INFO_Y + 25), PLAYER_COLOR, "Round: %d", _roundNumber);
|
|
|
|
screen.print(Common::Point(STATUS_INFO_X, STATUS_INFO_Y + 35), PLAYER_COLOR, "Turn Total: %d", _roundScore);
|
|
|
|
screen.slamRect(Common::Rect(STATUS_INFO_X, STATUS_INFO_Y + 10, SHERLOCK_SCREEN_WIDTH, STATUS_INFO_Y + 48));
|
|
|
|
}
|
|
|
|
|
|
|
|
int Darts::throwDart(int dartNum, int computer) {
|
|
|
|
Events &events = *_vm->_events;
|
|
|
|
Screen &screen = *_vm->_screen;
|
|
|
|
Common::Point targetNum;
|
|
|
|
int width, height;
|
|
|
|
|
|
|
|
events.clearKeyboard();
|
2015-05-07 19:33:44 +02:00
|
|
|
|
2015-04-20 01:07:54 -05:00
|
|
|
erasePowerBars();
|
|
|
|
screen.print(Common::Point(DART_INFO_X, DART_INFO_Y), DART_COL_FORE, "Dart # %d", dartNum);
|
|
|
|
|
|
|
|
if (!computer) {
|
|
|
|
screen.print(Common::Point(DART_INFO_X, DART_INFO_Y + 10), DART_COL_FORE, "Hit a key");
|
|
|
|
screen.print(Common::Point(DART_INFO_X, DART_INFO_Y + 18), DART_COL_FORE, "to start");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!computer) {
|
|
|
|
while (!_vm->shouldQuit() && !dartHit())
|
|
|
|
;
|
|
|
|
} else {
|
|
|
|
events.delay(10);
|
|
|
|
}
|
|
|
|
|
2015-04-29 18:02:08 -10:00
|
|
|
if (_vm->shouldQuit())
|
|
|
|
return 0;
|
|
|
|
|
2016-03-10 21:51:47 -05:00
|
|
|
screen._backBuffer1.SHblitFrom(screen._backBuffer2, Common::Point(DART_INFO_X, DART_INFO_Y - 1),
|
2015-04-20 01:07:54 -05:00
|
|
|
Common::Rect(DART_INFO_X, DART_INFO_Y - 1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
|
|
|
|
screen.slamRect(Common::Rect(DART_INFO_X, DART_INFO_Y - 1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
|
|
|
|
|
|
|
|
// If it's a computer player, choose a dart destination
|
|
|
|
if (computer)
|
|
|
|
targetNum = getComputerDartDest(computer - 1);
|
2015-05-07 19:33:44 +02:00
|
|
|
|
2015-04-21 01:12:16 -05:00
|
|
|
width = doPowerBar(Common::Point(DARTBARHX, DARTHORIZY), DART_BAR_FORE, targetNum.x, false);
|
|
|
|
height = 101 - doPowerBar(Common::Point(DARTBARVX, DARTHEIGHTY), DART_BAR_FORE, targetNum.y, true);
|
2015-05-07 19:33:44 +02:00
|
|
|
|
2015-04-20 01:07:54 -05:00
|
|
|
// For human players, slight y adjustment
|
|
|
|
if (computer == 0)
|
2015-04-29 18:02:08 -10:00
|
|
|
height += 2;
|
2015-04-20 01:07:54 -05:00
|
|
|
|
2015-04-29 18:02:08 -10:00
|
|
|
// Copy the bars to the secondary back buffer so that they remain fixed at their selected values
|
|
|
|
// whilst the dart is being animated at being thrown at the board
|
2016-03-10 21:51:47 -05:00
|
|
|
screen._backBuffer2.SHblitFrom(screen._backBuffer1, Common::Point(DARTBARHX - 1, DARTHORIZY - 1),
|
2015-04-20 01:07:54 -05:00
|
|
|
Common::Rect(DARTBARHX - 1, DARTHORIZY - 1, DARTBARHX + DARTBARSIZE + 3, DARTHORIZY + 10));
|
2016-03-10 21:51:47 -05:00
|
|
|
screen._backBuffer2.SHblitFrom(screen._backBuffer1, Common::Point(DARTBARVX - 1, DARTHEIGHTY - 1),
|
2015-04-20 01:07:54 -05:00
|
|
|
Common::Rect(DARTBARVX - 1, DARTHEIGHTY - 1, DARTBARVX + 11, DARTHEIGHTY + DARTBARSIZE + 3));
|
|
|
|
|
2015-04-29 18:02:08 -10:00
|
|
|
// Convert height and width to relative range of -50 to 50, where 0,0 is the exact centre of the board
|
2015-04-20 01:07:54 -05:00
|
|
|
height -= 50;
|
|
|
|
width -= 50;
|
|
|
|
|
|
|
|
Common::Point dartPos(111 + width * 2, 99 + height * 2);
|
|
|
|
drawDartThrow(dartPos);
|
|
|
|
|
|
|
|
return dartScore(dartPos);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Darts::drawDartThrow(const Common::Point &pt) {
|
2015-04-21 01:12:16 -05:00
|
|
|
Events &events = *_vm->_events;
|
|
|
|
Screen &screen = *_vm->_screen;
|
|
|
|
Common::Point pos(pt.x, pt.y + 2);
|
|
|
|
Common::Rect oldDrawBounds;
|
|
|
|
int delta = 9;
|
|
|
|
|
2015-04-29 18:02:08 -10:00
|
|
|
for (int idx = 4; idx < 23; ++idx) {
|
2015-05-19 09:10:35 -04:00
|
|
|
ImageFrame &frame = (*_dartImages)[idx];
|
2015-04-21 01:12:16 -05:00
|
|
|
|
|
|
|
// Adjust draw position for animating dart
|
2015-04-29 18:02:08 -10:00
|
|
|
if (idx < 13)
|
2015-04-21 01:12:16 -05:00
|
|
|
pos.y -= delta--;
|
2015-04-29 18:02:08 -10:00
|
|
|
else if (idx == 13)
|
2015-04-21 01:12:16 -05:00
|
|
|
delta = 1;
|
|
|
|
else
|
|
|
|
pos.y += delta++;
|
|
|
|
|
|
|
|
// Draw the dart
|
2015-05-19 09:10:35 -04:00
|
|
|
Common::Point drawPos(pos.x - frame._width / 2, pos.y - frame._height);
|
2016-03-10 21:51:47 -05:00
|
|
|
screen._backBuffer1.SHtransBlitFrom(frame, drawPos);
|
2015-05-19 09:10:35 -04:00
|
|
|
screen.slamArea(drawPos.x, drawPos.y, frame._width, frame._height);
|
2015-04-21 01:12:16 -05:00
|
|
|
|
2015-05-21 19:00:22 -04:00
|
|
|
// Handle erasing old dart frame area
|
2015-04-21 01:12:16 -05:00
|
|
|
if (!oldDrawBounds.isEmpty())
|
|
|
|
screen.slamRect(oldDrawBounds);
|
|
|
|
|
2015-05-19 09:10:35 -04:00
|
|
|
oldDrawBounds = Common::Rect(drawPos.x, drawPos.y, drawPos.x + frame._width, drawPos.y + frame._height);
|
2016-03-10 21:51:47 -05:00
|
|
|
screen._backBuffer1.SHblitFrom(screen._backBuffer2, drawPos, oldDrawBounds);
|
2015-04-21 01:12:16 -05:00
|
|
|
|
|
|
|
events.wait(2);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Draw dart in final "stuck to board" form
|
2016-03-10 21:51:47 -05:00
|
|
|
screen._backBuffer1.SHtransBlitFrom((*_dartImages)[22], Common::Point(oldDrawBounds.left, oldDrawBounds.top));
|
|
|
|
screen._backBuffer2.SHtransBlitFrom((*_dartImages)[22], Common::Point(oldDrawBounds.left, oldDrawBounds.top));
|
2015-04-21 01:12:16 -05:00
|
|
|
screen.slamRect(oldDrawBounds);
|
2015-04-20 01:07:54 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void Darts::erasePowerBars() {
|
|
|
|
Screen &screen = *_vm->_screen;
|
|
|
|
|
2015-06-13 12:20:17 +02:00
|
|
|
screen._backBuffer1.fillRect(Common::Rect(DARTBARHX, DARTHORIZY, DARTBARHX + DARTBARSIZE, DARTHORIZY + 10), BLACK);
|
|
|
|
screen._backBuffer1.fillRect(Common::Rect(DARTBARVX, DARTHEIGHTY, DARTBARVX + 10, DARTHEIGHTY + DARTBARSIZE), BLACK);
|
2016-03-10 21:51:47 -05:00
|
|
|
screen._backBuffer1.SHtransBlitFrom((*_dartImages)[2], Common::Point(DARTBARHX - 1, DARTHORIZY - 1));
|
|
|
|
screen._backBuffer1.SHtransBlitFrom((*_dartImages)[3], Common::Point(DARTBARVX - 1, DARTHEIGHTY - 1));
|
2015-04-20 01:07:54 -05:00
|
|
|
screen.slamArea(DARTBARHX - 1, DARTHORIZY - 1, DARTBARSIZE + 3, 11);
|
|
|
|
screen.slamArea(DARTBARVX - 1, DARTHEIGHTY - 1, 11, DARTBARSIZE + 3);
|
|
|
|
}
|
|
|
|
|
2015-04-21 01:12:16 -05:00
|
|
|
int Darts::doPowerBar(const Common::Point &pt, byte color, int goToPower, bool isVertical) {
|
|
|
|
Events &events = *_vm->_events;
|
|
|
|
Screen &screen = *_vm->_screen;
|
|
|
|
bool done;
|
|
|
|
int idx = 0;
|
|
|
|
|
|
|
|
events.clearEvents();
|
2015-08-13 20:01:35 -04:00
|
|
|
events.delay(100);
|
2015-04-21 01:12:16 -05:00
|
|
|
|
|
|
|
// Display loop
|
|
|
|
do {
|
|
|
|
done = _vm->shouldQuit() || idx >= DARTBARSIZE;
|
|
|
|
|
|
|
|
if (idx == (goToPower - 1))
|
|
|
|
// Reached target power for a computer player
|
|
|
|
done = true;
|
|
|
|
else if (goToPower == 0) {
|
2015-08-14 08:26:06 +02:00
|
|
|
// Check for press
|
2015-04-21 01:12:16 -05:00
|
|
|
if (dartHit())
|
|
|
|
done = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isVertical) {
|
|
|
|
screen._backBuffer1.hLine(pt.x, pt.y + DARTBARSIZE - 1 - idx, pt.x + 8, color);
|
2016-03-10 21:51:47 -05:00
|
|
|
screen._backBuffer1.SHtransBlitFrom((*_dartImages)[3], Common::Point(pt.x - 1, pt.y - 1));
|
2015-04-21 01:12:16 -05:00
|
|
|
screen.slamArea(pt.x, pt.y + DARTBARSIZE - 1 - idx, 8, 2);
|
|
|
|
} else {
|
|
|
|
screen._backBuffer1.vLine(pt.x + idx, pt.y, pt.y + 8, color);
|
2016-03-10 21:51:47 -05:00
|
|
|
screen._backBuffer1.SHtransBlitFrom((*_dartImages)[2], Common::Point(pt.x - 1, pt.y - 1));
|
2015-04-21 01:12:16 -05:00
|
|
|
screen.slamArea(pt.x + idx, pt.y, 1, 8);
|
|
|
|
}
|
|
|
|
|
2015-08-13 20:01:35 -04:00
|
|
|
if (!(idx % 8))
|
2015-05-19 22:30:47 +02:00
|
|
|
events.wait(1);
|
|
|
|
|
2015-04-21 01:12:16 -05:00
|
|
|
++idx;
|
|
|
|
} while (!done);
|
|
|
|
|
|
|
|
return MIN(idx * 100 / DARTBARSIZE, 100);
|
2015-04-20 01:07:54 -05:00
|
|
|
}
|
|
|
|
|
2015-08-01 17:03:15 -04:00
|
|
|
int Darts::dartHit() {
|
2015-04-20 01:07:54 -05:00
|
|
|
Events &events = *_vm->_events;
|
|
|
|
|
2015-04-29 18:02:08 -10:00
|
|
|
// Process pending events
|
|
|
|
events.pollEventsAndWait();
|
2015-04-21 01:12:16 -05:00
|
|
|
|
2015-04-29 18:02:08 -10:00
|
|
|
if (events.kbHit()) {
|
2015-08-01 17:03:15 -04:00
|
|
|
// Key was pressed, so return it
|
|
|
|
Common::KeyState keyState = events.getKey();
|
|
|
|
return keyState.keycode;
|
2015-04-20 01:07:54 -05:00
|
|
|
}
|
2015-05-07 19:33:44 +02:00
|
|
|
|
2015-04-29 18:02:08 -10:00
|
|
|
_oldDartButtons = events._pressed;
|
2015-04-20 01:07:54 -05:00
|
|
|
events.setButtonState();
|
2015-04-29 18:02:08 -10:00
|
|
|
|
|
|
|
// Only return true if the mouse button is newly pressed
|
|
|
|
return (events._pressed && !_oldDartButtons) ? 1 : 0;
|
2015-04-20 01:07:54 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
int Darts::dartScore(const Common::Point &pt) {
|
2015-04-21 01:12:16 -05:00
|
|
|
Common::Point pos(pt.x - 37, pt.y - 33);
|
2015-04-29 18:11:35 -10:00
|
|
|
Graphics::Surface &scoreImg = (*_dartImages)[1]._frame;
|
2015-04-21 01:12:16 -05:00
|
|
|
|
2015-04-29 18:11:35 -10:00
|
|
|
if (pos.x < 0 || pos.y < 0 || pos.x >= scoreImg.w || pos.y >= scoreImg.h)
|
2015-04-21 01:12:16 -05:00
|
|
|
// Not on the board
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
// On board, so get the score from the pixel at that position
|
2015-04-29 18:11:35 -10:00
|
|
|
int score = *(const byte *)scoreImg.getBasePtr(pos.x, pos.y);
|
2015-04-21 01:12:16 -05:00
|
|
|
return score;
|
2015-04-20 01:07:54 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
Common::Point Darts::getComputerDartDest(int playerNum) {
|
|
|
|
Common::Point target;
|
|
|
|
int score = playerNum == 0 ? _dartScore1 : _dartScore2;
|
|
|
|
|
|
|
|
if (score > 50) {
|
|
|
|
// Aim for the bullseye
|
|
|
|
target.x = target.y = 76;
|
|
|
|
|
|
|
|
if (_level <= 1 && _vm->getRandomNumber(1) == 1) {
|
|
|
|
// Introduce margin of error
|
|
|
|
target.x += _vm->getRandomNumber(21) - 10;
|
|
|
|
target.y += _vm->getRandomNumber(21) - 10;
|
|
|
|
}
|
|
|
|
} else {
|
2015-05-07 19:21:55 +02:00
|
|
|
int aim = score;
|
2015-04-20 01:07:54 -05:00
|
|
|
|
|
|
|
bool done;
|
|
|
|
Common::Point pt;
|
|
|
|
do {
|
|
|
|
done = findNumberOnBoard(aim, pt);
|
|
|
|
--aim;
|
|
|
|
} while (!done);
|
|
|
|
|
|
|
|
target.x = 75 + ((target.x - 75) * 20 / 27);
|
|
|
|
target.y = 75 + ((target.y - 75) * 2 / 3);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Pick a level of accuracy. The higher the level, the more accurate their throw will be
|
|
|
|
int accuracy = _vm->getRandomNumber(10) + _level * 2;
|
|
|
|
|
|
|
|
if (accuracy <= 2) {
|
|
|
|
target.x += _vm->getRandomNumber(71) - 35;
|
|
|
|
target.y += _vm->getRandomNumber(71) - 35;
|
|
|
|
} else if (accuracy <= 4) {
|
|
|
|
target.x += _vm->getRandomNumber(51) - 25;
|
|
|
|
target.y += _vm->getRandomNumber(51) - 25;
|
|
|
|
} else if (accuracy <= 6) {
|
|
|
|
target.x += _vm->getRandomNumber(31) - 15;
|
|
|
|
target.y += _vm->getRandomNumber(31) - 15;
|
|
|
|
} else if (accuracy <= 8) {
|
|
|
|
target.x += _vm->getRandomNumber(21) - 10;
|
|
|
|
target.y += _vm->getRandomNumber(21) - 10;
|
|
|
|
} else if (accuracy <= 10) {
|
|
|
|
target.x += _vm->getRandomNumber(11) - 5;
|
|
|
|
target.y += _vm->getRandomNumber(11) - 5;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (target.x < 1)
|
|
|
|
target.x = 1;
|
|
|
|
if (target.y < 1)
|
|
|
|
target.y = 1;
|
|
|
|
|
|
|
|
return target;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Darts::findNumberOnBoard(int aim, Common::Point &pt) {
|
2015-04-29 18:02:08 -10:00
|
|
|
ImageFrame &board = (*_dartImages)[1];
|
2015-04-20 01:07:54 -05:00
|
|
|
|
|
|
|
// Scan board image for the special "center" pixels
|
|
|
|
bool done = false;
|
|
|
|
for (int yp = 0; yp < 132 && !done; ++yp) {
|
|
|
|
const byte *srcP = (const byte *)board._frame.getBasePtr(0, yp);
|
|
|
|
for (int xp = 0; xp < 147 && !done; ++xp, ++srcP) {
|
|
|
|
int score = *srcP;
|
|
|
|
|
|
|
|
// Check for match
|
|
|
|
if (score == aim) {
|
|
|
|
done = true;
|
|
|
|
|
|
|
|
// Aim at non-double/triple numbers where possible
|
|
|
|
if (aim < 21) {
|
|
|
|
pt.x = xp + 5;
|
|
|
|
pt.y = yp + 5;
|
|
|
|
|
|
|
|
score = *(const byte *)board._frame.getBasePtr(xp + 10, yp + 10);
|
|
|
|
if (score != aim)
|
|
|
|
// Not aiming at non-double/triple number yet
|
|
|
|
done = false;
|
|
|
|
} else {
|
|
|
|
// Aiming at a double or triple
|
|
|
|
pt.x = xp + 3;
|
|
|
|
pt.y = yp + 3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aim == 3)
|
|
|
|
pt.x += 15;
|
|
|
|
pt.y = 132 - pt.y;
|
|
|
|
|
|
|
|
return done;
|
|
|
|
}
|
|
|
|
|
2015-03-18 23:01:47 -04:00
|
|
|
} // End of namespace Scalpel
|
|
|
|
|
2015-06-01 04:19:54 +03:00
|
|
|
} // End of namespace Sherlock
|