render walking creatures in the correct way

master
Eduardo Bart 12 years ago
parent cf18b0c36f
commit 7b965a27af

@ -69,12 +69,12 @@ void Creature::draw(const Point& dest, float scaleFactor)
if(m_showVolatileSquare) { if(m_showVolatileSquare) {
g_painter.setColor(m_volatileSquareColor); g_painter.setColor(m_volatileSquareColor);
g_painter.drawBoundingRect(Rect(dest + (m_walkOffset - getDisplacement() + 3)*scaleFactor, Size(28*scaleFactor, 28*scaleFactor)), 2*scaleFactor); g_painter.drawBoundingRect(Rect(dest + (m_walkOffset - getDisplacement() + 3)*scaleFactor, Size(28*scaleFactor, 28*scaleFactor)), std::max((int)(2*scaleFactor), 1));
} }
if(m_showStaticSquare) { if(m_showStaticSquare) {
g_painter.setColor(m_staticSquareColor); g_painter.setColor(m_staticSquareColor);
g_painter.drawBoundingRect(Rect(dest + (m_walkOffset - getDisplacement() + 1)*scaleFactor, Size(scaledTileSize, scaledTileSize)), 2*scaleFactor); g_painter.drawBoundingRect(Rect(dest + (m_walkOffset - getDisplacement() + 1)*scaleFactor, Size(scaledTileSize, scaledTileSize)), std::max((int)(2*scaleFactor), 1));
} }
g_painter.setColor(Fw::white); g_painter.setColor(Fw::white);
@ -134,10 +134,10 @@ void Creature::draw(const Point& dest, float scaleFactor)
} }
else if(m_outfit.getCategory() == ThingsType::Item) { else if(m_outfit.getCategory() == ThingsType::Item) {
for(int l = 0; l < getLayers(); l++) for(int l = 0; l < getLayers(); l++)
internalDraw(dest + m_walkOffset * scaleFactor, scaleFactor, l); internalDraw(dest + m_walkOffset, scaleFactor, l);
} }
else if(m_outfit.getCategory() == ThingsType::Effect) else if(m_outfit.getCategory() == ThingsType::Effect)
internalDraw(dest + m_walkOffset * scaleFactor, scaleFactor, 0); internalDraw(dest + m_walkOffset, scaleFactor, 0);
} }
void Creature::drawInformation(const Point& point, bool useGray, const Rect& parentRect) void Creature::drawInformation(const Point& point, bool useGray, const Rect& parentRect)
@ -276,6 +276,36 @@ void Creature::updateWalkOffset(int totalPixelsWalked)
m_walkOffset.x = 32 - totalPixelsWalked; m_walkOffset.x = 32 - totalPixelsWalked;
} }
void Creature::updateWalkingTile()
{
// determine new walking tile
TilePtr newWalkingTile;
Rect virtualCreatureRect(Otc::TILE_PIXELS + (m_walkOffset.x - getDisplacementX()),
Otc::TILE_PIXELS + (m_walkOffset.y - getDisplacementY()),
Otc::TILE_PIXELS, Otc::TILE_PIXELS);
for(int xi = -1; xi <= 1 && !newWalkingTile; ++xi) {
for(int yi = -1; yi <= 1 && !newWalkingTile; ++yi) {
Rect virtualTileRect((xi+1)*Otc::TILE_PIXELS, (yi+1)*Otc::TILE_PIXELS, Otc::TILE_PIXELS, Otc::TILE_PIXELS);
// only render creatures where bottom right is inside tile rect
if(virtualTileRect.contains(virtualCreatureRect.bottomRight())) {
const TilePtr& tile = g_map.getTile(m_position.translated(xi, yi, 0));
if(!tile)
continue;
newWalkingTile = tile;
}
}
}
if(newWalkingTile != m_walkingTile) {
if(m_walkingTile)
m_walkingTile->removeWalkingCreature(asCreature());
if(newWalkingTile)
newWalkingTile->addWalkingCreature(asCreature());
m_walkingTile = newWalkingTile;
}
}
void Creature::nextWalkUpdate() void Creature::nextWalkUpdate()
{ {
// remove any previous scheduled walk updates // remove any previous scheduled walk updates
@ -303,6 +333,7 @@ void Creature::updateWalk()
// update walk animation and offsets // update walk animation and offsets
updateWalkAnimation(totalPixelsWalked); updateWalkAnimation(totalPixelsWalked);
updateWalkOffset(totalPixelsWalked); updateWalkOffset(totalPixelsWalked);
updateWalkingTile();
// terminate walk // terminate walk
if(m_walking && m_walkTimer.ticksElapsed() >= m_walkInterval) if(m_walking && m_walkTimer.ticksElapsed() >= m_walkInterval)
@ -323,6 +354,11 @@ void Creature::terminateWalk()
m_walkTurnDirection = Otc::InvalidDirection; m_walkTurnDirection = Otc::InvalidDirection;
} }
if(m_walkingTile) {
m_walkingTile->removeWalkingCreature(asCreature());
m_walkingTile = nullptr;
}
m_walking = false; m_walking = false;
} }

