creatures walk and outift fixes

This commit is contained in:
Henrique Santiago 2011-12-28 09:00:09 -02:00
parent df0f2febe6
commit 5faa903e18
5 changed files with 108 additions and 126 deletions

View File

@ -26,6 +26,7 @@
#include "util/types.h" #include "util/types.h"
#define DEG_TO_RAD (acos(-1)/180.0) #define DEG_TO_RAD (acos(-1)/180.0)
#define RAD_TO_DEC (180.0/acos(-1))
namespace Fw namespace Fw
{ {

View File

@ -90,38 +90,24 @@ void Creature::draw(const Point& p)
outfitProgram->setUniformValue(LEGS_COLOR_UNIFORM, m_outfit.getLegsColor()); outfitProgram->setUniformValue(LEGS_COLOR_UNIFORM, m_outfit.getLegsColor());
outfitProgram->setUniformValue(FEET_COLOR_UNIFORM, m_outfit.getFeetColor()); outfitProgram->setUniformValue(FEET_COLOR_UNIFORM, m_outfit.getFeetColor());
for(int yi = 0; yi < m_type->dimensions[ThingType::Height]; yi++) { for(int h = 0; h < m_type->dimensions[ThingType::Height]; h++) {
for(int xi = 0; xi < m_type->dimensions[ThingType::Width]; xi++) { for(int w = 0; w < m_type->dimensions[ThingType::Width]; w++) {
int sprIndex = ((((((m_animation % m_type->dimensions[ThingType::AnimationPhases])
* m_type->dimensions[ThingType::PatternZ] + m_zPattern)
* m_type->dimensions[ThingType::PatternY] + m_yPattern)
* m_type->dimensions[ThingType::PatternX] + m_xPattern)
* m_type->dimensions[ThingType::Layers] + 0)
* m_type->dimensions[ThingType::Height] + yi)
* m_type->dimensions[ThingType::Width] + xi;
if(m_type->dimensions[ThingType::Layers] > 1) { if(m_type->dimensions[ThingType::Layers] > 1) {
int maskIndex = ((((((m_animation % m_type->dimensions[ThingType::AnimationPhases]) int maskId = m_type->getSpriteId(w, h, 1, m_xPattern, m_yPattern, m_zPattern, m_animation);
* m_type->dimensions[ThingType::PatternZ] + m_zPattern) if(!maskId)
* m_type->dimensions[ThingType::PatternY] + m_yPattern)
* m_type->dimensions[ThingType::PatternX] + m_xPattern)
* m_type->dimensions[ThingType::Layers] + 1)
* m_type->dimensions[ThingType::Height] + yi)
* m_type->dimensions[ThingType::Width] + xi;
int spriteId = m_type->sprites[maskIndex];
if(!spriteId)
continue; continue;
TexturePtr maskTex = g_sprites.getSpriteTexture(spriteId); TexturePtr maskTex = g_sprites.getSpriteTexture(maskId);
outfitProgram->setUniformTexture(MASK_TEXTURE_UNIFORM, maskTex, 1); outfitProgram->setUniformTexture(MASK_TEXTURE_UNIFORM, maskTex, 1);
} }
int spriteId = m_type->sprites[sprIndex]; int spriteId = m_type->getSpriteId(w, h, 0, m_xPattern, m_yPattern, m_zPattern, m_animation);
if(!spriteId) if(!spriteId)
continue; continue;
TexturePtr spriteTex = g_sprites.getSpriteTexture(spriteId); TexturePtr spriteTex = g_sprites.getSpriteTexture(spriteId);
Rect drawRect(((p + m_walkOffset).x - xi*32) - m_type->parameters[ThingType::DisplacementX], Rect drawRect(((p + m_walkOffset).x - w*32) - m_type->parameters[ThingType::DisplacementX],
((p + m_walkOffset).y - yi*32) - m_type->parameters[ThingType::DisplacementY], ((p + m_walkOffset).y - h*32) - m_type->parameters[ThingType::DisplacementY],
32, 32); 32, 32);
g_painter.drawTexturedRect(drawRect, spriteTex); g_painter.drawTexturedRect(drawRect, spriteTex);
} }
@ -162,90 +148,70 @@ void Creature::drawInformation(int x, int y, bool useGray, const Rect& rect)
g_painter.setColor(fillColor); g_painter.setColor(fillColor);
g_painter.drawFilledRect(healthRect); g_painter.drawFilledRect(healthRect);
if(m_informationFont)
m_informationFont->renderText(m_name, textRect, Fw::AlignTopCenter, fillColor); m_informationFont->renderText(m_name, textRect, Fw::AlignTopCenter, fillColor);
} }
void Creature::walk(const Position& position, bool inverse) void Creature::walk(const Position& position, bool inverse)
{ {
// set walking state // We're walking
bool sameWalk = m_walking && !m_inverseWalking && inverse;
m_walking = true;
m_inverseWalking = inverse;
int walkTimeFactor = 1;
// set new direction
if(m_position.isInRange(position, 1, 1, 0)) { if(m_position.isInRange(position, 1, 1, 0)) {
Otc::Direction direction = m_position.getDirectionFromPosition(position); Otc::Direction direction = m_position.getDirectionFromPosition(position);
setDirection(direction); setDirection(direction);
if(direction == Otc::NorthWest) { if(inverse) {
m_walkOffset.x = 32; Position positionDelta = m_position - position;
m_walkOffset.y = 32; m_walkOffset = Point(positionDelta.x * 32, positionDelta.y * 32);
walkTimeFactor = 2;
}
else if(direction == Otc::North) {
m_walkOffset.y = 32;
}
else if(direction == Otc::NorthEast) {
m_walkOffset.x = -32;
m_walkOffset.y = 32;
walkTimeFactor = 2;
}
else if(direction == Otc::East) {
m_walkOffset.x = -32;
}
else if(direction == Otc::SouthEast) {
m_walkOffset.x = -32;
m_walkOffset.y = -32;
walkTimeFactor = 2;
}
else if(direction == Otc::South) {
m_walkOffset.y = -32;
}
else if(direction == Otc::SouthWest) {
m_walkOffset.x = 32;
m_walkOffset.y = -32;
walkTimeFactor = 2;
}
else if(direction == Otc::West) {
m_walkOffset.x = 32;
}
}
else { // Teleport
// we teleported, dont walk or change direction
m_walking = false;
m_walkOffset.x = 0;
m_walkOffset.y = 0;
m_animation = 0;
} }
else
m_walkOffset = Point(0, 0);
if(!m_inverseWalking) { // Diagonal walking lasts 3 times more.
m_walkOffset.x = 0; int walkTimeFactor = 1;
m_walkOffset.y = 0; if(direction == Otc::NorthWest || direction == Otc::NorthEast || direction == Otc::SouthWest || direction == Otc::SouthEast)
} walkTimeFactor = 3;
if(m_walking) { // Get walking speed
// get walk speed
int groundSpeed = 100; int groundSpeed = 100;
if(ItemPtr ground = g_map.getTile(position)->getGround())
ItemPtr ground = g_map.getTile(position)->getGround();
if(ground)
groundSpeed = ground->getType()->parameters[ThingType::GroundSpeed]; groundSpeed = ground->getType()->parameters[ThingType::GroundSpeed];
float walkTime = walkTimeFactor * 1000.0 * (float)groundSpeed / m_speed; float walkTime = 1000.0 * (float)groundSpeed / m_speed;
walkTime = (walkTime == 0) ? 1000 : walkTime; walkTime = (walkTime == 0) ? 1000 : walkTime;
bool sameWalk = m_walking && !m_inverseWalking && inverse;
m_inverseWalking = inverse;
m_walking = true;
m_walkTimePerPixel = walkTime / 32.0; m_walkTimePerPixel = walkTime / 32.0;
if(!sameWalk) m_walkStart = sameWalk ? m_walkStart : g_clock.ticks();
m_walkStartTicks = g_clock.ticks(); m_walkEnd = m_walkStart + walkTime * walkTimeFactor;
m_turnDirection = m_direction;
updateWalk(); updateWalk();
} }
// Teleport
else {
m_walking = false;
m_walkOffset = Point(0, 0);
m_animation = 0;
}
}
void Creature::turn(Otc::Direction direction)
{
if(!m_walking)
setDirection(direction);
else
m_turnDirection = direction;
} }
void Creature::updateWalk() void Creature::updateWalk()
{ {
if(m_walking) { if(!m_walking)
int elapsedTicks = g_clock.ticksElapsed(m_walkStartTicks); return;
int elapsedTicks = g_clock.ticksElapsed(m_walkStart);
int totalPixelsWalked = std::min((int)round(elapsedTicks / m_walkTimePerPixel), 32); int totalPixelsWalked = std::min((int)round(elapsedTicks / m_walkTimePerPixel), 32);
if(m_inverseWalking) { if(m_inverseWalking) {
@ -271,19 +237,16 @@ void Creature::updateWalk()
m_walkOffset.x = -totalPixelsWalked; m_walkOffset.x = -totalPixelsWalked;
} }
int totalWalkTileTicks = (int)m_walkTimePerPixel*32 * 0.5; if(totalPixelsWalked == 32 || m_type->dimensions[ThingType::AnimationPhases] == 0)
if(m_type->dimensions[ThingType::AnimationPhases] > 0)
m_animation = (g_clock.ticks() % totalWalkTileTicks) / (totalWalkTileTicks / (m_type->dimensions[ThingType::AnimationPhases] - 1)) + 1;
else
m_animation = 0; m_animation = 0;
else if(m_type->dimensions[ThingType::AnimationPhases] > 0)
m_animation = 1 + totalPixelsWalked * 4 / Map::NUM_TILE_PIXELS % (m_type->dimensions[ThingType::AnimationPhases] - 1);
if(g_clock.ticks() > m_walkEnd)
if(totalPixelsWalked == 32) cancelWalk(m_turnDirection);
cancelWalk(m_direction);
else else
g_dispatcher.scheduleEvent(std::bind(&Creature::updateWalk, asCreature()), m_walkTimePerPixel); g_dispatcher.scheduleEvent(std::bind(&Creature::updateWalk, asCreature()), m_walkTimePerPixel);
} }
}
void Creature::cancelWalk(Otc::Direction direction) void Creature::cancelWalk(Otc::Direction direction)
{ {
@ -296,14 +259,14 @@ void Creature::cancelWalk(Otc::Direction direction)
} }
m_walking = false; m_walking = false;
m_walkStartTicks = 0; m_walkStart = 0;
m_walkOffset.x = 0; m_walkOffset = Point(0, 0);
m_walkOffset.y = 0; setDirection(direction);
m_direction = direction;
} }
void Creature::setName(const std::string& name) void Creature::setName(const std::string& name)
{ {
if(m_informationFont)
m_nameSize = m_informationFont->calculateTextRectSize(name); m_nameSize = m_informationFont->calculateTextRectSize(name);
m_name = name; m_name = name;
} }
@ -355,6 +318,14 @@ void Creature::setOutfit(const Outfit& outfit)
{ {
m_outfit = outfit; m_outfit = outfit;
m_type = getType(); m_type = getType();
// Do not apply any mask color.
if(m_type->dimensions[ThingType::Layers] == 1) {
m_outfit.setHead(0);
m_outfit.setBody(0);
m_outfit.setLegs(0);
m_outfit.setFeet(0);
}
} }
ThingType *Creature::getType() ThingType *Creature::getType()

