summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/being.cpp76
-rw-r--r--src/being.h12
-rw-r--r--src/gui/viewport.cpp24
-rw-r--r--src/localplayer.cpp10
-rw-r--r--src/utils/time.cpp5
-rw-r--r--src/utils/time.h7
-rw-r--r--src/vector.h4
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);
}
/**