@ -78,8 +78,6 @@ public:
void updateInvisibleAnimation(); void updateInvisibleAnimation();
void updateShield(); void updateShield();
ThingType *getType();
// walk related // walk related
void turn(Otc::Direction direction); void turn(Otc::Direction direction);
virtual void walk(const Position& oldPos, const Position& newPos); virtual void walk(const Position& oldPos, const Position& newPos);
@ -93,6 +91,7 @@ public:
protected: protected:
virtual void updateWalkAnimation(int totalPixelsWalked); virtual void updateWalkAnimation(int totalPixelsWalked);
virtual void updateWalkOffset(int totalPixelsWalked); virtual void updateWalkOffset(int totalPixelsWalked);
void updateWalkingTile();
virtual void nextWalkUpdate(); virtual void nextWalkUpdate();
virtual void updateWalk(); virtual void updateWalk();
virtual void terminateWalk(); virtual void terminateWalk();
@ -116,6 +115,7 @@ protected:
// walk related // walk related
Timer m_walkTimer; Timer m_walkTimer;
TilePtr m_walkingTile;
int m_walkInterval; int m_walkInterval;
int m_walkAnimationInterval; int m_walkAnimationInterval;
bool m_walking; bool m_walking;

@ -145,6 +145,7 @@ void LocalPlayer::updateWalk()
// update walk animation and offsets // update walk animation and offsets
updateWalkAnimation(totalPixelsWalked); updateWalkAnimation(totalPixelsWalked);
updateWalkOffset(totalPixelsWalked); updateWalkOffset(totalPixelsWalked);
updateWalkingTile();
// terminate walk only when client and server side walk are complated // terminate walk only when client and server side walk are complated
if(m_walking && !m_preWalking && m_walkTimer.ticksElapsed() >= m_walkInterval) if(m_walking && !m_preWalking && m_walkTimer.ticksElapsed() >= m_walkInterval)

@ -304,7 +304,7 @@ std::vector<CreaturePtr> Map::getSpectatorsInRangeEx(const Position& centerPos,
continue; continue;
auto tileCreatures = tile->getCreatures(); auto tileCreatures = tile->getCreatures();
creatures.insert(creatures.end(), tileCreatures.begin(), tileCreatures.end()); creatures.insert(creatures.end(), tileCreatures.rbegin(), tileCreatures.rend());
} }
} }
} }
@ -376,7 +376,7 @@ bool Map::isAwareOfPosition(const Position& pos)
int Map::getFirstAwareFloor() int Map::getFirstAwareFloor()
{ {
if(m_centralPosition.z > Otc::SEA_FLOOR) if(m_centralPosition.z > Otc::SEA_FLOOR)
return m_centralPosition.z-2; return m_centralPosition.z-Otc::AWARE_UNDEGROUND_FLOOR_RANGE;
else else
return 0; return 0;
} }
@ -384,7 +384,7 @@ int Map::getFirstAwareFloor()
int Map::getLastAwareFloor() int Map::getLastAwareFloor()
{ {
if(m_centralPosition.z > Otc::SEA_FLOOR) if(m_centralPosition.z > Otc::SEA_FLOOR)
return std::min(m_centralPosition.z+2, (int)Otc::MAX_Z); return std::min(m_centralPosition.z+Otc::AWARE_UNDEGROUND_FLOOR_RANGE, (int)Otc::MAX_Z);
else else
return Otc::SEA_FLOOR; return Otc::SEA_FLOOR;
} }

