summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorThorbjørn Lindeijer <bjorn@lindeijer.nl>2024-10-04 18:24:47 +0200
committerThorbjørn Lindeijer <bjorn@lindeijer.nl>2024-10-08 21:03:44 +0200
commitd9a6aa323b00e23e7c858e1feeacfd3ee26bc298 (patch)
treec5fb35d658cdfd7c376a2ae2cf8f2523406aaeeb /src
parent573df67919ec5f65a6b2ad51ed8aed31c9cfe4a6 (diff)
downloadmana-d9a6aa323b00e23e7c858e1feeacfd3ee26bc298.tar.gz
mana-d9a6aa323b00e23e7c858e1feeacfd3ee26bc298.tar.bz2
mana-d9a6aa323b00e23e7c858e1feeacfd3ee26bc298.tar.xz
mana-d9a6aa323b00e23e7c858e1feeacfd3ee26bc298.zip
Smoother keyboard movement
This change addresses the slight stutter and broken animation playback when walking with the keyboard. Once the end of the path has been reached but a movement key is still held, the LocalPlayer now immediately calculates a new path rather than waiting on the next logic update.
Diffstat (limited to 'src')
-rw-r--r--src/being.cpp8
-rw-r--r--src/being.h11
-rw-r--r--src/localplayer.cpp30
-rw-r--r--src/localplayer.h16
4 files changed, 39 insertions, 26 deletions
diff --git a/src/being.cpp b/src/being.cpp
index c23a650d..1ab13250 100644
--- a/src/being.cpp
+++ b/src/being.cpp
@@ -828,8 +828,13 @@ void Being::updateMovement()
// Also, if the destination is reached, try to get the next
// path point, if existing.
if (!mPath.empty())
+ {
mPath.pop_front();
+ if (mPath.empty())
+ pathFinished();
+ }
+
// Set dt to the time left after performing this move.
dt -= dt * (distanceToDest / distanceToMove);
}
@@ -870,6 +875,9 @@ void Being::updateMovement()
// If the current path node has been reached,
// remove it and go to the next one.
mPath.pop_front();
+
+ if (mPath.empty())
+ pathFinished();
}
else
{
diff --git a/src/being.h b/src/being.h
index 8f596810..6636af7b 100644
--- a/src/being.h
+++ b/src/being.h
@@ -175,7 +175,7 @@ class Being : public ActorSprite, public EventListener
* @param damage the amount of damage dealt (0 means miss)
* @param attackId the attack id
*/
- virtual void handleAttack(Being *victim, int damage, int attackId = 1);
+ void handleAttack(Being *victim, int damage, int attackId = 1);
const ItemInfo *getEquippedWeapon() const
{ return mEquippedWeapon; }
@@ -380,7 +380,7 @@ class Being : public ActorSprite, public EventListener
/**
* Returns the being's pixel radius used to detect collisions.
*/
- virtual int getCollisionRadius() const;
+ int getCollisionRadius() const;
/**
* Shoots a missile particle from this being, to target being
@@ -403,7 +403,7 @@ class Being : public ActorSprite, public EventListener
/**
* Sets the gender of this being.
*/
- virtual void setGender(Gender gender);
+ void setGender(Gender gender);
Gender getGender() const
{ return mGender; }
@@ -477,6 +477,11 @@ class Being : public ActorSprite, public EventListener
*/
int getSpeechTextYPosition() const;
+ /**
+ * Called when the being has reached the end of its path.
+ */
+ virtual void pathFinished() {}
+
const BeingInfo *mInfo;
Timer mActionTimer; /**< Time spent in current action. TODO: Remove use of it */
diff --git a/src/localplayer.cpp b/src/localplayer.cpp
index 5075c44c..40849379 100644
--- a/src/localplayer.cpp
+++ b/src/localplayer.cpp
@@ -700,23 +700,33 @@ void LocalPlayer::setWalkingDir(int dir)
// Don't compute a new path before the last one set by keyboard is finished.
// This permits to avoid movement glitches and server spamming.
- const Vector &pos = getPosition();
- const Vector &dest = getDestination();
- if (!isPathSetByMouse() && (pos.x != dest.x || pos.y != dest.y))
- return;
+ if (!isPathSetByMouse())
+ {
+ const Vector &pos = getPosition();
+ const Vector &dest = getDestination();
+
+ if (pos.x != dest.x || pos.y != dest.y)
+ {
+ mWalkingDir = dir;
+ return;
+ }
+ }
// If the player is pressing a key, and its different from what he has
// been pressing, stop (do not send this stop to the server) and
// start in the new direction
- if (dir && (dir != getWalkingDir()))
+ if (dir && dir != mWalkingDir)
+ {
local_player->stopWalking(false);
-
- // Else, he is not pressing a key,
- // and the current path hasn't been sent by mouse,
- // then let the path die (1/2 tile after that.)
- // This permit to avoid desyncs with other clients.
+ }
+ // Else, he is not pressing a key, and the current path hasn't been sent by
+ // mouse, then let the path die (1/2 tile after that.) This permit to avoid
+ // desyncs with other clients.
else if (!dir)
+ {
+ mWalkingDir = 0;
return;
+ }
cancelGoToTarget();
diff --git a/src/localplayer.h b/src/localplayer.h
index 43453498..34021cbd 100644
--- a/src/localplayer.h
+++ b/src/localplayer.h
@@ -100,18 +100,6 @@ class LocalPlayer final : public Being
void stopAttack();
/**
- * Overridden to do nothing. The attacks of the local player are
- * displayed as soon as the player attacks, not when the server says
- * the player does.
- *
- * @param victim the victim being
- * @param damage the amount of damage dealt (0 means miss)
- * @param type the attack type
- */
- //virtual void handleAttack(Being *victim, int damage, AttackType type) {}
- virtual void handleAttack() {}
-
- /**
* Returns the current target of the player. Returns 0 if no being is
* currently targeted.
*/
@@ -209,7 +197,7 @@ class LocalPlayer final : public Being
/**
* set the next path tile when walking and using the keyboard.
*/
- virtual void nextTile(unsigned char dir);
+ void nextTile(unsigned char dir);
/**
* Compute the next pathnode location when walking using keyboard.
@@ -217,6 +205,8 @@ class LocalPlayer final : public Being
*/
Position getNextWalkPosition(unsigned char dir);
+ void pathFinished() override { nextTile(mWalkingDir); }
+
int mAttackRange = -1;
Timer mLastTargetTimer; /**< Timer for last targeting action. */