summaryrefslogtreecommitdiff
path: root/src/object.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/object.cpp')
-rw-r--r--src/object.cpp99
1 files changed, 99 insertions, 0 deletions
diff --git a/src/object.cpp b/src/object.cpp
index 5c03981a..f6863cd4 100644
--- a/src/object.cpp
+++ b/src/object.cpp
@@ -21,11 +21,110 @@
*/
#include <cassert>
+#include <cmath>
#include "object.h"
+#include "map.h"
+#include "mapmanager.h"
+
void Object::setID(int id)
{
assert(mID < 0);
mID = id;
}
+
+void MovingObject::move()
+{
+ unsigned mSrcX = getX(), mSrcY = getY();
+ if (mSrcX == mDstX && mSrcY == mDstY) {
+ mNewX = mDstX;
+ mNewY = mDstY;
+ return;
+ }
+
+ Map *map = MapManager::instance().getMap(getMapId());
+ int tileW = map->getTileWidth(), tileH = map->getTileHeight();
+ int tileD = (int) std::sqrt((double)(tileW * tileW + tileH * tileH));
+ int tileSX = mSrcX / tileW, fracSX = mSrcX % tileW - tileW / 2;
+ int tileSY = mSrcY / tileH, fracSY = mSrcY % tileH - tileH / 2;
+ int tileDX = mDstX / tileW, fracDX = mDstX % tileW - tileW / 2;
+ int tileDY = mDstY / tileH, fracDY = mDstY % tileH - tileH / 2;
+
+ std::list<PATH_NODE> path;
+ if (tileSX != tileDX || tileSY != tileDY) {
+ path = map->findPath(tileSX, tileSY, tileDX, tileDY);
+ if (path.empty()) {
+ mNewX = mDstX = mSrcX;
+ mNewY = mDstY = mSrcY;
+ return;
+ }
+ }
+
+ int tileCX = tileSX, tileCY = tileSY, fracCX = fracSX, fracCY = fracSY;
+ int tileNX = tileDX, tileNY = tileDY, left = mSpeed;
+ int vecX = 0, vecY = 0, cost = 0;
+
+ for (std::list<PATH_NODE>::const_iterator it = path.begin(),
+ it_end = path.end(); it != it_end; ++it) {
+
+ tileNX = it->x;
+ tileNY = it->y;
+ assert(tileNX != tileCX && tileNY != tileCY &&
+ tileNX != tileDX && tileNY != tileDY);
+
+ if (fracCX != 0 || fracCY != 0) {
+ // not at the tile center, move toward the next tile center
+ vecX = -fracCX + tileW * (tileNX - tileCX);
+ vecY = -fracCY + tileH * (tileNY - tileCY);
+ cost = (int) std::sqrt((double)(vecX * vecX + vecY * vecY));
+ } else {
+ // at a tile center and toward the next tile center
+ assert(abs(tileNX - tileCX) <= 1 && abs(tileNY - tileCY) <= 1);
+ if (tileNX != tileCX) {
+ vecX = tileW * (tileNX - tileCX);
+ if (tileNY != tileCY) {
+ vecY = tileH * (tileNY - tileCY);
+ cost = tileD;
+ } else {
+ vecY = 0;
+ cost = tileW;
+ }
+ } else {
+ assert(tileNY != tileCY);
+ vecX = 0;
+ vecY = tileH * (tileNY - tileCY);
+ cost = tileH;
+ }
+ }
+
+ if (cost > left) break;
+ // enough movement left to reach the next tile center
+ tileCX = tileNX;
+ tileCY = tileNY;
+ fracCX = 0;
+ fracCY = 0;
+ vecX = 0;
+ vecY = 0;
+ left -= cost;
+ }
+
+ if ((vecX == 0 && vecY == 0) && (fracCX != fracDX || fracCY != fracDY)) {
+ // walk toward the destination
+ vecX = fracDX - fracCX + tileW * (tileDX - tileCX);
+ vecY = fracDY - fracCY + tileH * (tileDY - tileCY);
+ cost = (int) std::sqrt((double)(vecX * vecX + vecY * vecY));
+ }
+
+ if (cost <= left) {
+ // enough movement left to perform the last step
+ mNewX = mDstX;
+ mNewY = mDstY;
+ return;
+ }
+
+ // linear interpolation along the vector
+ assert(cost > 0);
+ mNewX = tileCX * tileW + tileW / 2 + fracCX + vecX * left / cost;
+ mNewY = tileCY * tileH + tileH / 2 + fracCY + vecY * left / cost;
+}