@ -45,7 +45,6 @@ MapView::MapView()
m_shaderProgram->addShaderFromSourceCode(Shader::Vertex, glslMainWithTexCoordsVertexShader + glslPositionOnlyVertexShader); m_shaderProgram->addShaderFromSourceCode(Shader::Vertex, glslMainWithTexCoordsVertexShader + glslPositionOnlyVertexShader);
m_shaderProgram->addShaderFromSourceFile(Shader::Fragment, "/game_shaders/map.frag"); m_shaderProgram->addShaderFromSourceFile(Shader::Fragment, "/game_shaders/map.frag");
assert(m_shaderProgram->link()); assert(m_shaderProgram->link());
//m_animated = false;
} }
void MapView::draw(const Rect& rect) void MapView::draw(const Rect& rect)
@ -60,7 +59,7 @@ void MapView::draw(const Rect& rect)
if(isNearView()) if(isNearView())
tileDrawFlags = Otc::DrawGround | Otc::DrawWalls | Otc::DrawCommonItems | Otc::DrawCreatures | Otc::DrawEffects; tileDrawFlags = Otc::DrawGround | Otc::DrawWalls | Otc::DrawCommonItems | Otc::DrawCreatures | Otc::DrawEffects;
else if(isMidView()) else if(isMidView())
tileDrawFlags = Otc::DrawGround | Otc::DrawWalls | Otc::DrawCommonItems; tileDrawFlags = Otc::DrawGround | Otc::DrawWalls | Otc::DrawCommonItems | Otc::DrawCreatures;
else if(isFarView()) else if(isFarView())
tileDrawFlags = Otc::DrawGround | Otc::DrawWalls; tileDrawFlags = Otc::DrawGround | Otc::DrawWalls;
else // huge far view else // huge far view
@ -161,6 +160,10 @@ bool MapView::updateVisibleTilesCache()
int firstFloor = getFirstVisibleFloor(); int firstFloor = getFirstVisibleFloor();
int lastFloor = getLastVisibleFloor(); int lastFloor = getLastVisibleFloor();
if(lastFloor < firstFloor)
lastFloor = firstFloor;
m_cachedFirstVisibleFloor = firstFloor; m_cachedFirstVisibleFloor = firstFloor;
m_cachedLastVisibleFloor = lastFloor; m_cachedLastVisibleFloor = lastFloor;
Position cameraPosition = getCameraPosition(); Position cameraPosition = getCameraPosition();
@ -291,7 +294,7 @@ int MapView::getFirstVisibleFloor()
// limits to underground floors while under sea level // limits to underground floors while under sea level
if(cameraPosition.z > Otc::SEA_FLOOR) if(cameraPosition.z > Otc::SEA_FLOOR)
firstFloor = Otc::SEA_FLOOR+1; firstFloor = cameraPosition.z - Otc::AWARE_UNDEGROUND_FLOOR_RANGE;
// loop in 3x3 tiles around the camera // loop in 3x3 tiles around the camera
for(int ix = -1; ix <= 1 && firstFloor < cameraPosition.z; ++ix) { for(int ix = -1; ix <= 1 && firstFloor < cameraPosition.z; ++ix) {
@ -338,7 +341,7 @@ int MapView::getLastVisibleFloor()
// view only underground floors when below sea level // view only underground floors when below sea level
if(cameraPosition.z > Otc::SEA_FLOOR) if(cameraPosition.z > Otc::SEA_FLOOR)
return Otc::MAX_Z; return cameraPosition.z + Otc::AWARE_UNDEGROUND_FLOOR_RANGE;
else else
return Otc::SEA_FLOOR; return Otc::SEA_FLOOR;
} }

