diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/being.cpp | 76 | ||||
-rw-r--r-- | src/being.h | 12 | ||||
-rw-r--r-- | src/gui/viewport.cpp | 24 | ||||
-rw-r--r-- | src/localplayer.cpp | 10 | ||||
-rw-r--r-- | src/utils/time.cpp | 5 | ||||
-rw-r--r-- | src/utils/time.h | 7 | ||||
-rw-r--r-- | src/vector.h | 4 |
7 files changed, 71 insertions, 67 deletions
diff --git a/src/being.cpp b/src/being.cpp index b622143a..c23a650d 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -128,6 +128,7 @@ void Being::setSubtype(Uint16 subtype) break; } } + bool Being::isTargetSelection() const { return mInfo->targetSelection; @@ -768,43 +769,59 @@ void Being::logic() restoreAllSpriteParticles(); } - if ((mAction != DEAD) && !mSpeedPixelsPerSecond.isNull()) + if (mAction != DEAD && !mSpeedPixelsPerSecond.isNull()) + { + updateMovement(); + } + + ActorSprite::logic(); + + // Remove it after 1.5 secs if the dead animation isn't long enough, + // or simply play it until it's finished. + if (!isAlive() && Net::getGameHandler()->removeDeadBeings() && getType() != PLAYER) + if (mActionTimer.elapsed() > std::max(getDuration(), 1500)) + actorSpriteManager->scheduleDelete(this); +} + +void Being::updateMovement() +{ + float dt = Time::deltaTime(); + + while (dt > 0.f) { - const Vector dest = (mPath.empty()) ? - mDest : Vector(mPath.front().x, - mPath.front().y); + const Vector dest = mPath.empty() ? mDest + : Vector(mPath.front().x, + mPath.front().y); // Avoid going to flawed destinations + // We make the being stop move in that case. if (dest.x <= 0 || dest.y <= 0) { - // We make the being stop move in that case. mDest = mPos; mPath.clear(); - // By returning now, we're losing one tick for the rest of the logic - // but as we have reset the destination, the next tick will be fine. - return; + break; } // The Vector representing the difference between current position // and the next destination path node. - Vector dir = dest - mPos; - - float distance = dir.length(); + const Vector dir = dest - mPos; // When we've not reached our destination, move to it. - if (distance > 0.0f) + if (!dir.isNull()) { + const float distanceToDest = dir.length(); + // The deplacement of a point along a vector is calculated // using the Unit Vector (â) multiplied by the point speed. // â = a / ||a|| (||a|| is the a length.) // Then, diff = (dir/||dir||) * speed. const Vector normalizedDir = dir.normalized(); - const int ms = Time::deltaTimeMs(); - Vector diff(normalizedDir.x * mSpeedPixelsPerSecond.x * ms / 1000.0f, - normalizedDir.y * mSpeedPixelsPerSecond.y * ms / 1000.0f); + Vector diff(normalizedDir.x * mSpeedPixelsPerSecond.x * dt, + normalizedDir.y * mSpeedPixelsPerSecond.y * dt); + const float distanceToMove = diff.length(); // Test if we don't miss the destination by a move too far: - if (diff.length() > distance) + if (distanceToMove > distanceToDest) { setPosition(dest); @@ -812,13 +829,16 @@ void Being::logic() // path point, if existing. if (!mPath.empty()) mPath.pop_front(); + + // Set dt to the time left after performing this move. + dt -= dt * (distanceToDest / distanceToMove); } else { // Otherwise, go to it using the nominal speed. setPosition(mPos + diff); - // And reset the nominalLength to the actual move length - distance = diff.length(); + // And set the remaining time to 0. + dt = 0.f; } if (mAction != MOVE) @@ -831,12 +851,11 @@ void Being::logic() // 1. It is not the local_player // 2. When it is the local_player but only by mouse // (because in that case, the path can have more than one tile.) - if ((local_player == this && local_player->isPathSetByMouse()) - || local_player != this) + if (local_player != this || local_player->isPathSetByMouse()) { int direction = 0; const float dx = std::abs(dir.x); - float dy = std::abs(dir.y); + const float dy = std::abs(dir.y); if (dx > dy) direction |= (dir.x > 0) ? RIGHT : LEFT; @@ -852,19 +871,13 @@ void Being::logic() // remove it and go to the next one. mPath.pop_front(); } - else if (mAction == MOVE) + else { - setAction(STAND); + if (mAction == MOVE) + setAction(STAND); + break; } } - - ActorSprite::logic(); - - // Remove it after 1.5 secs if the dead animation isn't long enough, - // or simply play it until it's finished. - if (!isAlive() && Net::getGameHandler()->removeDeadBeings() && getType() != PLAYER) - if (mActionTimer.elapsed() > std::max(getDuration(), 1500)) - actorSpriteManager->scheduleDelete(this); } void Being::drawSpeech(int offsetX, int offsetY) @@ -1198,7 +1211,6 @@ void Being::event(Event::Channel channel, const Event &event) setShowName(config.getBoolValue("visiblenames")); } } - } void Being::setMap(Map *map) diff --git a/src/being.h b/src/being.h index 5c939fcc..8f596810 100644 --- a/src/being.h +++ b/src/being.h @@ -319,14 +319,7 @@ class Being : public ActorSprite, public EventListener * in ticks per tile for eAthena, * in tiles per second for Manaserv (0.1 precision). */ - virtual void setMoveSpeed(const Vector &speed); - - /** - * Gets the original Move speed. - * in ticks per tile for eAthena, - * in tiles per second for Manaserv (0.1 precision). - */ - Vector getMoveSpeed() const { return mMoveSpeed; } + void setMoveSpeed(const Vector &speed); /** * Sets the attack speed. @@ -530,6 +523,7 @@ class Being : public ActorSprite, public EventListener bool mIsGM = false; private: + void updateMovement(); const Type mType; @@ -539,7 +533,7 @@ class Being : public ActorSprite, public EventListener /** * Walk speed for x and y movement values. * In ticks per tile for eAthena, - * In pixels per second for Manaserv. + * In tiles per second for Manaserv. */ Vector mMoveSpeed; diff --git a/src/gui/viewport.cpp b/src/gui/viewport.cpp index 8dbdf7c7..6c8016dc 100644 --- a/src/gui/viewport.cpp +++ b/src/gui/viewport.cpp @@ -41,6 +41,7 @@ #include "utils/stringutils.h" +#include <algorithm> #include <cmath> Viewport::Viewport() @@ -166,24 +167,21 @@ void Viewport::draw(gcn::Graphics *gcnGraphics) }; // Don't move camera so that the end of the map is on screen + // Center camera on map if the map is smaller than the screen const int mapWidthPixels = mMap->getWidth() * mMap->getTileWidth(); const int mapHeightPixels = mMap->getHeight() * mMap->getTileHeight(); const int viewXmax = mapWidthPixels - graphics->getWidth(); const int viewYmax = mapHeightPixels - graphics->getHeight(); - if (mPixelViewX < 0) - mPixelViewX = 0; - if (mPixelViewY < 0) - mPixelViewY = 0; - if (mPixelViewX > viewXmax) - mPixelViewX = viewXmax; - if (mPixelViewY > viewYmax) - mPixelViewY = viewYmax; - // Center camera on map if the map is smaller than the screen - if (mapWidthPixels < graphics->getWidth()) - mPixelViewX = (mapWidthPixels - graphics->getWidth()) / 2; - if (mapHeightPixels < graphics->getHeight()) - mPixelViewY = (mapHeightPixels - graphics->getHeight()) / 2; + if (viewXmax > 0) + mPixelViewX = std::clamp<float>(mPixelViewX, 0, viewXmax); + else + mPixelViewX = viewXmax / 2; + + if (viewYmax > 0) + mPixelViewY = std::clamp<float>(mPixelViewY, 0, viewYmax); + else + mPixelViewY = viewYmax / 2; // Draw black background if map is smaller than the screen if ( mapWidthPixels < graphics->getWidth() diff --git a/src/localplayer.cpp b/src/localplayer.cpp index 1a91ffb7..5075c44c 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -746,16 +746,6 @@ void LocalPlayer::startWalking(unsigned char dir) return; } - int dx = 0, dy = 0; - if (dir & UP) - dy--; - if (dir & DOWN) - dy++; - if (dir & LEFT) - dx--; - if (dir & RIGHT) - dx++; - nextTile(dir); } diff --git a/src/utils/time.cpp b/src/utils/time.cpp index c89914fa..df20fc23 100644 --- a/src/utils/time.cpp +++ b/src/utils/time.cpp @@ -41,6 +41,11 @@ unsigned deltaTimeMs() return s_deltaTimeMs; } +float deltaTime() +{ + return s_deltaTimeMs / 1000.f; +} + static int32_t getElapsedTime(uint32_t timeMs) { return static_cast<int32_t>(s_absoluteTimeMs - timeMs); diff --git a/src/utils/time.h b/src/utils/time.h index ac7cd351..58b8164a 100644 --- a/src/utils/time.h +++ b/src/utils/time.h @@ -39,11 +39,16 @@ namespace Time uint32_t absoluteTimeMs(); /** - * The time in milliseconds since the last frame, maximized to 1000ms. + * The time in milliseconds since the last frame, but never more than 1000. */ unsigned deltaTimeMs(); /** + * The time in seconds since the last frame, but never more than 1. + */ +float deltaTime(); + +/** * Called at the start of each frame, updates the above variables. */ void beginFrame(); diff --git a/src/vector.h b/src/vector.h index 5d7d63d7..6bf6d81a 100644 --- a/src/vector.h +++ b/src/vector.h @@ -140,7 +140,7 @@ class Vector */ float length() const { - return sqrtf(x * x + y * y + z * z); + return std::sqrt(x * x + y * y + z * z); } /** @@ -156,7 +156,7 @@ class Vector */ float manhattanLength() const { - return fabsf(x) + fabsf(y) + fabsf(z); + return std::abs(x) + std::abs(y) + std::abs(z); } /** |