summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuillaume Melquiond <guillaume.melquiond@gmail.com>2006-08-27 19:05:07 +0000
committerGuillaume Melquiond <guillaume.melquiond@gmail.com>2006-08-27 19:05:07 +0000
commit6f6d061b23c6c70c632fb3ec6aa3735325f701e0 (patch)
treea0d57853d826ebca0abe9ec86973c64bec688427
parenta544d1b3bf1d133d5877aa97d59d7128555e69fc (diff)
downloadmana-client-6f6d061b23c6c70c632fb3ec6aa3735325f701e0.tar.gz
mana-client-6f6d061b23c6c70c632fb3ec6aa3735325f701e0.tar.bz2
mana-client-6f6d061b23c6c70c632fb3ec6aa3735325f701e0.tar.xz
mana-client-6f6d061b23c6c70c632fb3ec6aa3735325f701e0.zip
Implemented pixel-grained movements.
-rw-r--r--ChangeLog3
-rw-r--r--src/being.cpp61
-rw-r--r--src/being.h15
-rw-r--r--src/engine.cpp10
-rw-r--r--src/gui/gui.cpp6
-rw-r--r--src/localplayer.cpp34
6 files changed, 81 insertions, 48 deletions
diff --git a/ChangeLog b/ChangeLog
index 2d7cbdd9..ecaf0b13 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -30,7 +30,8 @@
Being::mFrame field.
* src/localplayer.cpp, src/player.cpp, src/monster.h, src/being.cpp,
src/monster.cpp, src/player.h: Cleaned the logic members.
-
+ * src/engine.cpp, src/localplayer.cpp, src/gui/gui.cpp, src/being.cpp,
+ src/being.h: Implemented pixel-grained movements.
2006-08-26 Bjørn Lindeijer <bjorn@lindeijer.nl>
diff --git a/src/being.cpp b/src/being.cpp
index 46fb67bb..b497d58f 100644
--- a/src/being.cpp
+++ b/src/being.cpp
@@ -23,6 +23,7 @@
#include "being.h"
#include <algorithm>
+#include <cmath>
#include "animatedsprite.h"
#include "equipment.h"
@@ -48,7 +49,7 @@ PATH_NODE::PATH_NODE(Uint16 iX, Uint16 iY):
Being::Being(Uint32 id, Uint16 job, Map *map):
mJob(job),
mX(0), mY(0), mDirection(DOWN),
- mAction(0),
+ mAction(STAND),
mWalkTime(0),
mEmotion(0), mEmotionTime(0),
mAttackSpeed(350),
@@ -77,10 +78,31 @@ Being::~Being()
void
Being::setDestination(Uint16 destX, Uint16 destY)
{
- if (mMap)
+ if (!mMap || (mX == destX && mY == destY))
{
- setPath(mMap->findPath(mX / 32, mY / 32, destX / 32, destY / 32));
+ return;
+ }
+
+ Path p;
+ if (mX / 32 != destX / 32 || mY / 32 != destY / 32)
+ {
+ p = mMap->findPath(mX / 32, mY / 32, destX / 32, destY / 32);
+ if (p.empty())
+ {
+ setPath(p);
+ return;
+ }
+ // Remove last tile so that it can be replaced by the exact destination.
+ p.pop_back();
+ for (Path::iterator i = p.begin(), i_end = p.end(); i != i_end; ++i)
+ {
+ // Set intermediate step to tile centers.
+ i->x = i->x * 32 + 16;
+ i->y = i->y * 32 + 16;
+ }
}
+ p.push_back(PATH_NODE(destX, destY));
+ setPath(p);
}
void
@@ -96,8 +118,9 @@ Being::setPath(const Path &path)
if (mAction != WALK && mAction != DEAD)
{
- nextStep();
mWalkTime = tick_time;
+ mStepTime = 0;
+ nextStep();
}
}
@@ -265,28 +288,31 @@ Being::nextStep()
mPath.pop_front();
int dir = 0;
- if (node.x > mX / 32)
+ if (node.x > mX)
dir |= RIGHT;
- else if (node.x < mX / 32)
+ else if (node.x < mX)
dir |= LEFT;
- if (node.y > mY / 32)
+ if (node.y > mY)
dir |= DOWN;
- else if (node.y < mY / 32)
+ else if (node.y < mY)
dir |= UP;
setDirection(dir);
- mX = node.x * 32 + 16;
- mY = node.y * 32 + 16;
+ mStepX = node.x - mX;
+ mStepY = node.y - mY;
+ mX = node.x;
+ mY = node.y;
setAction(WALK);
- mWalkTime += mWalkSpeed / 10;
+ mWalkTime += mStepTime / 10;
+ mStepTime = mWalkSpeed * (int)std::sqrt((double)mStepX * mStepX + (double)mStepY * mStepY) / 32;
}
void
Being::logic()
{
// Determine whether the being should take another step
- if (mAction == WALK && get_elapsed_time(mWalkTime) >= mWalkSpeed)
+ if (mAction == WALK && get_elapsed_time(mWalkTime) >= mStepTime)
{
nextStep();
}
@@ -435,24 +461,23 @@ Being::setWeaponById(Uint16 weapon)
}
}
-int
-Being::getOffset(char pos, char neg) const
+int Being::getOffset(int step) const
{
// Check whether we're walking in the requested direction
- if (mAction != WALK || !(mDirection & (pos | neg))) {
+ if (mAction != WALK || step == 0) {
return 0;
}
- int offset = (get_elapsed_time(mWalkTime) * 32) / mWalkSpeed;
+ int offset = (get_elapsed_time(mWalkTime) * std::abs(step)) / mStepTime;
// We calculate the offset _from_ the _target_ location
- offset -= 32;
+ offset -= std::abs(step);
if (offset > 0) {
offset = 0;
}
// Going into negative direction? Invert the offset.
- if (mDirection & pos) {
+ if (step < 0) {
offset = -offset;
}
diff --git a/src/being.h b/src/being.h
index 38c62dbb..7c08ab81 100644
--- a/src/being.h
+++ b/src/being.h
@@ -324,13 +324,13 @@ class Being : public Sprite
* Get the current X pixel offset.
*/
int
- getXOffset() const { return getOffset(LEFT, RIGHT); }
+ getXOffset() const { return getOffset(mStepX); }
/**
* Get the current Y pixel offset.
*/
int
- getYOffset() const { return getOffset(UP, DOWN); }
+ getYOffset() const { return getOffset(mStepY); }
std::auto_ptr<Equipment> mEquipment;
int mVisibleEquipment[6]; /**< Visible equipments */
@@ -343,12 +343,6 @@ class Being : public Sprite
setPath(const Path &path);
/**
- * Calculates the offset in the given directions.
- * If walking in direction 'neg' the value is negated.
- */
- int getOffset(char pos, char neg) const;
-
- /**
* Returns the sprite direction of this being.
*/
SpriteDirection
@@ -371,6 +365,11 @@ class Being : public Sprite
Sint32 mPx, mPy; /**< Pixel coordinates */
std::vector<AnimatedSprite*> mSprites;
+
+ private:
+ Sint16 mStepX, mStepY;
+ Uint16 mStepTime;
+ int getOffset(int) const;
};
#endif
diff --git a/src/engine.cpp b/src/engine.cpp
index f3aff6ce..eda154f3 100644
--- a/src/engine.cpp
+++ b/src/engine.cpp
@@ -176,8 +176,8 @@ void Engine::draw(Graphics *graphics)
}
}
- camera_x = map_x / 32;
- camera_y = map_y / 32;
+ camera_x = map_x;
+ camera_y = map_y;
// Draw tiles and sprites
if (mCurrentMap != NULL)
@@ -202,11 +202,11 @@ void Engine::draw(Graphics *graphics)
int mouseX, mouseY;
SDL_GetMouseState(&mouseX, &mouseY);
- int mouseTileX = mouseX / 32 + camera_x;
- int mouseTileY = mouseY / 32 + camera_y;
+ int mouseTileX = (mouseX + map_x) / 32;
+ int mouseTileY = (mouseY + map_y) / 32;
Path debugPath = mCurrentMap->findPath(
- player_node->mX, player_node->mY,
+ player_node->mX / 32, player_node->mY / 32,
mouseTileX, mouseTileY);
graphics->setColor(gcn::Color(255, 0, 0));
diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp
index a3ec299b..5df26d63 100644
--- a/src/gui/gui.cpp
+++ b/src/gui/gui.cpp
@@ -245,8 +245,8 @@ Gui::mousePress(int mx, int my, int button)
if (current_npc)
return;
- int tilex = mx / 32 + camera_x;
- int tiley = my / 32 + camera_y;
+ int tilex = (mx + camera_x) / 32;
+ int tiley = (my + camera_y) / 32;
// Right click might open a popup
if (button == gcn::MouseInput::RIGHT)
@@ -313,7 +313,7 @@ Gui::mousePress(int mx, int my, int button)
Uint8 *keys = SDL_GetKeyState(NULL);
if (!(keys[SDLK_LSHIFT] || keys[SDLK_RSHIFT]))
{
- player_node->setDestination(tilex * 32 + 16, tiley * 32 + 16);
+ player_node->setDestination(mx + camera_x, my + camera_y);
player_node->stopAttack();
}
}
diff --git a/src/localplayer.cpp b/src/localplayer.cpp
index 368bc8e3..9df3ac3f 100644
--- a/src/localplayer.cpp
+++ b/src/localplayer.cpp
@@ -161,30 +161,30 @@ void LocalPlayer::walk(unsigned char dir)
return;
}
- Sint16 dx = 0, dy = 0;
+ int dx = 0, dy = 0;
if (dir & UP)
- dy--;
+ dy -= 32;
if (dir & DOWN)
- dy++;
+ dy += 32;
if (dir & LEFT)
- dx--;
+ dx -= 32;
if (dir & RIGHT)
- dx++;
+ dx += 32;
// Prevent skipping corners over colliding tiles
- if (dx && mMap->tileCollides(mX / 32 + dx, mY / 32))
- dx = 0;
- if (dy && mMap->tileCollides(mX / 32, mY / 32 + dy))
- dy = 0;
+ if (dx && mMap->tileCollides((mX + dx) / 32, mY / 32))
+ dx = 16 - mX % 32;
+ if (dy && mMap->tileCollides(mX / 32, (mY + dy) / 32))
+ dy = 16 - mY % 32;
// Choose a straight direction when diagonal target is blocked
- if (dx && dy && !mMap->getWalk(mX / 32 + dx, mY / 32 + dy))
- dx = 0;
+ if (dx && dy && !mMap->getWalk((mX + dx) / 32, (mY + dy) / 32))
+ dx = 16 - mX % 32;
// Walk to where the player can actually go
- if ((dx || dy) && mMap->getWalk(mX / 32 + dx, mY / 32 + dy))
+ if ((dx || dy) && mMap->getWalk((mX + dx) / 32, (mY + dy) / 32))
{
- setDestination(mX + dx * 32, mY + dy * 32);
+ setDestination(mX + dx, mY + dy);
}
else if (dir)
{
@@ -198,6 +198,14 @@ void LocalPlayer::walk(unsigned char dir)
void LocalPlayer::setDestination(Uint16 x, Uint16 y)
{
+ // Fix coordinates so that the player does not seem to dig into walls.
+ int tx = x / 32, ty = y / 32, fx = x % 32, fy = y % 32;
+ if (fx != 16 && !mMap->getWalk(tx + fx / 16 * 2 - 1, ty)) fx = 16;
+ if (fy != 16 && !mMap->getWalk(tx, ty + fy / 16 * 2 - 1)) fy = 16;
+ if (fx != 16 && fy != 16 && !mMap->getWalk(tx + fx / 16 * 2 - 1, ty + fy / 16 * 2 - 1)) fx = 16;
+ x = tx * 32 + fx;
+ y = ty * 32 + fy;
+
MessageOut msg(PGMSG_WALK);
msg.writeShort(x);
msg.writeShort(y);