View File

@ -61,6 +61,7 @@ public:
ThingType *getType(); ThingType *getType();
virtual void walk(const Position& position, bool inverse = true); virtual void walk(const Position& position, bool inverse = true);
void turn(Otc::Direction direction);
virtual void cancelWalk(Otc::Direction direction); virtual void cancelWalk(Otc::Direction direction);
Point getWalkOffset() { return m_walkOffset; } Point getWalkOffset() { return m_walkOffset; }
@ -88,10 +89,11 @@ protected:
FontPtr m_informationFont; FontPtr m_informationFont;
Color m_informationColor; Color m_informationColor;
ticks_t m_walkStartTicks; ticks_t m_walkStart, m_walkEnd;
bool m_walking, m_inverseWalking; bool m_walking, m_inverseWalking;
float m_walkTimePerPixel; float m_walkTimePerPixel;
Point m_walkOffset; Point m_walkOffset;
Otc::Direction m_turnDirection;
}; };
#endif #endif

View File

@ -408,9 +408,17 @@ void ProtocolGame::parseCreatureMove(InputMessage& msg)
Position newPos = parsePosition(msg); Position newPos = parsePosition(msg);
ThingPtr thing = g_map.getTile(oldPos)->getThing(oldStackpos); ThingPtr thing = g_map.getTile(oldPos)->getThing(oldStackpos);
assert(thing); if(!thing) {
logError("could not get thing");
return;
}
CreaturePtr creature = thing->asCreature(); CreaturePtr creature = thing->asCreature();
assert(creature); if(!creature) {
logError("thing is not a creature");
return;
}
creature->walk(newPos); creature->walk(newPos);
// update map tiles // update map tiles
@ -642,7 +650,7 @@ void ProtocolGame::parseCreatureTurn(InputMessage& msg)
CreaturePtr creature = g_map.getCreatureById(id); CreaturePtr creature = g_map.getCreatureById(id);
if(creature) if(creature)
creature->setDirection(direction); creature->turn(direction);
} }
void ProtocolGame::parseItemTextWindow(InputMessage& msg) void ProtocolGame::parseItemTextWindow(InputMessage& msg)

View File

@ -74,7 +74,7 @@ public:
return Otc::East; return Otc::East;
} }
else { else {
float angle = std::atan2(positionDelta.y * -1, positionDelta.x) * DEG_TO_RAD; float angle = std::atan2(positionDelta.y * -1, positionDelta.x) * RAD_TO_DEC;
if(angle < 0) if(angle < 0)
angle += 360; angle += 360;