@ -31,9 +31,9 @@ class MapView : public LuaObject
{ {
enum { enum {
DEFAULT_FRAMBUFFER_SIZE = 2048, DEFAULT_FRAMBUFFER_SIZE = 2048,
NEAR_VIEW_AREA = 4096, NEAR_VIEW_AREA = 64*64,
MID_VIEW_AREA = 16384, MID_VIEW_AREA = 128*128,
FAR_VIEW_AREA = 32768 FAR_VIEW_AREA = 192*192
}; };
public: public:

@ -77,6 +77,8 @@ void Thing::internalDraw(const Point& dest, float scaleFactor, int layer)
Rect drawRect((dest.x - w*scaledSize) - getDisplacementX()*scaleFactor, Rect drawRect((dest.x - w*scaledSize) - getDisplacementX()*scaleFactor,
(dest.y - h*scaledSize) - getDisplacementY()*scaleFactor, (dest.y - h*scaledSize) - getDisplacementY()*scaleFactor,
scaledSize, scaledSize); scaledSize, scaledSize);
g_painter.setColor(Fw::white);
g_painter.drawTexturedRect(drawRect, spriteTex); g_painter.drawTexturedRect(drawRect, spriteTex);
} }
} }

@ -38,7 +38,7 @@ Tile::Tile(const Position& position)
void Tile::draw(const Point& dest, float scaleFactor, int drawFlags) void Tile::draw(const Point& dest, float scaleFactor, int drawFlags)
{ {
m_drawElevation = 0; int drawElevation = 0;
// first bottom items // first bottom items
if(drawFlags & Otc::DrawGround || drawFlags & Otc::DrawWalls) { if(drawFlags & Otc::DrawGround || drawFlags & Otc::DrawWalls) {
@ -47,11 +47,11 @@ void Tile::draw(const Point& dest, float scaleFactor, int drawFlags)
break; break;
if((drawFlags & Otc::DrawGround && thing->isGround()) || (drawFlags & Otc::DrawWalls)) if((drawFlags & Otc::DrawGround && thing->isGround()) || (drawFlags & Otc::DrawWalls))
thing->draw(dest - m_drawElevation*scaleFactor, scaleFactor); thing->draw(dest - drawElevation*scaleFactor, scaleFactor);
m_drawElevation += thing->getElevation(); drawElevation += thing->getElevation();
if(m_drawElevation > Otc::MAX_ELEVATION) if(drawElevation > Otc::MAX_ELEVATION)
m_drawElevation = Otc::MAX_ELEVATION; drawElevation = Otc::MAX_ELEVATION;
} }
} }
@ -59,37 +59,28 @@ void Tile::draw(const Point& dest, float scaleFactor, int drawFlags)
if(drawFlags & Otc::DrawCommonItems) { if(drawFlags & Otc::DrawCommonItems) {
for(auto it = m_things.rbegin(); it != m_things.rend(); ++it) { for(auto it = m_things.rbegin(); it != m_things.rend(); ++it) {
const ThingPtr& thing = *it; const ThingPtr& thing = *it;
if(thing->asCreature() || thing->isOnTop() || thing->isOnBottom() || thing->isGroundBorder() || thing->isGround()) if(thing->isOnTop() || thing->isOnBottom() || thing->isGroundBorder() || thing->isGround() || thing->asCreature())
break; break;
thing->draw(dest - m_drawElevation*scaleFactor, scaleFactor); thing->draw(dest - drawElevation*scaleFactor, scaleFactor);
m_drawElevation += thing->getElevation(); drawElevation += thing->getElevation();
if(m_drawElevation > Otc::MAX_ELEVATION) if(drawElevation > Otc::MAX_ELEVATION)
m_drawElevation = Otc::MAX_ELEVATION; drawElevation = Otc::MAX_ELEVATION;
} }
} }
// we can render creatures in 3x3 range // creatures
if(drawFlags & Otc::DrawCreatures) { if(drawFlags & Otc::DrawCreatures) {
for(int xi = -1; xi <= 1; ++xi) { for(const CreaturePtr& creature : m_walkingCreatures) {
for(int yi = -1; yi <= 1; ++yi) { creature->draw(Point(dest.x + ((creature->getPosition().x - m_position.x)*Otc::TILE_PIXELS - drawElevation)*scaleFactor,
const TilePtr& tile = g_map.getTile(m_position.translated(xi, yi, 0)); dest.y + ((creature->getPosition().y - m_position.y)*Otc::TILE_PIXELS - drawElevation)*scaleFactor), scaleFactor);
if(!tile)
continue; }
for(const CreaturePtr& creature : tile->getCreatures()) {
int tileSize = Otc::TILE_PIXELS * scaleFactor; for(auto it = m_things.rbegin(); it != m_things.rend(); ++it) {
Rect creatureRect(dest.x + xi*tileSize + (creature->getWalkOffset().x - creature->getDisplacementX())*scaleFactor, CreaturePtr creature = (*it)->asCreature();
dest.y + yi*tileSize + (creature->getWalkOffset().y - creature->getDisplacementY())*scaleFactor, if(creature && !creature->isWalking())
tileSize, tileSize); creature->draw(dest - drawElevation, scaleFactor);
Rect thisTileRect(dest.x, dest.y, tileSize, tileSize);
// only render creatures where bottom right is inside our rect
if(thisTileRect.contains(creatureRect.bottomRight())) {
creature->draw(Point(dest.x + xi*tileSize - m_drawElevation*scaleFactor,
dest.y + yi*tileSize - m_drawElevation*scaleFactor), scaleFactor);
}
}
}
} }
} }
@ -103,7 +94,7 @@ void Tile::draw(const Point& dest, float scaleFactor, int drawFlags)
if(drawFlags & Otc::DrawWalls) { if(drawFlags & Otc::DrawWalls) {
for(const ThingPtr& thing : m_things) { for(const ThingPtr& thing : m_things) {
if(thing->isOnTop()) if(thing->isOnTop())
thing->draw(dest - m_drawElevation, scaleFactor); thing->draw(dest - drawElevation, scaleFactor);
} }
} }
} }
@ -114,6 +105,18 @@ void Tile::clean()
m_effects.clear(); m_effects.clear();
} }
void Tile::addWalkingCreature(const CreaturePtr& creature)
{
m_walkingCreatures.push_back(creature);
}
void Tile::removeWalkingCreature(const CreaturePtr& creature)
{
auto it = std::find(m_walkingCreatures.begin(), m_walkingCreatures.end(), creature);
if(it != m_walkingCreatures.end())
m_walkingCreatures.erase(it);
}
ThingPtr Tile::addThing(const ThingPtr& thing, int stackPos) ThingPtr Tile::addThing(const ThingPtr& thing, int stackPos)
{ {
if(!thing) if(!thing)

@ -33,12 +33,12 @@ public:
void draw(const Point& dest, float scaleFactor, int drawFlags); void draw(const Point& dest, float scaleFactor, int drawFlags);
private:
void updateVisibleItemsCache();
public: public:
void clean(); void clean();
void addWalkingCreature(const CreaturePtr& creature);
void removeWalkingCreature(const CreaturePtr& creature);
ThingPtr addThing(const ThingPtr& thing, int stackPos = -1); ThingPtr addThing(const ThingPtr& thing, int stackPos = -1);
bool removeThing(const ThingPtr& thing); bool removeThing(const ThingPtr& thing);
ThingPtr getThing(int stackPos); ThingPtr getThing(int stackPos);
@ -70,6 +70,7 @@ public:
TilePtr asTile() { return std::static_pointer_cast<Tile>(shared_from_this()); } TilePtr asTile() { return std::static_pointer_cast<Tile>(shared_from_this()); }
private: private:
std::vector<CreaturePtr> m_walkingCreatures;
std::vector<EffectPtr> m_effects; // leave this outside m_things because it has no stackpos. std::vector<EffectPtr> m_effects; // leave this outside m_things because it has no stackpos.
std::vector<ThingPtr> m_things; std::vector<ThingPtr> m_things;
Position m_position; Position m_position;

Loading…
Cancel
Save