diff options
Diffstat (limited to 'engines/access/player.cpp')
-rw-r--r-- | engines/access/player.cpp | 872 |
1 files changed, 872 insertions, 0 deletions
diff --git a/engines/access/player.cpp b/engines/access/player.cpp new file mode 100644 index 0000000000..0162491aee --- /dev/null +++ b/engines/access/player.cpp @@ -0,0 +1,872 @@ +/* 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 "common/algorithm.h" +#include "common/textconsole.h" +#include "access/player.h" +#include "access/access.h" +#include "access/resources.h" +#include "access/amazon/amazon_player.h" +#include "access/martian/martian_player.h" + +namespace Access { + +Player *Player::init(AccessEngine *vm) { + switch (vm->getGameID()) { + case GType_Amazon: + vm->_playerDataCount = 8; + return new Amazon::AmazonPlayer(vm); + case GType_MartianMemorandum: + vm->_playerDataCount = 10; + return new Martian::MartianPlayer(vm); + default: + vm->_playerDataCount = 8; + return new Player(vm); + } +} + +Player::Player(AccessEngine *vm) : Manager(vm), ImageEntry() { + _playerSprites = nullptr; + _playerSprites1 = nullptr; + _manPal1 = nullptr; + _frameNumber = 0; + _rawTempL = 0; + _rawXTemp = 0; + _rawYTempL = 0; + _rawYTemp = 0; + _playerXLow = 0; + _playerX = 0; + _playerYLow = 0; + _playerY = 0; + _frame = 0; + _playerOff = false; + _playerMove = false; + _leftDelta = _rightDelta = 0; + _upDelta = _downDelta = 0; + _scrollConst = 0; + _scrollFlag = false; + _scrollThreshold = 0; + _scrollAmount = 0; + _scrollEnd = 0; + _roomNumber = 0; + _collideFlag = false; + _move = NONE; + _playerDirection = NONE; + _xFlag = _yFlag = 0; + _inactiveYOff = 0; + + _sideWalkMin = _sideWalkMax = 0; + _upWalkMin = _upWalkMax = 0; + _downWalkMin = _downWalkMax = 0; + _diagUpWalkMin = _diagUpWalkMax = 0; + _diagDownWalkMin = _diagDownWalkMax = 0; + _walkOffRight = _walkOffLeft = nullptr; + _walkOffUp = _walkOffDown = nullptr; + _walkOffUR = _walkOffDR = nullptr; + _walkOffUL = _walkOffDL = nullptr; +} + +Player::~Player() { + delete _playerSprites; + delete[] _manPal1; + delete[] _walkOffRight; + delete[] _walkOffLeft; + delete[] _walkOffUp; + delete[] _walkOffDown; + delete[] _walkOffUR; + delete[] _walkOffDR; + delete[] _walkOffUL; + delete[] _walkOffDL; +} + +void Player::load() { + int dataCount = _vm->_playerDataCount; + _walkOffRight = new int[dataCount]; + _walkOffLeft = new int[dataCount]; + _walkOffUp = new int[dataCount]; + _walkOffDown = new int[dataCount]; + _walkOffUR = new Common::Point[dataCount]; + _walkOffDR = new Common::Point[dataCount]; + _walkOffUL = new Common::Point[dataCount]; + _walkOffDL = new Common::Point[dataCount]; + + _playerOffset.x = _vm->_screen->_scaleTable1[25]; + _playerOffset.y = _vm->_screen->_scaleTable1[67]; + _leftDelta = -3; + _rightDelta = 33; + _upDelta = 5; + _downDelta = -10; + _scrollConst = 5; + + _sideWalkMin = 0; + _sideWalkMax = 7; + _upWalkMin = 16; + _upWalkMax = 23; + _downWalkMin = 8; + _downWalkMax = 15; + _diagUpWalkMin = 0; + _diagUpWalkMax = 7; + _diagDownWalkMin = 0; + _diagDownWalkMax = 7; + + _playerSprites = _playerSprites1; + if (_manPal1) { + // Those values are from MM as Amazon doesn't use it + Common::copy(_manPal1 + 0x2A0, _manPal1 + 0x2A0 + 0x42, _vm->_screen->_manPal); + } else { + Common::fill(_vm->_screen->_manPal, _vm->_screen->_manPal + 0x60, 0); + } +} + +void Player::loadTexPalette() { + Resource *texPal = _vm->_files->loadFile("TEXPAL.COL"); + int size = texPal->_size; + assert(size == 768); + _manPal1 = new byte[size]; + memcpy(_manPal1, texPal->data(), size); +} + +void Player::loadSprites(const Common::String &name) { + freeSprites(); + + Resource *data = _vm->_files->loadFile(name); + +#if 0 + Common::DumpFile *outFile = new Common::DumpFile(); + Common::String outName = name + ".dump"; + outFile->open(outName); + outFile->write(data->data(), data->_size); + outFile->finalize(); + outFile->close(); +#endif + + _playerSprites1 = new SpriteResource(_vm, data); + delete data; +} + +void Player::freeSprites() { + delete _playerSprites; + _playerSprites1 = nullptr; + _playerSprites = nullptr; +} + +void Player::removeSprite1() { + if (_playerSprites1) { + delete _playerSprites1; + _playerSprites1 = nullptr; + } +} + +void Player::calcManScale() { + if (!_vm->_manScaleOff) { + _vm->_scale = ((((_rawPlayer.y - _vm->_scaleMaxY + _vm->_scaleN1) * + _vm->_scaleT1 + (_vm->_scaleH2 << 8)) & 0xff00) / _vm->_scaleH1 * _vm->_scaleI) >> 8; + _vm->_screen->setScaleTable(_vm->_scale); + + _playerOffset.x = _vm->_screen->_scaleTable1[20]; + _playerOffset.y = _vm->_screen->_scaleTable1[67]; + _inactiveYOff = _playerOffset.y; + } +} + +void Player::walk() { + _collideFlag = false; + _playerDirection = NONE; + + if (_playerOff) + return; + else if (_vm->_timers[0]._flag) { + plotCom3(); + return; + } + + ++_vm->_timers[0]._flag; + switch (_move) { + case UP: + _playerMove = false; + walkUp(); + break; + case DOWN: + _playerMove = false; + walkDown(); + break; + case LEFT: + _playerMove = false; + walkLeft(); + break; + case RIGHT: + _playerMove = false; + walkRight(); + break; + case UPLEFT: + _playerMove = false; + walkUpLeft(); + break; + case DOWNLEFT: + _playerMove = false; + walkDownLeft(); + break; + case UPRIGHT: + _playerMove = false; + walkUpRight(); + break; + case DOWNRIGHT: + _playerMove = false; + walkDownRight(); + break; + default: + checkMove(); + break; + } +} + +void Player::calcPlayer() { + Screen &scr = *_vm->_screen; + scr._bufferStart.x = (_vm->_scrollCol << 4) + _vm->_scrollX; + scr._bufferStart.y = (_vm->_scrollRow << 4) + _vm->_scrollY; + _playerX = _rawPlayer.x - scr._bufferStart.x; + _playerY = _rawPlayer.y - scr._bufferStart.y; +} + +void Player::walkUp() { + if (_frame > _upWalkMax || _frame < _upWalkMin) + _frame = _upWalkMin; + + _playerDirection = UP; + int walkOff = _walkOffUp[_frame - _upWalkMin]; + int tempL = _rawPlayerLow.y - _vm->_screen->_scaleTable2[walkOff]; + _rawYTempL = (byte)tempL; + int yTemp = _rawPlayer.y - _vm->_screen->_scaleTable1[walkOff] - + (tempL < 0 ? 1 : 0); + _rawYTemp = yTemp; + _rawXTemp = _rawPlayer.x; + + if (_vm->_room->codeWalls()) { + plotCom2(); + } else { + _rawPlayer.y = _rawYTemp; + _rawPlayerLow.y = _rawYTempL; + + calcManScale(); + + // This code looks totally useless as 'si' is unconditionally set in plotCom + //if (_vm->_currentMan != 3 && (_frame == 17 || _frame == 21)) + // warning("TODO: walkUp - si = 0?"); + + if (++_frame > _upWalkMax) + _frame = _upWalkMin; + + plotCom(0); + } +} + +void Player::walkDown() { + if (_frame > _downWalkMax || _frame < _downWalkMin) + _frame = _downWalkMin; + + _playerDirection = DOWN; + int walkOff = _walkOffDown[_frame - _downWalkMin]; + int tempL = _vm->_screen->_scaleTable2[walkOff] + _rawPlayerLow.y; + _rawYTempL = (byte)tempL; + _rawYTemp = _vm->_screen->_scaleTable1[walkOff] + _rawPlayer.y + (tempL >= 0x100 ? 1 : 0); + _rawXTemp = _rawPlayer.x; + + if (_vm->_room->codeWalls()) { + plotCom2(); + } else { + _rawPlayer.y = _rawYTemp; + _rawPlayerLow.y = _rawYTempL; + + calcManScale(); + + // This code looks totally useless as 'si' is unconditionally set in plotCom + //if (_vm->_currentMan != 3 && (_frame == 10 || _frame == 14)) + // warning("TODO: walkDown - si = 0?"); + + if (++_frame > _downWalkMax) + _frame = _downWalkMin; + + plotCom(0); + } +} + +void Player::walkLeft() { + if (_frame > _sideWalkMax || _frame < _sideWalkMin) + _frame = _sideWalkMin; + + _playerDirection = LEFT; + + bool flag = _scrollEnd == 1; + if (!flag) { + calcPlayer(); + flag = (_playerX - _vm->_screen->_scaleTable1[_scrollConst] - + _vm->_player->_scrollThreshold) > 0; + } + if (flag) { + int walkOffset = _walkOffLeft[_frame - _sideWalkMin]; + int tempL = _rawPlayerLow.x - _vm->_screen->_scaleTable2[walkOffset]; + _rawTempL = (byte)tempL; + _rawXTemp = _rawPlayer.x - _vm->_screen->_scaleTable1[walkOffset] - + (tempL < 0 ? 1 : 0); + } else { + _rawXTemp = _rawPlayer.x - _vm->_screen->_scaleTable1[_scrollConst]; + } + _rawYTemp = _rawPlayer.y; + + if (_vm->_room->codeWalls()) { + plotCom2(); + } else { + _rawPlayer.x = _rawXTemp; + _rawPlayerLow.x = _rawTempL; + ++_frame; + + // This code looks totally useless as 'si' is unconditionally set in plotCom1 + //if (_vm->_currentMan != 3 && (_frame == 1 || _frame == 5)) + // warning("TODO: walkLeft - si = 0?"); + + if (_frame > _sideWalkMax) + _frame = _sideWalkMin; + + plotCom1(); + } +} + +void Player::walkRight() { + if (_frame > _sideWalkMax || _frame < _sideWalkMin) + _frame = _sideWalkMin; + + _playerDirection = RIGHT; + + bool flag = _scrollEnd == 2; + if (!flag) { + calcPlayer(); + flag = (_vm->_screen->_clipWidth - _playerX - _vm->_screen->_scaleTable1[_scrollConst] - + _vm->_player->_scrollThreshold) > 0; + } + if (flag) { + int walkOffset = _walkOffRight[_frame - _sideWalkMin]; + int tempL = _rawPlayerLow.x + _vm->_screen->_scaleTable2[walkOffset]; + _rawTempL = (byte)tempL; + _rawXTemp = _rawPlayer.x + _vm->_screen->_scaleTable1[walkOffset] + + (tempL >= 0x100 ? 1 : 0); + } else { + _rawXTemp = _rawPlayer.x + _vm->_screen->_scaleTable1[_scrollConst]; + } + _rawYTemp = _rawPlayer.y; + + if (_vm->_room->codeWalls()) { + plotCom2(); + } else { + _rawPlayer.x = _rawXTemp; + _rawPlayerLow.x = _rawTempL; + ++_frame; + + // Useless check removed + if (_frame > _sideWalkMax) + _frame = _sideWalkMin; + + plotCom0(); + } +} + +void Player::walkUpLeft() { + if (_frame > _diagUpWalkMax || _frame < _diagUpWalkMin) + _frame = _diagUpWalkMin; + + _playerDirection = UPLEFT; + + int walkOffset, tempL; + bool flag = _scrollEnd == 1; + if (!flag) { + calcPlayer(); + flag = (_playerX - _vm->_screen->_scaleTable1[_scrollConst] - + _vm->_player->_scrollThreshold) > 0; + } + if (flag) { + walkOffset = _walkOffUL[_frame - _diagUpWalkMin].x; + tempL = _rawPlayerLow.x - _vm->_screen->_scaleTable2[walkOffset]; + _rawTempL = (byte)tempL; + _rawXTemp = _rawPlayer.x - _vm->_screen->_scaleTable1[walkOffset] - + (tempL < 0 ? 1 : 0); + } else { + _rawXTemp = _rawPlayer.x - _vm->_screen->_scaleTable1[_scrollConst]; + } + + walkOffset = _walkOffUL[_frame - _diagUpWalkMin].y; + tempL = _rawPlayerLow.y - _vm->_screen->_scaleTable2[walkOffset]; + _rawYTempL = (byte)tempL; + _rawYTemp = _rawPlayer.y - _vm->_screen->_scaleTable1[walkOffset] - + (tempL < 0 ? 1 : 0); + + if (_vm->_room->codeWalls()) { + plotCom2(); + } else { + _rawPlayer.x = _rawXTemp; + _rawPlayer.y = _rawYTemp; + _rawPlayerLow.x = _rawTempL; + _rawPlayerLow.y = _rawYTempL; + + ++_frame; + calcManScale(); + + // This code looks totally useless as 'si' is unconditionally set in plotCom1 + //if (_vm->_currentMan != 3 && (_frame == 1 || _frame == 5)) + // warning("TODO: walkUpLeft - si = 0?"); + + if (_frame > _diagUpWalkMax) + _frame = _diagUpWalkMin; + + plotCom1(); + } +} + +void Player::walkDownLeft() { + if (_frame > _diagDownWalkMax || _frame < _diagDownWalkMin) + _frame = _diagDownWalkMin; + + _playerDirection = DOWNLEFT; + + int walkOffset, tempL; + bool flag = _scrollEnd == 1; + if (!flag) { + calcPlayer(); + flag = (_playerX - _vm->_screen->_scaleTable1[_scrollConst] - + _vm->_player->_scrollThreshold) > 0; + } + if (flag) { + walkOffset = _walkOffDL[_frame - _sideWalkMin].x; + tempL = _rawPlayerLow.x - _vm->_screen->_scaleTable2[walkOffset]; + _rawTempL = (byte)tempL; + _rawXTemp = _rawPlayer.x - _vm->_screen->_scaleTable1[walkOffset] - + (tempL < 0 ? 1 : 0); + } else { + _rawXTemp = _rawPlayer.x - _vm->_screen->_scaleTable1[_scrollConst]; + } + + walkOffset = _walkOffDL[_frame - _diagDownWalkMin].y; + tempL = _rawPlayerLow.y + _vm->_screen->_scaleTable2[walkOffset]; + _rawYTempL = (byte)tempL; + _rawYTemp = _rawPlayer.y + _vm->_screen->_scaleTable1[walkOffset] + + (tempL >= 0x100 ? 1 : 0); + + if (_vm->_room->codeWalls()) { + plotCom2(); + } else { + _rawPlayer.x = _rawXTemp; + _rawPlayer.y = _rawYTemp; + _rawPlayerLow.x = _rawTempL; + _rawPlayerLow.y = _rawYTempL; + + ++_frame; + calcManScale(); + + // This code looks totally useless as 'si' is unconditionally set in plotCom1 + //if (_vm->_currentMan != 3 && (_frame == 1 || _frame == 5)) + // warning("TODO: walkDownLeft - si = 0?"); + + if (_frame > _diagDownWalkMax) + _frame = _diagDownWalkMin; + + plotCom1(); + } +} + +void Player::walkUpRight() { + if (_frame > _diagUpWalkMax || _frame < _diagUpWalkMin) + _frame = _diagUpWalkMin; + + _playerDirection = UPRIGHT; + + int walkOffset, tempL; + bool flag = _scrollEnd == 1; + if (!flag) { + calcPlayer(); + flag = (_vm->_screen->_clipWidth - _playerX - _vm->_screen->_scaleTable1[_scrollConst] - + _vm->_player->_scrollThreshold) > 0; + } + if (flag) { + walkOffset = _walkOffUR[_frame - _diagUpWalkMin].x; + tempL = _rawPlayerLow.x + _vm->_screen->_scaleTable2[walkOffset]; + _rawTempL = (byte)tempL; + _rawXTemp = _rawPlayer.x + _vm->_screen->_scaleTable1[walkOffset] + + (tempL >= 0x100 ? 1 : 0); + } else { + _rawXTemp = _rawPlayer.x + _vm->_screen->_scaleTable1[_scrollConst]; + } + + walkOffset = _walkOffUL[_frame - _diagUpWalkMin].y; + tempL = _rawPlayerLow.y - _vm->_screen->_scaleTable2[walkOffset]; + _rawYTempL = (byte)tempL; + _rawYTemp = _rawPlayer.y - _vm->_screen->_scaleTable1[walkOffset] - + (tempL < 0 ? 1 : 0); + + if (_vm->_room->codeWalls()) { + plotCom2(); + } else { + _rawPlayer.x = _rawXTemp; + _rawPlayer.y = _rawYTemp; + _rawPlayerLow.x = _rawTempL; + _rawPlayerLow.y = _rawYTempL; + + ++_frame; + calcManScale(); + + // This code looks totally useless as 'si' is unconditionally set in plotCom + //if (_vm->_currentMan != 3 && (_frame == 1 || _frame == 5)) + // warning("TODO: walkUpRight - si = 0?"); + + if (_frame > _diagUpWalkMax) + _frame = _diagUpWalkMin; + + plotCom(0); + } +} + +void Player::walkDownRight() { + if (_frame > _diagDownWalkMax || _frame < _diagDownWalkMin) + _frame = _diagDownWalkMin; + + _playerDirection = DOWNRIGHT; + + int walkOffset, tempL; + bool flag = _scrollEnd == 2; + if (!flag) { + calcPlayer(); + flag = (_vm->_screen->_clipWidth - _playerX - _vm->_screen->_scaleTable1[_scrollConst] - + _vm->_player->_scrollThreshold) > 0; + } + if (flag) { + walkOffset = _walkOffUR[_frame - _diagDownWalkMin].x; + tempL = _rawPlayerLow.x + _vm->_screen->_scaleTable2[walkOffset]; + _rawTempL = (byte)tempL; + _rawXTemp = _rawPlayer.x + _vm->_screen->_scaleTable1[walkOffset] + + (tempL >= 0x100 ? 1 : 0); + } else { + _rawXTemp = _rawPlayer.x + _vm->_screen->_scaleTable1[_scrollConst]; + } + + walkOffset = _walkOffDR[_frame - _diagDownWalkMin].y; + tempL = _rawPlayerLow.y + _vm->_screen->_scaleTable2[walkOffset]; + _rawYTempL = (byte)tempL; + _rawYTemp = _rawPlayer.y + _vm->_screen->_scaleTable1[walkOffset] + + (tempL >= 0x100 ? 1 : 0); + + if (_vm->_room->codeWalls()) { + plotCom2(); + } else { + _rawPlayer.x = _rawXTemp; + _rawPlayer.y = _rawYTemp; + _rawPlayerLow.x = _rawTempL; + _rawPlayerLow.y = _rawYTempL; + + calcManScale(); + + // This code looks totally useless as 'si' is unconditionally set in plotCom1 + //if (_vm->_currentMan != 3 && (_frame == 1 || _frame == 5)) + // warning("TODO: walkDownRight - si = 0?"); + + ++_frame; + if (_frame > _diagDownWalkMax) + _frame = _diagDownWalkMin; + + plotCom(0); + } +} + +void Player::checkMove() { + if (_playerMove) { + if (_xFlag == 0 && _yFlag == 0) { + int xp = (_playerOffset.x / 2) + _rawPlayer.x - _moveTo.x; + if (xp < 0) + xp = -xp; + int yp = _rawPlayer.y - _moveTo.y; + if (yp < 0) + yp = -yp; + + if (xp >= yp) + _xFlag = 1; + else + _yFlag = 1; + } + + if (_yFlag == 1) { + int yd = _rawPlayer.y - _moveTo.y; + if ((yd >= 0 && yd <= _upDelta) || (yd < 0 && -yd <= _upDelta)) { + ++_yFlag; + if (_xFlag) { + _playerMove = false; + _xFlag = _yFlag = 0; + } else { + ++_xFlag; + } + } else { + if (yd >= 0) + walkUp(); + else + walkDown(); + + if (_collideFlag) { + _playerMove = false; + _xFlag = _yFlag = 0; + } + } + } else if (_xFlag == 1) { + int xd = (_playerOffset.x / 2) + _rawPlayer.x - _moveTo.x; + if ((xd >= 0 && xd <= -_leftDelta) || (xd < 0 && -xd <= -_leftDelta)) { + ++_xFlag; + + if (_yFlag) { + _playerMove = false; + _xFlag = _yFlag = 0; + } + } else { + if (xd >= 0) + walkLeft(); + else + walkRight(); + + if (_collideFlag) { + _playerMove = false; + _xFlag = _yFlag = 0; + } + } + } else if (!_yFlag) { + ++_yFlag; + } else { + _playerMove = false; + _xFlag = _yFlag = 0; + } + } + + plotCom3(); +} + +void Player::plotCom(int flags) { + _flags &= ~IMGFLAG_BACKWARDS; + _flags &= ~IMGFLAG_UNSCALED; + _flags |= flags; + + plotCom3(); +} + +void Player::plotCom0() { + plotCom(_vm->getGameID() == GType_Amazon ? 0 : IMGFLAG_BACKWARDS); +} + +void Player::plotCom1() { + plotCom(_vm->getGameID() == GType_Amazon ? IMGFLAG_BACKWARDS : 0); +} + +void Player::plotCom2() { + // WORKAROUND: Amazon has at least one cutscene with the player not properly turned off + if (!_playerOff && _spritesPtr != nullptr) + _vm->_images.addToList(*this); +} + +void Player::plotCom3() { + // Update the base ImageEntry fields for the player + _position.x = _rawPlayer.x; + _position.y = _rawPlayer.y - _playerOffset.y; + _offsetY = _playerOffset.y; + _spritesPtr = _playerSprites; + _frameNumber = _frame; + + plotCom2(); +} + +void Player::checkScrollUp() { + if ((_playerDirection == DOWNRIGHT || _playerDirection == DOWNLEFT || + _playerDirection == DOWN) && (_vm->_screen->_clipHeight - + _playerY - _scrollThreshold) <= 0) { + // Scroll up + if (scrollUp()) { + _scrollEnd = 4; + _vm->_scrollY &= TILE_HEIGHT; + _scrollFlag = true; + } + } +} + +void Player::checkScroll() { + _scrollFlag = false; + if (_playerDirection == NONE) + return; + + if ((_playerDirection == UPLEFT || _playerDirection == DOWNLEFT || + _playerDirection == LEFT) && _playerX <= _scrollThreshold) { + // Scroll right + if (!scrollRight()) { + if (_playerDirection == DOWNLEFT) + checkScrollUp(); + + return; + } + } else if ((_playerDirection == UPRIGHT || _playerDirection == DOWNRIGHT || + _playerDirection == RIGHT) && (_vm->_screen->_clipWidth - + _playerX - _scrollThreshold) <= 0) { + // Scroll left + if (!scrollLeft()) { + if (_playerDirection == DOWNRIGHT) + checkScrollUp(); + + return; + } + } + + if ((_playerDirection == UPRIGHT || _playerDirection == UPLEFT || + _playerDirection == UP) && _playerY <= _scrollThreshold) { + scrollDown(); + } else { + checkScrollUp(); + } +} + +bool Player::scrollUp(int forcedAmount) { + if (forcedAmount == -1) + _scrollAmount = -(_vm->_screen->_clipHeight - _playerY - _scrollThreshold); + else + _scrollAmount = forcedAmount; + + if ((_vm->_scrollRow + _vm->_screen->_vWindowHeight) >= + _vm->_room->_playFieldHeight) + return true; + + _scrollFlag = true; + _vm->_scrollY = _vm->_scrollY + _scrollAmount; + + while (_vm->_scrollY >= TILE_HEIGHT && !_vm->shouldQuit()) { + _vm->_scrollY -= TILE_HEIGHT; + ++_vm->_scrollRow; + _vm->_buffer1.moveBufferUp(); + + _vm->_room->buildRow(_vm->_scrollRow + _vm->_screen->_vWindowHeight, + _vm->_screen->_vWindowLinesTall); + + if ((_vm->_scrollRow + _vm->_screen->_vWindowHeight) >= + _vm->_room->_playFieldHeight) + return true; + + if (_vm->_scrollY <= TILE_HEIGHT) + return false; + } + + return false; +} + +bool Player::scrollDown(int forcedAmount) { + if (forcedAmount == -1) + _scrollAmount = -(_playerY - _scrollThreshold); + else + _scrollAmount = forcedAmount; + + _scrollFlag = true; + _vm->_scrollY -= _scrollAmount; + if (_vm->_scrollY >= 0) + return true; + + do { + _vm->_scrollY += TILE_HEIGHT; + if (--_vm->_scrollRow < 0) + break; + + _vm->_buffer1.moveBufferDown(); + _vm->_room->buildRow(_vm->_scrollRow, 0); + + if (_vm->_scrollY >= 0) + return false; + } while (!_vm->shouldQuit()); + + _scrollEnd = 3; + _vm->_scrollY = 0; + _vm->_scrollRow = 0; + return true; +} + +bool Player::scrollLeft(int forcedAmount) { + Screen &screen = *_vm->_screen; + if (forcedAmount == -1) + _scrollAmount = -(_vm->_screen->_clipWidth - _playerX - _scrollThreshold); + else + _scrollAmount = forcedAmount; + + if ((_vm->_scrollCol + screen._vWindowWidth) == _vm->_room->_playFieldWidth) { + _scrollEnd = 2; + _vm->_scrollX = 0; + _scrollFlag = true; + return true; + } else { + _scrollFlag = true; + _vm->_scrollX = _vm->_scrollX + _scrollAmount; + + do { + if (_vm->_scrollX < TILE_WIDTH) + return true; + + _vm->_scrollX -= TILE_WIDTH; + ++_vm->_scrollCol; + _vm->_buffer1.moveBufferLeft(); + _vm->_room->buildColumn(_vm->_scrollCol + screen._vWindowWidth, + screen._vWindowBytesWide); + } while (!_vm->shouldQuit() && (_vm->_scrollX >= TILE_WIDTH)); + + return (_playerDirection == UPRIGHT); + } +} + +bool Player::scrollRight(int forcedAmount) { + if (forcedAmount == -1) + _scrollAmount = -(_playerX - _scrollThreshold); + else + _scrollAmount = forcedAmount; + + _scrollFlag = true; + _vm->_scrollX -= _scrollAmount; + + if (_vm->_scrollX < 0) { + do { + _vm->_scrollX += TILE_WIDTH; + if (--_vm->_scrollCol < 0) { + _scrollEnd = true; + _vm->_scrollX = 0; + _vm->_scrollCol = 0; + return true; + } + + _vm->_buffer1.moveBufferRight(); + _vm->_room->buildColumn(_vm->_scrollCol, 0); + } while (!_vm->shouldQuit() && (_vm->_scrollX < 0)); + + return false; + } + + return true; +} + +void Player::synchronize(Common::Serializer &s) { + s.syncAsUint16LE(_roomNumber); + s.syncAsSint16LE(_rawPlayerLow.x); + s.syncAsSint16LE(_rawPlayer.x); + s.syncAsSint16LE(_rawPlayerLow.y); + s.syncAsSint16LE(_rawPlayer.y); +} + +} // End of namespace Access |