Move WalkingMap into new module.
Also, fix a bug when loading the default walking map (wasn't implemented) and setting font size. The reason I move this code into a new module is because I will augment it with other walking-related algorithms soon. svn-id: r45510
This commit is contained in:
parent
1526fda715
commit
a20e42efb9
7 changed files with 254 additions and 192 deletions
|
@ -1044,9 +1044,7 @@ void Game::loadRoom(int roomNum) {
|
||||||
// Music will be played by the GPL2 command startMusic when needed.
|
// Music will be played by the GPL2 command startMusic when needed.
|
||||||
setMusicTrack(roomReader.readByte());
|
setMusicTrack(roomReader.readByte());
|
||||||
|
|
||||||
int mapID = roomReader.readByte() - 1;
|
_currentRoom._mapID = roomReader.readByte() - 1;
|
||||||
loadWalkingMap(mapID);
|
|
||||||
|
|
||||||
_currentRoom._palette = roomReader.readByte() - 1;
|
_currentRoom._palette = roomReader.readByte() - 1;
|
||||||
_currentRoom._numOverlays = roomReader.readSint16LE();
|
_currentRoom._numOverlays = roomReader.readSint16LE();
|
||||||
_currentRoom._init = roomReader.readSint16LE();
|
_currentRoom._init = roomReader.readSint16LE();
|
||||||
|
@ -1078,7 +1076,7 @@ void Game::loadRoom(int roomNum) {
|
||||||
_currentRoom._numGates = roomReader.readByte();
|
_currentRoom._numGates = roomReader.readByte();
|
||||||
|
|
||||||
debugC(4, kDraciLogicDebugLevel, "Music: %d", getMusicTrack());
|
debugC(4, kDraciLogicDebugLevel, "Music: %d", getMusicTrack());
|
||||||
debugC(4, kDraciLogicDebugLevel, "Map: %d", mapID);
|
debugC(4, kDraciLogicDebugLevel, "Map: %d", _currentRoom._mapID);
|
||||||
debugC(4, kDraciLogicDebugLevel, "Palette: %d", _currentRoom._palette);
|
debugC(4, kDraciLogicDebugLevel, "Palette: %d", _currentRoom._palette);
|
||||||
debugC(4, kDraciLogicDebugLevel, "Overlays: %d", _currentRoom._numOverlays);
|
debugC(4, kDraciLogicDebugLevel, "Overlays: %d", _currentRoom._numOverlays);
|
||||||
debugC(4, kDraciLogicDebugLevel, "Init: %d", _currentRoom._init);
|
debugC(4, kDraciLogicDebugLevel, "Init: %d", _currentRoom._init);
|
||||||
|
@ -1096,13 +1094,14 @@ void Game::loadRoom(int roomNum) {
|
||||||
debugC(4, kDraciLogicDebugLevel, "Gates: %d", _currentRoom._numGates);
|
debugC(4, kDraciLogicDebugLevel, "Gates: %d", _currentRoom._numGates);
|
||||||
|
|
||||||
// Read in the gates' numbers
|
// Read in the gates' numbers
|
||||||
|
|
||||||
_currentRoom._gates.clear();
|
_currentRoom._gates.clear();
|
||||||
|
|
||||||
for (uint i = 0; i < _currentRoom._numGates; ++i) {
|
for (uint i = 0; i < _currentRoom._numGates; ++i) {
|
||||||
_currentRoom._gates.push_back(roomReader.readSint16LE());
|
_currentRoom._gates.push_back(roomReader.readSint16LE());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load the walking map
|
||||||
|
loadWalkingMap(_currentRoom._mapID);
|
||||||
|
|
||||||
// Load the room's objects
|
// Load the room's objects
|
||||||
for (uint i = 0; i < _info._numObjects; ++i) {
|
for (uint i = 0; i < _info._numObjects; ++i) {
|
||||||
debugC(7, kDraciLogicDebugLevel,
|
debugC(7, kDraciLogicDebugLevel,
|
||||||
|
@ -1258,6 +1257,9 @@ void Game::loadObject(uint objNum) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::loadWalkingMap(int mapID) {
|
void Game::loadWalkingMap(int mapID) {
|
||||||
|
if (mapID < 0) {
|
||||||
|
mapID = _currentRoom._mapID;
|
||||||
|
}
|
||||||
const BAFile *f;
|
const BAFile *f;
|
||||||
f = _vm->_walkingMapsArchive->getFile(mapID);
|
f = _vm->_walkingMapsArchive->getFile(mapID);
|
||||||
_currentRoom._walkingMap.load(f->_data, f->_length);
|
_currentRoom._walkingMap.load(f->_data, f->_length);
|
||||||
|
@ -1665,124 +1667,6 @@ void Game::DoSync(Common::Serializer &s) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WalkingMap::isWalkable(int x, int y) const {
|
|
||||||
// Convert to map pixels
|
|
||||||
x = x / _deltaX;
|
|
||||||
y = y / _deltaY;
|
|
||||||
|
|
||||||
int pixelIndex = _mapWidth * y + x;
|
|
||||||
int byteIndex = pixelIndex / 8;
|
|
||||||
int mapByte = _data[byteIndex];
|
|
||||||
|
|
||||||
return mapByte & (1 << pixelIndex % 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief For a given point, find a nearest walkable point on the walking map
|
|
||||||
*
|
|
||||||
* @param startX x coordinate of the point
|
|
||||||
* @param startY y coordinate of the point
|
|
||||||
*
|
|
||||||
* @return A Common::Point representing the nearest walkable point
|
|
||||||
*
|
|
||||||
* The algorithm was copied from the original engine for exactness.
|
|
||||||
* TODO: Study this algorithm in more detail so it can be documented properly and
|
|
||||||
* possibly improved / simplified.
|
|
||||||
*/
|
|
||||||
Common::Point WalkingMap::findNearestWalkable(int startX, int startY, Common::Rect searchRect) const {
|
|
||||||
// If the starting point is walkable, just return that
|
|
||||||
if (searchRect.contains(startX, startY) && isWalkable(startX, startY)) {
|
|
||||||
return Common::Point(startX, startY);
|
|
||||||
}
|
|
||||||
|
|
||||||
int signs[] = { 1, -1 };
|
|
||||||
const uint kSignsNum = 2;
|
|
||||||
|
|
||||||
int radius = 0;
|
|
||||||
int x, y;
|
|
||||||
int dx, dy;
|
|
||||||
int prediction;
|
|
||||||
|
|
||||||
// The place where, eventually, the result coordinates will be stored
|
|
||||||
int finalX, finalY;
|
|
||||||
|
|
||||||
// The algorithm appears to start off with an ellipse with the minor radius equal to
|
|
||||||
// zero and the major radius equal to the walking map delta (the number of pixels
|
|
||||||
// one map pixel represents). It then uses a heuristic to gradually reshape it into
|
|
||||||
// a circle (by shortening the major radius and lengthening the minor one). At each
|
|
||||||
// such resizing step, it checks some select points on the ellipse for walkability.
|
|
||||||
// It also does the same check for the ellipse perpendicular to it (rotated by 90 degrees).
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
// The default major radius
|
|
||||||
radius += _deltaX;
|
|
||||||
|
|
||||||
// The ellipse radii (minor, major) that get resized
|
|
||||||
x = 0;
|
|
||||||
y = radius;
|
|
||||||
|
|
||||||
// Heuristic variables
|
|
||||||
prediction = 1 - radius;
|
|
||||||
dx = 3;
|
|
||||||
dy = 2 * radius - 2;
|
|
||||||
|
|
||||||
do {
|
|
||||||
// The following two loops serve the purpose of checking the points on the two
|
|
||||||
// ellipses for walkability. The signs[] array is there to obliterate the need
|
|
||||||
// of writing out all combinations manually.
|
|
||||||
|
|
||||||
for (uint i = 0; i < kSignsNum; ++i) {
|
|
||||||
finalY = startY + y * signs[i];
|
|
||||||
|
|
||||||
for (uint j = 0; j < kSignsNum; ++j) {
|
|
||||||
finalX = startX + x * signs[j];
|
|
||||||
|
|
||||||
// If the current point is walkable, return it
|
|
||||||
if (searchRect.contains(finalX, finalY) && isWalkable(finalX, finalY)) {
|
|
||||||
return Common::Point(finalX, finalY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (x == y) {
|
|
||||||
// If the starting point is walkable, just return that
|
|
||||||
if (searchRect.contains(finalX, finalY) && isWalkable(finalX, finalY)) {
|
|
||||||
return Common::Point(finalX, finalY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint i = 0; i < kSignsNum; ++i) {
|
|
||||||
finalY = startY + x * signs[i];
|
|
||||||
|
|
||||||
for (uint j = 0; j < kSignsNum; ++j) {
|
|
||||||
finalX = startX + y * signs[j];
|
|
||||||
|
|
||||||
// If the current point is walkable, return it
|
|
||||||
if (searchRect.contains(finalX, finalY) && isWalkable(finalX, finalY)) {
|
|
||||||
return Common::Point(finalX, finalY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If prediction is non-negative, we need to decrease the major radius of the
|
|
||||||
// ellipse
|
|
||||||
if (prediction >= 0) {
|
|
||||||
prediction -= dy;
|
|
||||||
dy -= 2 * _deltaX;
|
|
||||||
y -= _deltaX;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Increase the minor radius of the ellipse and update heuristic variables
|
|
||||||
prediction += dx;
|
|
||||||
dx += 2 * _deltaX;
|
|
||||||
x += _deltaX;
|
|
||||||
|
|
||||||
// If the current ellipse has been reshaped into a circle,
|
|
||||||
// end this loop and enlarge the radius
|
|
||||||
} while (x <= y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static double real_to_double(byte real[6]) {
|
static double real_to_double(byte real[6]) {
|
||||||
// Extract sign bit
|
// Extract sign bit
|
||||||
int sign = real[0] & (1 << 7);
|
int sign = real[0] & (1 << 7);
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include "draci/script.h"
|
#include "draci/script.h"
|
||||||
#include "draci/animation.h"
|
#include "draci/animation.h"
|
||||||
#include "draci/sprite.h"
|
#include "draci/sprite.h"
|
||||||
|
#include "draci/walking.h"
|
||||||
|
|
||||||
namespace Draci {
|
namespace Draci {
|
||||||
|
|
||||||
|
@ -64,12 +65,6 @@ enum {
|
||||||
kNoItem = -1
|
kNoItem = -1
|
||||||
};
|
};
|
||||||
|
|
||||||
// Used as a default parameter in Game::loadWalkingMap() to specify that the default
|
|
||||||
// walking map to the room is to be loaded.
|
|
||||||
enum {
|
|
||||||
kDefaultRoomMap = -1
|
|
||||||
};
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
kNoDialogue = -1,
|
kNoDialogue = -1,
|
||||||
kDialogueLines = 4
|
kDialogueLines = 4
|
||||||
|
@ -104,51 +99,6 @@ enum InventoryConstants {
|
||||||
kInventorySlots = kInventoryLines * kInventoryColumns
|
kInventorySlots = kInventoryLines * kInventoryColumns
|
||||||
};
|
};
|
||||||
|
|
||||||
class WalkingMap {
|
|
||||||
public:
|
|
||||||
WalkingMap() {
|
|
||||||
_realWidth = 0;
|
|
||||||
_realHeight = 0;
|
|
||||||
_mapWidth = 0;
|
|
||||||
_mapHeight = 0;
|
|
||||||
_byteWidth = 0;
|
|
||||||
_data = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void load(const byte *data, uint length) {
|
|
||||||
Common::MemoryReadStream mapReader(data, length);
|
|
||||||
|
|
||||||
_realWidth = mapReader.readUint16LE();
|
|
||||||
_realHeight = mapReader.readUint16LE();
|
|
||||||
_deltaX = mapReader.readUint16LE();
|
|
||||||
_deltaY = mapReader.readUint16LE();
|
|
||||||
_mapWidth = mapReader.readUint16LE();
|
|
||||||
_mapHeight = mapReader.readUint16LE();
|
|
||||||
_byteWidth = mapReader.readUint16LE();
|
|
||||||
|
|
||||||
// Set the data pointer to raw map data
|
|
||||||
_data = data + mapReader.pos();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isWalkable(int x, int y) const;
|
|
||||||
Common::Point findNearestWalkable(int x, int y, Common::Rect searchRect) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
int _realWidth, _realHeight;
|
|
||||||
int _deltaX, _deltaY;
|
|
||||||
int _mapWidth, _mapHeight;
|
|
||||||
int _byteWidth;
|
|
||||||
const byte *_data;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Enumerates the directions the dragon can look into when arrived.
|
|
||||||
*/
|
|
||||||
enum SightDirection {
|
|
||||||
kDirectionLast, kDirectionMouse, kDirectionUnknown,
|
|
||||||
kDirectionRight, kDirectionLeft, kDirectionIntelligent
|
|
||||||
};
|
|
||||||
|
|
||||||
struct GameObject {
|
struct GameObject {
|
||||||
uint _init, _look, _use, _canUse;
|
uint _init, _look, _use, _canUse;
|
||||||
bool _imInit, _imLook, _imUse;
|
bool _imInit, _imLook, _imUse;
|
||||||
|
@ -201,6 +151,7 @@ struct Room {
|
||||||
int _roomNum;
|
int _roomNum;
|
||||||
byte _music;
|
byte _music;
|
||||||
WalkingMap _walkingMap;
|
WalkingMap _walkingMap;
|
||||||
|
int _mapID;
|
||||||
int _palette;
|
int _palette;
|
||||||
int _numOverlays;
|
int _numOverlays;
|
||||||
int _init, _look, _use, _canUse;
|
int _init, _look, _use, _canUse;
|
||||||
|
@ -227,18 +178,6 @@ enum LoopSubstatus {
|
||||||
kSubstatusStrange
|
kSubstatusStrange
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Enumerates the animations for the dragon's movement.
|
|
||||||
*/
|
|
||||||
enum Movement {
|
|
||||||
kMoveUndefined = -1,
|
|
||||||
kMoveDown, kMoveUp, kMoveRight, kMoveLeft,
|
|
||||||
kMoveRightDown, kMoveRightUp, kMoveLeftDown, kMoveLeftUp,
|
|
||||||
kMoveDownRight, kMoveUpRight, kMoveDownLeft, kMoveUpLeft,
|
|
||||||
kMoveLeftRight, kMoveRightLeft, kMoveUpStopLeft, kMoveUpStopRight,
|
|
||||||
kSpeakRight, kSpeakLeft, kStopRight, kStopLeft
|
|
||||||
};
|
|
||||||
|
|
||||||
class Game {
|
class Game {
|
||||||
public:
|
public:
|
||||||
Game(DraciEngine *vm);
|
Game(DraciEngine *vm);
|
||||||
|
@ -281,7 +220,7 @@ public:
|
||||||
int loadAnimation(uint animNum, uint z);
|
int loadAnimation(uint animNum, uint z);
|
||||||
void loadOverlays();
|
void loadOverlays();
|
||||||
void loadObject(uint numObj);
|
void loadObject(uint numObj);
|
||||||
void loadWalkingMap(int mapID = kDefaultRoomMap);
|
void loadWalkingMap(int mapID);
|
||||||
void loadItem(int itemID);
|
void loadItem(int itemID);
|
||||||
|
|
||||||
uint getNumObjects() const;
|
uint getNumObjects() const;
|
||||||
|
|
|
@ -14,7 +14,8 @@ MODULE_OBJS := \
|
||||||
surface.o \
|
surface.o \
|
||||||
mouse.o \
|
mouse.o \
|
||||||
game.o \
|
game.o \
|
||||||
animation.o
|
animation.o \
|
||||||
|
walking.o
|
||||||
|
|
||||||
MODULE_DIRS += \
|
MODULE_DIRS += \
|
||||||
engines/draci
|
engines/draci
|
||||||
|
|
|
@ -728,10 +728,9 @@ void Script::talk(Common::Queue<int> ¶ms) {
|
||||||
|
|
||||||
// HACK: Some strings in the English data files are too long to fit the screen
|
// HACK: Some strings in the English data files are too long to fit the screen
|
||||||
// This is a temporary resolution.
|
// This is a temporary resolution.
|
||||||
|
speechFrame->setFont(_vm->_bigFont);
|
||||||
if (speechFrame->getWidth() >= kScreenWidth) {
|
if (speechFrame->getWidth() >= kScreenWidth) {
|
||||||
speechFrame->setFont(_vm->_smallFont);
|
speechFrame->setFont(_vm->_smallFont);
|
||||||
} else {
|
|
||||||
speechFrame->setFont(_vm->_bigFont);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the loop substatus to an appropriate value
|
// Set the loop substatus to an appropriate value
|
||||||
|
@ -838,7 +837,7 @@ void Script::exitDialogue(Common::Queue<int> ¶ms) {
|
||||||
|
|
||||||
void Script::roomMap(Common::Queue<int> ¶ms) {
|
void Script::roomMap(Common::Queue<int> ¶ms) {
|
||||||
// Load the default walking map for the room
|
// Load the default walking map for the room
|
||||||
_vm->_game->loadWalkingMap();
|
_vm->_game->loadWalkingMap(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Script::disableQuickHero(Common::Queue<int> ¶ms) {
|
void Script::disableQuickHero(Common::Queue<int> ¶ms) {
|
||||||
|
|
|
@ -341,6 +341,9 @@ Common::Rect Text::getRect(const Displacement &displacement) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Text::setFont(const Font *font) {
|
void Text::setFont(const Font *font) {
|
||||||
|
if (font == _font) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
_font = font;
|
_font = font;
|
||||||
|
|
||||||
_width = _font->getStringWidth(_text, _spacing);
|
_width = _font->getStringWidth(_text, _spacing);
|
||||||
|
|
165
engines/draci/walking.cpp
Normal file
165
engines/draci/walking.cpp
Normal file
|
@ -0,0 +1,165 @@
|
||||||
|
/* 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.
|
||||||
|
*
|
||||||
|
* $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/engines/draci/game.cpp $
|
||||||
|
* $Id: game.cpp 45505 2009-10-29 18:15:12Z eriktorbjorn $
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "common/stream.h"
|
||||||
|
|
||||||
|
#include "draci/walking.h"
|
||||||
|
|
||||||
|
namespace Draci {
|
||||||
|
|
||||||
|
void WalkingMap::load(const byte *data, uint length) {
|
||||||
|
Common::MemoryReadStream mapReader(data, length);
|
||||||
|
|
||||||
|
_realWidth = mapReader.readUint16LE();
|
||||||
|
_realHeight = mapReader.readUint16LE();
|
||||||
|
_deltaX = mapReader.readUint16LE();
|
||||||
|
_deltaY = mapReader.readUint16LE();
|
||||||
|
_mapWidth = mapReader.readUint16LE();
|
||||||
|
_mapHeight = mapReader.readUint16LE();
|
||||||
|
_byteWidth = mapReader.readUint16LE();
|
||||||
|
|
||||||
|
// Set the data pointer to raw map data
|
||||||
|
_data = data + mapReader.pos();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WalkingMap::isWalkable(int x, int y) const {
|
||||||
|
// Convert to map pixels
|
||||||
|
x = x / _deltaX;
|
||||||
|
y = y / _deltaY;
|
||||||
|
|
||||||
|
int pixelIndex = _mapWidth * y + x;
|
||||||
|
int byteIndex = pixelIndex / 8;
|
||||||
|
int mapByte = _data[byteIndex];
|
||||||
|
|
||||||
|
return mapByte & (1 << pixelIndex % 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief For a given point, find a nearest walkable point on the walking map
|
||||||
|
*
|
||||||
|
* @param startX x coordinate of the point
|
||||||
|
* @param startY y coordinate of the point
|
||||||
|
*
|
||||||
|
* @return A Common::Point representing the nearest walkable point
|
||||||
|
*
|
||||||
|
* The algorithm was copied from the original engine for exactness.
|
||||||
|
* TODO: Study this algorithm in more detail so it can be documented properly and
|
||||||
|
* possibly improved / simplified.
|
||||||
|
*/
|
||||||
|
Common::Point WalkingMap::findNearestWalkable(int startX, int startY, Common::Rect searchRect) const {
|
||||||
|
// If the starting point is walkable, just return that
|
||||||
|
if (searchRect.contains(startX, startY) && isWalkable(startX, startY)) {
|
||||||
|
return Common::Point(startX, startY);
|
||||||
|
}
|
||||||
|
|
||||||
|
int signs[] = { 1, -1 };
|
||||||
|
const uint kSignsNum = 2;
|
||||||
|
|
||||||
|
int radius = 0;
|
||||||
|
int x, y;
|
||||||
|
int dx, dy;
|
||||||
|
int prediction;
|
||||||
|
|
||||||
|
// The place where, eventually, the result coordinates will be stored
|
||||||
|
int finalX, finalY;
|
||||||
|
|
||||||
|
// The algorithm appears to start off with an ellipse with the minor radius equal to
|
||||||
|
// zero and the major radius equal to the walking map delta (the number of pixels
|
||||||
|
// one map pixel represents). It then uses a heuristic to gradually reshape it into
|
||||||
|
// a circle (by shortening the major radius and lengthening the minor one). At each
|
||||||
|
// such resizing step, it checks some select points on the ellipse for walkability.
|
||||||
|
// It also does the same check for the ellipse perpendicular to it (rotated by 90 degrees).
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
// The default major radius
|
||||||
|
radius += _deltaX;
|
||||||
|
|
||||||
|
// The ellipse radii (minor, major) that get resized
|
||||||
|
x = 0;
|
||||||
|
y = radius;
|
||||||
|
|
||||||
|
// Heuristic variables
|
||||||
|
prediction = 1 - radius;
|
||||||
|
dx = 3;
|
||||||
|
dy = 2 * radius - 2;
|
||||||
|
|
||||||
|
do {
|
||||||
|
// The following two loops serve the purpose of checking the points on the two
|
||||||
|
// ellipses for walkability. The signs[] array is there to obliterate the need
|
||||||
|
// of writing out all combinations manually.
|
||||||
|
|
||||||
|
for (uint i = 0; i < kSignsNum; ++i) {
|
||||||
|
finalY = startY + y * signs[i];
|
||||||
|
|
||||||
|
for (uint j = 0; j < kSignsNum; ++j) {
|
||||||
|
finalX = startX + x * signs[j];
|
||||||
|
|
||||||
|
// If the current point is walkable, return it
|
||||||
|
if (searchRect.contains(finalX, finalY) && isWalkable(finalX, finalY)) {
|
||||||
|
return Common::Point(finalX, finalY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x == y) {
|
||||||
|
// If the starting point is walkable, just return that
|
||||||
|
if (searchRect.contains(finalX, finalY) && isWalkable(finalX, finalY)) {
|
||||||
|
return Common::Point(finalX, finalY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint i = 0; i < kSignsNum; ++i) {
|
||||||
|
finalY = startY + x * signs[i];
|
||||||
|
|
||||||
|
for (uint j = 0; j < kSignsNum; ++j) {
|
||||||
|
finalX = startX + y * signs[j];
|
||||||
|
|
||||||
|
// If the current point is walkable, return it
|
||||||
|
if (searchRect.contains(finalX, finalY) && isWalkable(finalX, finalY)) {
|
||||||
|
return Common::Point(finalX, finalY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If prediction is non-negative, we need to decrease the major radius of the
|
||||||
|
// ellipse
|
||||||
|
if (prediction >= 0) {
|
||||||
|
prediction -= dy;
|
||||||
|
dy -= 2 * _deltaX;
|
||||||
|
y -= _deltaX;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Increase the minor radius of the ellipse and update heuristic variables
|
||||||
|
prediction += dx;
|
||||||
|
dx += 2 * _deltaX;
|
||||||
|
x += _deltaX;
|
||||||
|
|
||||||
|
// If the current ellipse has been reshaped into a circle,
|
||||||
|
// end this loop and enlarge the radius
|
||||||
|
} while (x <= y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
71
engines/draci/walking.h
Normal file
71
engines/draci/walking.h
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
/* 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.
|
||||||
|
*
|
||||||
|
* $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/engines/draci/game.h $
|
||||||
|
* $Id: game.h 45501 2009-10-29 15:26:48Z spalek $
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DRACI_WALKING_H
|
||||||
|
#define DRACI_WALKING_H
|
||||||
|
|
||||||
|
#include "common/rect.h"
|
||||||
|
|
||||||
|
namespace Draci {
|
||||||
|
|
||||||
|
class WalkingMap {
|
||||||
|
public:
|
||||||
|
WalkingMap() : _realWidth(0), _realHeight(0), _mapWidth(0), _mapHeight(0), _byteWidth(0), _data(NULL) { }
|
||||||
|
|
||||||
|
void load(const byte *data, uint length);
|
||||||
|
bool isWalkable(int x, int y) const;
|
||||||
|
Common::Point findNearestWalkable(int x, int y, Common::Rect searchRect) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int _realWidth, _realHeight;
|
||||||
|
int _deltaX, _deltaY;
|
||||||
|
int _mapWidth, _mapHeight;
|
||||||
|
int _byteWidth;
|
||||||
|
const byte *_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enumerates the directions the dragon can look into when arrived.
|
||||||
|
*/
|
||||||
|
enum SightDirection {
|
||||||
|
kDirectionLast, kDirectionMouse, kDirectionUnknown,
|
||||||
|
kDirectionRight, kDirectionLeft, kDirectionIntelligent
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enumerates the animations for the dragon's movement.
|
||||||
|
*/
|
||||||
|
enum Movement {
|
||||||
|
kMoveUndefined = -1,
|
||||||
|
kMoveDown, kMoveUp, kMoveRight, kMoveLeft,
|
||||||
|
kMoveRightDown, kMoveRightUp, kMoveLeftDown, kMoveLeftUp,
|
||||||
|
kMoveDownRight, kMoveUpRight, kMoveDownLeft, kMoveUpLeft,
|
||||||
|
kMoveLeftRight, kMoveRightLeft, kMoveUpStopLeft, kMoveUpStopRight,
|
||||||
|
kSpeakRight, kSpeakLeft, kStopRight, kStopLeft
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End of namespace Draci
|
||||||
|
|
||||||
|
#endif // DRACI_WALKING_H
|
Loading…
Add table
Add a link
Reference in a new issue