render walking creatures in the correct way

This commit is contained in:
Eduardo Bart 2012-01-30 19:28:08 -02:00
parent cf18b0c36f
commit 7b965a27af
9 changed files with 95 additions and 49 deletions

View File

@ -69,12 +69,12 @@ void Creature::draw(const Point& dest, float scaleFactor)
if(m_showVolatileSquare) {
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) {
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);
@ -134,10 +134,10 @@ void Creature::draw(const Point& dest, float scaleFactor)
}
else if(m_outfit.getCategory() == ThingsType::Item) {
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)
internalDraw(dest + m_walkOffset * scaleFactor, scaleFactor, 0);
internalDraw(dest + m_walkOffset, scaleFactor, 0);
}
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;
}
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()
{
// remove any previous scheduled walk updates
@ -303,6 +333,7 @@ void Creature::updateWalk()
// update walk animation and offsets
updateWalkAnimation(totalPixelsWalked);
updateWalkOffset(totalPixelsWalked);
updateWalkingTile();
// terminate walk
if(m_walking && m_walkTimer.ticksElapsed() >= m_walkInterval)
@ -323,6 +354,11 @@ void Creature::terminateWalk()
m_walkTurnDirection = Otc::InvalidDirection;
}
if(m_walkingTile) {
m_walkingTile->removeWalkingCreature(asCreature());
m_walkingTile = nullptr;
}
m_walking = false;
}

View File

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

View File

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

View File

@ -304,7 +304,7 @@ std::vector<CreaturePtr> Map::getSpectatorsInRangeEx(const Position& centerPos,
continue;
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()
{
if(m_centralPosition.z > Otc::SEA_FLOOR)
return m_centralPosition.z-2;
return m_centralPosition.z-Otc::AWARE_UNDEGROUND_FLOOR_RANGE;
else
return 0;
}
@ -384,7 +384,7 @@ int Map::getFirstAwareFloor()
int Map::getLastAwareFloor()
{
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
return Otc::SEA_FLOOR;
}

View File

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

View File

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

View File

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

View File

@ -38,7 +38,7 @@ Tile::Tile(const Position& position)
void Tile::draw(const Point& dest, float scaleFactor, int drawFlags)
{
m_drawElevation = 0;
int drawElevation = 0;
// first bottom items
if(drawFlags & Otc::DrawGround || drawFlags & Otc::DrawWalls) {
@ -47,11 +47,11 @@ void Tile::draw(const Point& dest, float scaleFactor, int drawFlags)
break;
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();
if(m_drawElevation > Otc::MAX_ELEVATION)
m_drawElevation = Otc::MAX_ELEVATION;
drawElevation += thing->getElevation();
if(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) {
for(auto it = m_things.rbegin(); it != m_things.rend(); ++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;
thing->draw(dest - m_drawElevation*scaleFactor, scaleFactor);
thing->draw(dest - drawElevation*scaleFactor, scaleFactor);
m_drawElevation += thing->getElevation();
if(m_drawElevation > Otc::MAX_ELEVATION)
m_drawElevation = Otc::MAX_ELEVATION;
drawElevation += thing->getElevation();
if(drawElevation > Otc::MAX_ELEVATION)
drawElevation = Otc::MAX_ELEVATION;
}
}
// we can render creatures in 3x3 range
// creatures
if(drawFlags & Otc::DrawCreatures) {
for(int xi = -1; xi <= 1; ++xi) {
for(int yi = -1; yi <= 1; ++yi) {
const TilePtr& tile = g_map.getTile(m_position.translated(xi, yi, 0));
if(!tile)
continue;
for(const CreaturePtr& creature : tile->getCreatures()) {
int tileSize = Otc::TILE_PIXELS * scaleFactor;
Rect creatureRect(dest.x + xi*tileSize + (creature->getWalkOffset().x - creature->getDisplacementX())*scaleFactor,
dest.y + yi*tileSize + (creature->getWalkOffset().y - creature->getDisplacementY())*scaleFactor,
tileSize, tileSize);
Rect thisTileRect(dest.x, dest.y, tileSize, tileSize);
for(const CreaturePtr& creature : m_walkingCreatures) {
creature->draw(Point(dest.x + ((creature->getPosition().x - m_position.x)*Otc::TILE_PIXELS - drawElevation)*scaleFactor,
dest.y + ((creature->getPosition().y - m_position.y)*Otc::TILE_PIXELS - drawElevation)*scaleFactor), scaleFactor);
// 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);
}
}
}
}
for(auto it = m_things.rbegin(); it != m_things.rend(); ++it) {
CreaturePtr creature = (*it)->asCreature();
if(creature && !creature->isWalking())
creature->draw(dest - drawElevation, scaleFactor);
}
}
@ -103,7 +94,7 @@ void Tile::draw(const Point& dest, float scaleFactor, int drawFlags)
if(drawFlags & Otc::DrawWalls) {
for(const ThingPtr& thing : m_things) {
if(thing->isOnTop())
thing->draw(dest - m_drawElevation, scaleFactor);
thing->draw(dest - drawElevation, scaleFactor);
}
}
}
@ -114,6 +105,18 @@ void Tile::clean()
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)
{
if(!thing)

View File

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