diff options
author | Bjørn Lindeijer <bjorn@lindeijer.nl> | 2008-10-09 19:42:13 +0000 |
---|---|---|
committer | Bjørn Lindeijer <bjorn@lindeijer.nl> | 2008-10-09 19:42:13 +0000 |
commit | 3fe1772b1e00344365e3cf8204225be19925b9e5 (patch) | |
tree | 0f66dddac8e14787096c01368611efa53f453134 /src/being.cpp | |
parent | 8cc0423b0c0aaa5dd9e91f673a691e5e634988c1 (diff) | |
download | mana-3fe1772b1e00344365e3cf8204225be19925b9e5.tar.gz mana-3fe1772b1e00344365e3cf8204225be19925b9e5.tar.bz2 mana-3fe1772b1e00344365e3cf8204225be19925b9e5.tar.xz mana-3fe1772b1e00344365e3cf8204225be19925b9e5.zip |
Merged the movement branch into trunk
I consider this the only way forward. In my tests this code isn't actually
doing worse than what was there before. Of course some cases are a bit broken,
and I'm open to any kind of feedback so that we can fix those issues.
Diffstat (limited to 'src/being.cpp')
-rw-r--r-- | src/being.cpp | 230 |
1 files changed, 88 insertions, 142 deletions
diff --git a/src/being.cpp b/src/being.cpp index cf2e3772..7b77ed5a 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -43,27 +43,27 @@ #include "utils/dtor.h" #include "utils/tostring.h" +namespace { +const bool debug_movement = true; +} + int Being::instances = 0; ImageSet *Being::emotionSet = NULL; Being::Being(int id, int job, Map *map): - mX(0), mY(0), mEmotion(0), mEmotionTime(0), mAttackSpeed(350), - mWalkTime(0), mAction(STAND), mJob(job), mId(id), - mWalkSpeed(150), - mSpeedModifier(1024), mSpriteDirection(DIRECTION_DOWN), mDirection(DOWN), mMap(NULL), mEquippedWeapon(NULL), mSpeechTime(0), - mPx(0), mPy(0), mSprites(VECTOREND_SPRITE, NULL), mSpriteIDs(VECTOREND_SPRITE, 0), - mSpriteColors(VECTOREND_SPRITE, "") + mSpriteColors(VECTOREND_SPRITE, ""), + mWalkSpeed(100) { setMap(map); @@ -106,27 +106,36 @@ Being::~Being() delete mSpeechBubble; } -void Being::setPositionInPixels(int x, int y) +void Being::setPosition(const Vector &pos) { - mMap->freeTile(mX / 32, mY / 32, getBlockType()); - mX = x; - mY = y; - mMap->blockTile(x / 32, y / 32, getBlockType()); + mPos = pos; + mDest = pos; } -void Being::adjustCourse(Uint16 srcX, Uint16 srcY, Uint16 dstX, Uint16 dstY) +void Being::adjustCourse(int srcX, int srcY, int dstX, int dstY) { - if (!mMap || (mX == dstX && mY == dstY)) - { + if (debug_movement) + printf("%p adjustCourse(%d, %d, %d, %d)\n", + (void*) this, srcX, srcY, dstX, dstY); + + mDest.x = dstX; + mDest.y = dstY; + + // Find a path to the destination when it is at least a tile away + if (mMap && fabsf((mDest - mPos).length()) > 32) { + setPath(mMap->findPath((int) mPos.x / 32, (int) mPos.y / 32, + dstX / 32, dstY / 32, getWalkMask())); + } else { setPath(Path()); - return; } + // TODO: Evaluate the implementation of this method + /* if (mX / 32 == dstX / 32 && mY / 32 == dstY / 32) { // The being is already on the last tile of the path. Path p; - p.push_back(PATH_NODE(dstX, dstY)); + p.push_back(Position(dstX, dstY)); setPath(p); return; } @@ -173,7 +182,7 @@ void Being::adjustCourse(Uint16 srcX, Uint16 srcY, Uint16 dstX, Uint16 dstY) p1_length = mMap->getMetaTile(dstX / 32, dstY / 32)->Gcost; p1_dist[p1_size - 1] = p1_length; } - p1.push_back(PATH_NODE(dstX, dstY)); + p1.push_back(Position(dstX, dstY)); if (mX / 32 == srcX / 32 && mY / 32 == srcY / 32) { @@ -248,19 +257,24 @@ void Being::adjustCourse(Uint16 srcX, Uint16 srcY, Uint16 dstX, Uint16 dstY) assert(bestLength > 0); setPath(p1, p1_length * 1024 / bestLength); delete[] p1_dist; + */ } -void Being::adjustCourse(Uint16 srcX, Uint16 srcY) +void Being::adjustCourse(int srcX, int srcY) { + if (debug_movement) + printf("%p adjustCourse(%d, %d)\n", (void*) this, srcX, srcY); + if (!mPath.empty()) - { - adjustCourse(srcX, srcY, mPath.back().x, mPath.back().y); - } + adjustCourse(srcX, srcY, mPath.back().x * 32, mPath.back().y * 32); } -void Being::setDestination(Uint16 destX, Uint16 destY) +void Being::setDestination(int destX, int destY) { - adjustCourse(mX, mY, destX, destY); + if (debug_movement) + printf("%p setDestination(%d, %d)\n", (void*) this, destX, destY); + + adjustCourse((int) mPos.x, (int) mPos.y, destX, destY); } void Being::clearPath() @@ -268,34 +282,10 @@ void Being::clearPath() mPath.clear(); } -void Being::setPath(const Path &path, int mod) +void Being::setPath(const Path &path) { + std::cout << this << " New path: " << path << std::endl; mPath = path; - mSpeedModifier = mod >= 512 ? (mod <= 2048 ? mod : 2048) : 512; // TODO: tune bounds - - int sz = mPath.size(); - if (sz > 1) - { - // The path contains intermediate steps, so avoid going through tile - // centers for them. Instead, interpolate the tile offset. - int sx = mX & 31, sy = mY & 31; - int dx = (mPath.back().x & 31) - sx; - int dy = (mPath.back().y & 31) - sy; - Path::iterator j = mPath.begin(); - for (int i = 0; i < sz - 1; ++i) - { - j->x |= sx + dx * (i + 1) / (sz - 1); - j->y |= sy + dy * (i + 1) / (sz - 1); - ++j; - } - } - - if (mAction != WALK && mAction != DEAD) - { - mWalkTime = tick_time; - mStepTime = 0; - nextStep(); - } } void Being::setSprite(int slot, int id, const std::string &color) @@ -339,7 +329,8 @@ void Being::takeDamage(int amount) // Show damage number particleEngine->addTextSplashEffect(damage, 255, 255, 255, font, - mPx + 16, mPy + 16); + (int) mPos.x + 16, + (int) mPos.y + 16); } void Being::handleAttack() @@ -349,11 +340,9 @@ void Being::handleAttack() void Being::setMap(Map *map) { - // Remove sprite from potential previous map if (mMap) { - mMap->freeTile(mX / 32, mY / 32, getBlockType()); mMap->removeSprite(mSpriteIterator); } @@ -363,7 +352,6 @@ void Being::setMap(Map *map) if (mMap) { mSpriteIterator = mMap->addSprite(this); - mMap->blockTile(mX / 32, mY / 32, getBlockType()); } // Clear particle effect list because child particles became invalid @@ -447,21 +435,13 @@ void Being::setDirection(Uint8 direction) SpriteDirection dir; if (mFaceDirection & UP) - { dir = DIRECTION_UP; - } else if (mFaceDirection & RIGHT) - { dir = DIRECTION_RIGHT; - } else if (mFaceDirection & DOWN) - { dir = DIRECTION_DOWN; - } else - { dir = DIRECTION_LEFT; - } mSpriteDirection = dir; for (int i = 0; i < VECTOREND_SPRITE; i++) @@ -471,57 +451,48 @@ void Being::setDirection(Uint8 direction) } } -void Being::nextStep() -{ - if (mPath.empty()) - { - setAction(STAND); - return; - } - - PATH_NODE node = mPath.front(); - mPath.pop_front(); - - mStepX = node.x - mX; - mStepY = node.y - mY; - - int dir = 0, dx = std::abs(mStepX), dy = std::abs(mStepY); - if (dx * 2 > dy) - dir |= mStepX > 0 ? RIGHT : LEFT; - if (dy * 2 > dx) - dir |= mStepY > 0 ? DOWN : UP; - - setDirection(dir); - - if (!mMap->getWalk(node.x / 32, node.y / 32)) - { - setAction(STAND); - return; - } - - setPositionInPixels(node.x, node.y); - setAction(WALK); - mWalkTime += mStepTime / 10; - mStepTime = mWalkSpeed * (int)std::sqrt((double)mStepX * mStepX + (double)mStepY * mStepY) * - mSpeedModifier / (32 * 1024); -} - void Being::logic() { - // Determine whether the being should take another step - if (mAction == WALK && get_elapsed_time(mWalkTime) >= mStepTime) - { - nextStep(); + const Vector dest = (mPath.empty()) ? + mDest : Vector(mPath.front().x * 32 + 16, + mPath.front().y * 32 + 16); + + Vector dir = dest - mPos; + const float length = dir.length(); + + // When we're over 2 pixels from our destination, move to it + // TODO: Should be possible to make it even pixel exact, but this solves + // the jigger caused by moving too far. + if (length > 2.0f) { + const float speed = mWalkSpeed / 100.0f; + dir /= (length / speed); + mPos += dir; + + if (mAction != WALK) + setAction(WALK); + + // Update the player sprite direction + int direction = 0; + const float dx = std::abs(dir.x); + const float dy = std::abs(dir.y); + if (dx * 2 > dy) + direction |= (dir.x > 0) ? RIGHT : LEFT; + if (dy * 2 > dx) + direction |= (dir.y > 0) ? DOWN : UP; + setDirection(direction); + } + else if (!mPath.empty()) { + // TODO: Pop as soon as there is a direct unblocked line to the next + // point on the path. + mPath.pop_front(); + } else if (mAction == WALK) { + setAction(STAND); } // Reduce the time that speech is still displayed if (mSpeechTime > 0) mSpeechTime--; - // Update pixel coordinates - mPx = mX - 16 + getXOffset(); - mPy = mY - 16 + getYOffset(); - if (mEmotion != 0) { mEmotionTime--; @@ -543,7 +514,7 @@ void Being::logic() for (std::list<Particle *>::iterator i = mChildParticleEffects.begin(); i != mChildParticleEffects.end();) { - (*i)->setPosition((float)mPx + 16.0f, (float)mPy + 32.0f); + (*i)->setPosition(mPos.x, mPos.y); if (!(*i)->isAlive()) { (*i)->kill(); @@ -557,14 +528,16 @@ void Being::logic() void Being::draw(Graphics *graphics, int offsetX, int offsetY) const { - int px = mPx + offsetX; - int py = mPy + offsetY; + int px = (int) mPos.x + offsetX; + int py = (int) mPos.y + offsetY; for (int i = 0; i < VECTOREND_SPRITE; i++) { if (mSprites[i] != NULL) { - mSprites[i]->draw(graphics, px, py); + // TODO: Eventually, we probably should fix all sprite offsets so + // that this translation isn't necessary anymore. + mSprites[i]->draw(graphics, px - 16, py - 32); } } } @@ -574,18 +547,18 @@ void Being::drawEmotion(Graphics *graphics, int offsetX, int offsetY) if (!mEmotion) return; - const int px = mPx + offsetX + 3; - const int py = mPy + offsetY - 60; + const int px = (int) mPos.x + offsetX + 3; + const int py = (int) mPos.y + offsetY - 60; const int emotionIndex = mEmotion - 1; - if ( emotionIndex >= 0 && emotionIndex < (int) emotionSet->size() ) + if (emotionIndex >= 0 && emotionIndex < (int) emotionSet->size()) graphics->drawImage(emotionSet->get(emotionIndex), px, py); } void Being::drawSpeech(Graphics *graphics, int offsetX, int offsetY) { - int px = mPx + offsetX; - int py = mPy + offsetY; + int px = (int) mPos.x + offsetX; + int py = (int) mPos.y + offsetY; // Draw speech above this being if (mSpeechTime > 0) @@ -605,32 +578,7 @@ Being::Type Being::getType() const return UNKNOWN; } -int Being::getOffset(int step) const -{ - // Check whether we're walking in the requested direction - if (mAction != WALK || step == 0) { - return 0; - } - - int offset = (get_elapsed_time(mWalkTime) * std::abs(step)) / mStepTime; - - // We calculate the offset _from_ the _target_ location - offset -= std::abs(step); - if (offset > 0) { - offset = 0; - } - - // Going into negative direction? Invert the offset. - if (step < 0) { - offset = -offset; - } - - return offset; -} - - -int -Being::getWidth() const +int Being::getWidth() const { if (mSprites[BASE_SPRITE]) { @@ -641,9 +589,7 @@ Being::getWidth() const } } - -int -Being::getHeight() const +int Being::getHeight() const { if (mSprites[BASE_SPRITE]) { |