walk improvements, but not great yet

This commit is contained in:
Henrique 2011-11-05 18:34:49 -02:00
parent 650713a1e6
commit fbda996b76
8 changed files with 119 additions and 35 deletions

View File

@ -94,29 +94,44 @@ void Creature::draw(int x, int y)
int pixelsWalked = std::floor((g_platform.getTicks() - m_lastTicks) / m_walkTimePerPixel);
int remainingTime = (g_platform.getTicks() - m_lastTicks) % (int)m_walkTimePerPixel;
if(m_direction == Otc::North || m_direction == Otc::NorthEast || m_direction == Otc::NorthWest)
m_walkOffsetY = std::max(m_walkOffsetY - pixelsWalked, 0);
else if(m_direction == Otc::South || m_direction == Otc::SouthEast || m_direction == Otc::SouthWest)
m_walkOffsetY = std::min(m_walkOffsetY + pixelsWalked, 0);
if(m_inverseWalking) {
if(m_direction == Otc::North || m_direction == Otc::NorthEast || m_direction == Otc::NorthWest)
m_walkOffsetY = std::max(m_walkOffsetY - pixelsWalked, 0);
else if(m_direction == Otc::South || m_direction == Otc::SouthEast || m_direction == Otc::SouthWest)
m_walkOffsetY = std::min(m_walkOffsetY + pixelsWalked, 0);
if(m_direction == Otc::East || m_direction == Otc::NorthEast || m_direction == Otc::SouthEast)
m_walkOffsetX = std::min(m_walkOffsetX + pixelsWalked, 0);
else if(m_direction == Otc::West || m_direction == Otc::NorthWest || m_direction == Otc::SouthWest)
m_walkOffsetX = std::max(m_walkOffsetX - pixelsWalked, 0);
if(m_direction == Otc::East || m_direction == Otc::NorthEast || m_direction == Otc::SouthEast)
m_walkOffsetX = std::min(m_walkOffsetX + pixelsWalked, 0);
else if(m_direction == Otc::West || m_direction == Otc::NorthWest || m_direction == Otc::SouthWest)
m_walkOffsetX = std::max(m_walkOffsetX - pixelsWalked, 0);
int walkOffset = std::max(std::abs(m_walkOffsetX), std::abs(m_walkOffsetY));
if(m_walkOffsetX == 0 && m_walkOffsetY == 0)
cancelWalk(m_direction);
}
else {
if(m_direction == Otc::North || m_direction == Otc::NorthEast || m_direction == Otc::NorthWest)
m_walkOffsetY = std::max(m_walkOffsetY - pixelsWalked, -32);
else if(m_direction == Otc::South || m_direction == Otc::SouthEast || m_direction == Otc::SouthWest)
m_walkOffsetY = std::min(m_walkOffsetY + pixelsWalked, 32);
if(m_direction == Otc::East || m_direction == Otc::NorthEast || m_direction == Otc::SouthEast)
m_walkOffsetX = std::min(m_walkOffsetX + pixelsWalked, 32);
else if(m_direction == Otc::West || m_direction == Otc::NorthWest || m_direction == Otc::SouthWest)
m_walkOffsetX = std::max(m_walkOffsetX - pixelsWalked, -32);
if(std::abs(m_walkOffsetX) == 32 && std::abs(m_walkOffsetY) == 32)
m_animation = 0;
}
int walkOffset = std::max(std::abs(m_walkOffsetX), std::abs(m_walkOffsetY)) + 32;
if(walkOffset % (int)std::ceil(32 / (float)type.animationPhases) == 0) {
if((m_lastWalkAnim+1) % type.animationPhases == 0)
m_lastWalkAnim = 1;
else
m_lastWalkAnim++;
}
m_animation = m_lastWalkAnim;
if(((m_walkOffsetX == 0 && m_walkOffsetY == 0) && m_walkOffsetX != m_walkOffsetY) ||
((m_walkOffsetX == 0 || m_walkOffsetY == 0) && m_walkOffsetX == m_walkOffsetY)) {
cancelWalk(m_direction);
}
if(m_walking)
m_animation = m_lastWalkAnim;
m_lastTicks = g_platform.getTicks() - remainingTime;
}
@ -172,12 +187,11 @@ void Creature::drawInformation(int x, int y, bool useGray, const Rect& rect)
m_informationFont->renderText(m_name, textRect, Fw::AlignTopCenter, fillColor);
}
void Creature::walk(const Position& position)
void Creature::walk(const Position& position, bool inverse)
{
// set walking state
m_walking = true;
m_walkOffsetX = 0;
m_walkOffsetY = 0;
m_inverseWalking = inverse;
int walkTimeFactor = 1;
// set new direction
@ -226,9 +240,10 @@ void Creature::walk(const Position& position)
m_walking = false;
}
// update map tiles
g_map.removeThing(asThing());
g_map.addThing(asThing(), position);
if(!m_inverseWalking) {
m_walkOffsetX = 0;
m_walkOffsetY = 0;
}
if(m_walking) {
// Calculate xPattern

View File

@ -70,8 +70,8 @@ public:
void onHealthPercentChange(int);
void walk(const Position& position);
void cancelWalk(Otc::Direction direction);
virtual void walk(const Position& position, bool inverse = true);
virtual void cancelWalk(Otc::Direction direction);
int getWalkOffsetX() { return m_walkOffsetX; }
int getWalkOffsetY() { return m_walkOffsetY; }
@ -79,7 +79,7 @@ public:
CreaturePtr asCreature() { return std::static_pointer_cast<Creature>(shared_from_this()); }
private:
protected:
std::string m_name;
uint8 m_healthPercent;
Otc::Direction m_direction;
@ -95,7 +95,7 @@ private:
Color m_informationColor;
int m_lastTicks;
bool m_walking;
bool m_walking, m_inverseWalking;
float m_walkTimePerPixel;
Position m_walkingFromPosition;
int m_lastWalkAnim;

View File

@ -104,12 +104,10 @@ void Game::processTextMessage(int type, const std::string& message)
void Game::walk(Otc::Direction direction)
{
if(!m_online)
if(!m_online || !m_localPlayer->canWalk(direction))
return;
// TODO: check if we can walk.
m_localPlayer->walk(direction);
m_localPlayer->clientWalk(direction);
switch(direction) {
case Otc::North:

View File

@ -21,10 +21,59 @@
*/
#include "localplayer.h"
#include "map.h"
#include "game.h"
#include "tile.h"
void LocalPlayer::walk(Otc::Direction direction)
LocalPlayer::LocalPlayer()
{
//Position newPos = m_position + Position::getPositionFromDirection(direction);
//asCreature()->walk(newPos);
m_clientWalking = false;
}
void LocalPlayer::clientWalk(Otc::Direction direction)
{
if(!m_walking) {
Position newPos = m_position + Position::getPositionFromDirection(direction);
Creature::walk(newPos, false);
m_clientWalking = true;
}
}
void LocalPlayer::walk(const Position& position, bool inverse)
{
if(m_clientWalking) {
Position pos = Position::getPositionFromDirection(m_direction);
int walkOffsetX = m_walkOffsetX - pos.x * 32;
int walkOffsetY = m_walkOffsetY - pos.y * 32;
Creature::walk(position, inverse);
m_walkOffsetX = walkOffsetX;
m_walkOffsetY = walkOffsetY;
m_clientWalking = false;
}
else {
m_walkOffsetX = 0;
m_walkOffsetY = 0;
Creature::walk(position, inverse);
}
}
void LocalPlayer::cancelWalk(Otc::Direction direction)
{
m_clientWalking = false;
Creature::cancelWalk(direction);
}
bool LocalPlayer::canWalk(Otc::Direction direction)
{
Position newPos = m_position + Position::getPositionFromDirection(direction);
TilePtr tile = g_map.getTile(newPos);
if(!tile->isWalkable()) {
// TODO: create enum for 17, white message on screen bottom and console.
g_game.processTextMessage(17, "Sorry, not possible.");
return false;
}
return !m_clientWalking;
}

View File

@ -28,7 +28,7 @@
class LocalPlayer : public Player
{
public:
LocalPlayer() { }
LocalPlayer();
void setDrawSpeed(uint16 drawSpeed) { m_drawSpeed = drawSpeed; }
uint16 getDrawSpeed() { return m_drawSpeed; }
@ -42,13 +42,17 @@ public:
void setStatistic(Otc::Statistic statistic, double value) { m_statistics[statistic] = value; }
double getStatistic(Otc::Statistic statistic) { return m_statistics[statistic]; }
void walk(Otc::Direction direction);
void clientWalk(Otc::Direction direction);
void walk(const Position& position, bool inverse);
void cancelWalk(Otc::Direction direction);
bool canWalk(Otc::Direction direction);
LocalPlayerPtr asLocalPlayer() { return std::static_pointer_cast<LocalPlayer>(shared_from_this()); }
private:
uint16 m_drawSpeed;
bool m_canReportBugs;
bool m_clientWalking;
int m_skills[Otc::LastSkill][Otc::LastSkillType];
double m_statistics[Otc::LastStatistic];

View File

@ -183,6 +183,19 @@ ItemPtr Tile::getGround()
return nullptr;
}
bool Tile::isWalkable()
{
if(!getGround())
return false;
for(const ThingPtr& thing : m_things) {
const ThingType& type = thing->getType();
if(type.isNotWalkable)
return false;
}
return true;
}
bool Tile::isFullGround()
{
ThingPtr ground = getThing(0);

View File

@ -48,6 +48,7 @@ public:
int getDrawElevation() { return m_drawElevation; }
std::vector<CreaturePtr> getCreatures();
ItemPtr getGround();
bool isWalkable();
bool isFullGround();
bool isFullyOpaque();
bool isLookPossible();

View File

@ -406,6 +406,10 @@ void ProtocolGame::parseCreatureMove(InputMessage& msg)
CreaturePtr creature = thing->asCreature();
assert(creature);
creature->walk(newPos);
// update map tiles
g_map.removeThing(thing);
g_map.addThing(thing, newPos);
}
void ProtocolGame::parseOpenContainer(InputMessage& msg)