diff options
author | Bertram <bertram@cegetel.net> | 2010-02-27 15:26:22 +0100 |
---|---|---|
committer | Bertram <yohanndotferreiraatorange.fr> | 2010-04-12 23:50:21 +0200 |
commit | 98967ec85b48fcc85d1468b7fa02b847389431fb (patch) | |
tree | 48654c088a161208848928451965563eacdcd69c | |
parent | d95381372559c75b1829b43f9476c21b166f6dad (diff) | |
download | mana-client-98967ec85b48fcc85d1468b7fa02b847389431fb.tar.gz mana-client-98967ec85b48fcc85d1468b7fa02b847389431fb.tar.bz2 mana-client-98967ec85b48fcc85d1468b7fa02b847389431fb.tar.xz mana-client-98967ec85b48fcc85d1468b7fa02b847389431fb.zip |
One step closer to the full movement system ready.
The LocalPlayer::nextTile() function has been sanitized and the movement
system has been fine tuned, but yet not optimized.
(Optimizations and riddance of 32 hard-coded value will come later.)
There is just one case left not handled correctly when the character
walked within one tile south-east of a blocking one and then
the player click north-west (through the blocking tile) on a walkable
location. Quite rare but still here.
-rw-r--r-- | src/being.cpp | 32 | ||||
-rw-r--r-- | src/localplayer.cpp | 148 |
2 files changed, 134 insertions, 46 deletions
diff --git a/src/being.cpp b/src/being.cpp index d18fcb8f..b248ffa0 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -621,7 +621,7 @@ void Being::logic() const float nominalLength = dir.length(); // When we've not reached our destination, move to it. - if (nominalLength > 1.0f && !mWalkSpeed.isNull()) + if (nominalLength > 0.0f && !mWalkSpeed.isNull()) { // The deplacement of a point along a vector is calculated // using the Unit Vector (รข) multiplied by the point speed. @@ -648,22 +648,26 @@ void Being::logic() if (mAction != WALK) setAction(WALK); - // Update the player sprite direction - int direction = 0; - const float dx = std::abs(dir.x); - float dy = std::abs(dir.y); + // Update the player sprite direction. + // N.B.: We only change this if the distance is more than one pixel. + if (nominalLength > 1.0f) + { + int direction = 0; + const float dx = std::abs(dir.x); + float dy = std::abs(dir.y); - // When not using mouse for the player, we slightly prefer - // UP and DOWN position, especially when walking diagonally. - if (this == player_node && !player_node->isPathSetByMouse()) - dy = dy + 2; + // When not using mouse for the player, we slightly prefer + // UP and DOWN position, especially when walking diagonally. + if (this == player_node && !player_node->isPathSetByMouse()) + dy = dy + 2; - if (dx > dy) - direction |= (dir.x > 0) ? RIGHT : LEFT; - else - direction |= (dir.y > 0) ? DOWN : UP; + if (dx > dy) + direction |= (dir.x > 0) ? RIGHT : LEFT; + else + direction |= (dir.y > 0) ? DOWN : UP; - setDirection(direction); + setDirection(direction); + } } else if (!mPath.empty()) { diff --git a/src/localplayer.cpp b/src/localplayer.cpp index 2cf59f12..684c21e1 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -300,38 +300,119 @@ void LocalPlayer::nextTile(unsigned char dir = 0) if (dir & RIGHT) dx++; - // Prevent skipping corners over colliding tiles - if (dx && !mMap->getWalk(((int) pos.x + dx) / 32, - (int) pos.y / 32, getWalkMask())) - dx = 16 - (int) pos.x % 32; - if (dy && !mMap->getWalk((int) pos.x / 32, - ((int) pos.y + dy) / 32, getWalkMask())) - dy = 16 - (int) pos.y % 32; - // Choose a straight direction when diagonal target is blocked - if (dx && dy && !mMap->getWalk((pos.x + dx) / 32, - (pos.y + dy) / 32, getWalkMask())) - dx = 16 - (int) pos.x % 32; + if (dx && dy && !mMap->getWalk((pos.x / 32) + dx, + (pos.y / 32) + dy, getWalkMask())) + { + // If one straight direction is blocked, and not the other, + // we choose the free one. + if (!mMap->getWalk((pos.x / 32) + dx, pos.y / 32, + getWalkMask()) + && mMap->getWalk((pos.x / 32), pos.y / 32 + dy, + getWalkMask())) + { + dx = 0; + } + + else if (mMap->getWalk((pos.x / 32) + dx, pos.y / 32, + getWalkMask()) + && !mMap->getWalk((pos.x / 32), pos.y / 32 + dy, + getWalkMask())) + { + dy = 0; + } + else + { + // In the other cases, we test if the current tile offset + // is more inclined to one straight direction or another. + int fx = (int) pos.x % 32; + int fy = (int) pos.y % 32; + + // Top-left case + if (dx < 0 && dy < 0) + { + // Go left when below the corner + if (fy >= (fx / mMap->getTileWidth() + * mMap->getTileHeight())) + dy = 0; + else // Go up otherwise + dx = 0; + } + + // Bottom-right case + if (dx > 0 && dy > 0) + { + // Go down when below the corner + if (fy >= (fx / mMap->getTileWidth() + * mMap->getTileHeight())) + dx = 0; + else // Go right otherwise + dy = 0; + } + + // Top-right case + if (dx > 0 && dy < 0) + { + // Go right when below the corner + if (fy >= (fx / mMap->getTileHeight() + - (fx / mMap->getTileWidth() + * mMap->getTileHeight()) )) + dy = 0; + else // Go up otherwise + dx = 0; + } + + // Bottom-left case + if (dx < 0 && dy > 0) + { + // Go down when below the corner + if (fy >= (fx / mMap->getTileHeight() + - (fx / mMap->getTileWidth() + * mMap->getTileHeight()) )) + dx = 0; + else // Go left otherwise + dy = 0; + } + } + } - int dScaler; // Distance to walk + int dScaler = 0; // Distance to walk in pixels - // Checks our path up to 1 tiles, if a blocking tile is found - // We go to the last good tile, and break out of the loop - for (dScaler = 1; dScaler <= 32; dScaler++) + if (dx || dy) { - if ( (dx || dy) && - !mMap->getWalk( ((int) pos.x + (dx * dScaler)) / 32, - ((int) pos.y + (dy * dScaler)) / 32, getWalkMask()) ) + Position refPosition(0, 0); + Position testPosition(0, 0); + // Checks our path up to 1 tiles, if a blocking tile is found + // We go to the last good tile, and break out of the loop + for (dScaler = 1; dScaler <= std::max(mMap->getTileWidth(), + mMap->getTileHeight()); + dScaler++) { - dScaler--; - break; + refPosition = Position((int) pos.x + (dx * dScaler) / 32, + (int) pos.y + (dy * dScaler) / 32); + testPosition = checkNodeOffsets(refPosition); + if (refPosition.x != testPosition.x + || refPosition.y != testPosition.y) + { + dScaler--; + break; + } } } - if (dScaler > 16) + // Test also current position to avoid being blocked on corners + // in certain situations. + Position currentPosition((int) pos.x, (int) pos.y); + Position testPosition = checkNodeOffsets(currentPosition); + if (dScaler > 0) + { + setDestination((int) pos.x + (dx * dScaler), + (int) pos.y + (dy * dScaler)); + } + else if (currentPosition.x != testPosition.x + || currentPosition.y != testPosition.y) { - //effectManager->trigger(15, (int) pos.x + (dx * dScaler), (int) pos.y + (dy * dScaler)); - setDestination((int) pos.x + (dx * dScaler), (int) pos.y + (dy * dScaler)); + setDestination(testPosition.x, testPosition.y); } else if (dir != mDirection) { @@ -464,7 +545,7 @@ void LocalPlayer::setDestination(int x, int y) // we inform the Server. if ((x == mDest.x && y == mDest.y) || Net::getNetworkType() == ServerInfo::EATHENA) - Net::getPlayerHandler()->setDestination(x, y, mDirection); + Net::getPlayerHandler()->setDestination(x, y, mDirection); } mPickUpTarget = NULL; @@ -518,9 +599,7 @@ void LocalPlayer::setWalkingDir(int dir) void LocalPlayer::startWalking(unsigned char dir) { // This function is called by setWalkingDir(), - // but also by nextStep() for eAthena... - - // TODO: Evaluate the implementation of this method for Manaserv + // but also by nextTile() for eAthena... if (!mMap || !dir) return; @@ -556,11 +635,13 @@ void LocalPlayer::startWalking(unsigned char dir) dy = 0; // Choose a straight direction when diagonal target is blocked - if (dx && dy && !mMap->getWalk(getTileX() + dx, getTileY() + dy, getWalkMask())) + if (dx && dy && !mMap->getWalk(getTileX() + dx, getTileY() + dy, + getWalkMask())) dx = 0; // Walk to where the player can actually go - if ((dx || dy) && mMap->getWalk(getTileX() + dx, getTileY() + dy, getWalkMask())) + if ((dx || dy) && mMap->getWalk(getTileX() + dx, getTileY() + dy, + getWalkMask())) { setDestination(getTileX() + dx, getTileY() + dy); } @@ -628,7 +709,8 @@ void LocalPlayer::useSpecial(int special) void LocalPlayer::setSpecialStatus(int id, int current, int max, int recharge) { - logger->log("SpecialUpdate Skill #%d -- (%d/%d) -> %d", id, current, max, recharge); + logger->log("SpecialUpdate Skill #%d -- (%d/%d) -> %d", id, current, max, + recharge); mSpecials[id].currentMana = current; mSpecials[id].neededMana = max; mSpecials[id].recharge = recharge; @@ -739,7 +821,8 @@ void LocalPlayer::stopAttack() void LocalPlayer::raiseAttribute(int attr) { - // we assume that the server allows the change. When not we will undo it later. + // we assume that the server allows the change. + // When not we will undo it later. mCharacterPoints--; IntMap::iterator it = mAttributeBase.find(attr); if (it != mAttributeBase.end()) @@ -749,7 +832,8 @@ void LocalPlayer::raiseAttribute(int attr) void LocalPlayer::lowerAttribute(int attr) { - // we assume that the server allows the change. When not we will undo it later. + // we assume that the server allows the change. + // When not we will undo it later. mCorrectionPoints--; mCharacterPoints++; IntMap::iterator it = mAttributeBase.find(attr); |