new render, look through windows/doors

This commit is contained in:
Eduardo Bart 2011-09-01 19:00:46 -03:00
parent ff2e248e40
commit e37efe7e65
7 changed files with 109 additions and 69 deletions

View File

@ -24,6 +24,7 @@
#include "game.h" #include "game.h"
#include "localplayer.h" #include "localplayer.h"
#include "tile.h" #include "tile.h"
#include "item.h"
#include <framework/graphics/graphics.h> #include <framework/graphics/graphics.h>
#include <framework/graphics/framebuffer.h> #include <framework/graphics/framebuffer.h>
@ -37,29 +38,27 @@ void Map::draw(const Rect& rect)
g_graphics.bindColor(Fw::white); g_graphics.bindColor(Fw::white);
m_framebuffer->bind(); m_framebuffer->bind();
// draw offsets
LocalPlayerPtr localPlayer = g_game.getLocalPlayer(); LocalPlayerPtr localPlayer = g_game.getLocalPlayer();
int walkOffsetX = localPlayer->getWalkOffsetX(); int walkOffsetX = localPlayer->getWalkOffsetX();
int walkOffsetY = localPlayer->getWalkOffsetY(); int walkOffsetY = localPlayer->getWalkOffsetY();
int maxFloor = getMaxVisibleFloor(); // draw from bottom floors to top floors
for(int z = MAX_Z-1; z >= maxFloor; --z) { int firstFloor = getFirstVisibleFloor();
if(z < maxFloor) const int lastFloor = MAX_Z-1;
continue; for(int iz = lastFloor; iz >= firstFloor; --iz) {
// draw tiles in linus pauling's rule order
int zdif = m_centralPosition.z - z; const int numDiagonals = MAP_SIZE_X + MAP_SIZE_Y - 1;
for(int y = 0; y < MAP_SIZE_Y; ++y) { for(int diagonal = 0; diagonal < numDiagonals; ++diagonal) {
for(int x = 0; x < MAP_SIZE_X; ++x) { // loop through / diagonal tiles
Position tilePos(m_centralPosition.x + (x - PLAYER_OFFSET_X), m_centralPosition.y + (y - PLAYER_OFFSET_Y), m_centralPosition.z); for(int ix = std::min(diagonal, MAP_SIZE_X - 1), iy = std::max(diagonal - MAP_SIZE_X, 0); ix >= 0 && iy < MAP_SIZE_Y; --ix, ++iy) {
tilePos.coveredUp(m_centralPosition.z - z); // position on current floor
if(const TilePtr& tile = m_tiles[tilePos]) { Position tilePos(m_centralPosition.x + (ix - PLAYER_OFFSET_X), m_centralPosition.y + (iy - PLAYER_OFFSET_Y), m_centralPosition.z);
// skip tiles that are behind another tile // adjust tilePos to the wanted floor
if(z > maxFloor && isCompletlyCovered(tilePos, maxFloor)) tilePos.perspectiveUp(m_centralPosition.z - iz);
continue; // TODO: skip tiles that are behind another tile
if(const TilePtr& tile = m_tiles[tilePos])
int x = (7 + (tile->getPosition().x - m_centralPosition.x) - zdif) * NUM_TILE_PIXELS; tile->draw(tilePos.to2D(m_centralPosition) - Point(walkOffsetX, walkOffsetY));
int y = (5 + (tile->getPosition().y - m_centralPosition.y) - zdif) * NUM_TILE_PIXELS;
tile->draw(x - walkOffsetX, y - walkOffsetY);
}
} }
} }
} }
@ -93,7 +92,7 @@ void Map::draw(const Rect& rect)
y += creature->getWalkOffsetY() - walkOffsetY; y += creature->getWalkOffsetY() - walkOffsetY;
} }
creature->drawInformation(rect.x() + x*horizontalStretchFactor, rect.y() + y*verticalStretchFactor, isCovered(tilePos, maxFloor)); creature->drawInformation(rect.x() + x*horizontalStretchFactor, rect.y() + y*verticalStretchFactor, isCovered(tilePos, firstFloor));
} }
} }
} }
@ -105,51 +104,62 @@ void Map::clean()
m_tiles.clear(); m_tiles.clear();
} }
int Map::getMaxVisibleFloor() int Map::getFirstVisibleFloor()
{ {
Position tilePos = m_centralPosition; int firstFloor = 0;
tilePos.up(); for(int ix = -1; ix <= 1 && firstFloor < m_centralPosition.z; ++ix) {
TilePtr tile = m_tiles[tilePos]; for(int iy = -1; iy <= 1 && firstFloor < m_centralPosition.z; ++iy) {
if(tile) Position currentPos(m_centralPosition.x + ix, m_centralPosition.y + iy, m_centralPosition.z);
return m_centralPosition.z; if((ix == 0 && iy == 0) || isLookPossible(currentPos)) {
Position upperPos = currentPos;
tilePos = Position(m_centralPosition); Position perspectivePos = currentPos;
while(tilePos.z >= 0) { perspectivePos.perspectiveUp();
tilePos.coveredUp(); upperPos.up();
tile = m_tiles[tilePos]; while(upperPos.z >= firstFloor) {
if(tile) if(TilePtr tile = m_tiles[upperPos]) {
return tilePos.z + 1; if(ThingPtr firstThing = tile->getThing(0)) {
} const ThingType type = firstThing->getType();
/* if((type.isGround || type.isOnBottom) && !type.isDontHide) {
int maxZ = MAP_SIZE_Z - 1; firstFloor = upperPos.z + 1;
int currentZ = m_centralPosition.z; break;
while(maxZ > currentZ) { }
TilePtr tile = m_tiles[tilePos]; }
if(tilç }
maxZ--; if(TilePtr tile = m_tiles[perspectivePos]) {
}; if(ThingPtr firstThing = tile->getThing(0)) {
const ThingType type = firstThing->getType();
for(int x = PLAYER_OFFSET_X-1; x <= PLAYER_OFFSET_X+1; ++x) { if((type.isGround || type.isOnBottom) && !type.isDontHide) {
for(int y = PLAYER_OFFSET_Y-1; y <= PLAYER_OFFSET_Y+1; ++y) { firstFloor = perspectivePos.z + 1;
if(x == PLAYER_OFFSET_X && y == PLAYER_OFFSET_Y) break;
continue; }
for(int z = currentZ + 1; z < }
}
perspectivePos.perspectiveUp();
upperPos.up();
}
}
} }
} }
*/ return firstFloor;
}
return 0; bool Map::isLookPossible(const Position& pos)
{
TilePtr tile = m_tiles[pos];
if(tile)
return tile->isLookPossible();
return true;
} }
bool Map::isCovered(const Position& pos, int maxFloor) bool Map::isCovered(const Position& pos, int maxFloor)
{ {
Position tilePos = pos; Position tilePos = pos;
tilePos.coveredUp(); tilePos.perspectiveUp();
while(tilePos.z >= maxFloor) { while(tilePos.z >= maxFloor) {
TilePtr tile = m_tiles[tilePos]; TilePtr tile = m_tiles[tilePos];
if(tile) if(tile && tile->isFullGround())
return true; return true;
tilePos.coveredUp(); tilePos.perspectiveUp();
} }
return false; return false;
} }
@ -157,7 +167,7 @@ bool Map::isCovered(const Position& pos, int maxFloor)
bool Map::isCompletlyCovered(const Position& pos, int maxFloor) bool Map::isCompletlyCovered(const Position& pos, int maxFloor)
{ {
Position tilePos = pos; Position tilePos = pos;
tilePos.coveredUp(); tilePos.perspectiveUp();
while(tilePos.z >= maxFloor) { while(tilePos.z >= maxFloor) {
bool covered = true; bool covered = true;
for(int x=0;x<2;++x) { for(int x=0;x<2;++x) {
@ -171,7 +181,7 @@ bool Map::isCompletlyCovered(const Position& pos, int maxFloor)
} }
if(covered) if(covered)
return true; return true;
tilePos.coveredUp(); tilePos.perspectiveUp();
} }
return false; return false;
} }

View File

@ -44,7 +44,8 @@ public:
void draw(const Rect& rect); void draw(const Rect& rect);
void clean(); void clean();
int getMaxVisibleFloor(); int getFirstVisibleFloor();
bool isLookPossible(const Position& pos);
bool isCovered(const Position& pos, int maxFloor); bool isCovered(const Position& pos, int maxFloor);
bool isCompletlyCovered(const Position& pos, int maxFloor); bool isCompletlyCovered(const Position& pos, int maxFloor);

View File

@ -129,7 +129,7 @@ void ThingsType::parseThingType(std::stringstream& fin, ThingType& thingType)
thingType.isNotMoveable = true; thingType.isNotMoveable = true;
break; break;
case Otc::DatBlockProjectile: // Blocks missiles (walls, magic wall etc) case Otc::DatBlockProjectile: // Blocks missiles (walls, magic wall etc)
thingType.isNotProjectable = true; thingType.isUnsight = true;
break; break;
case Otc::DatBlockPathFind: // Blocks pathfind algorithms (monsters) case Otc::DatBlockPathFind: // Blocks pathfind algorithms (monsters)
thingType.isNotPathable = true; thingType.isNotPathable = true;

View File

@ -50,7 +50,7 @@ struct ThingType
isSplash = false; isSplash = false;
isNotWalkable = false; isNotWalkable = false;
isNotMoveable = false; isNotMoveable = false;
isNotProjectable = false; isUnsight = false;
isNotPathable = false; isNotPathable = false;
isPickupable = false; isPickupable = false;
isHangable = false; isHangable = false;
@ -101,7 +101,7 @@ struct ThingType
bool isSplash; bool isSplash;
bool isNotWalkable; bool isNotWalkable;
bool isNotMoveable; bool isNotMoveable;
bool isNotProjectable; bool isUnsight;
bool isNotPathable; bool isNotPathable;
bool isPickupable; bool isPickupable;
bool isHangable; bool isHangable;

View File

@ -35,7 +35,7 @@ Tile::Tile(const Position& position)
m_position = position; m_position = position;
} }
void Tile::draw(int x, int y) void Tile::draw(const Point& p)
{ {
m_drawElevation = 0; m_drawElevation = 0;
@ -44,7 +44,7 @@ void Tile::draw(int x, int y)
const ThingType& type = thing->getType(); const ThingType& type = thing->getType();
if(!type.isGround && !type.isGroundClip && !type.isOnBottom) if(!type.isGround && !type.isGroundClip && !type.isOnBottom)
break; break;
thing->draw(x - m_drawElevation, y - m_drawElevation); thing->draw(p.x - m_drawElevation, p.y - m_drawElevation);
m_drawElevation += type.elevation; m_drawElevation += type.elevation;
if(m_drawElevation > MAX_DRAW_ELEVATION) if(m_drawElevation > MAX_DRAW_ELEVATION)
m_drawElevation = MAX_DRAW_ELEVATION; m_drawElevation = MAX_DRAW_ELEVATION;
@ -56,7 +56,7 @@ void Tile::draw(int x, int y)
const ThingType& type = thing->getType(); const ThingType& type = thing->getType();
if(thing->asCreature() || type.isOnTop || type.isOnBottom || type.isGroundClip || type.isGround) if(thing->asCreature() || type.isOnTop || type.isOnBottom || type.isGroundClip || type.isGround)
break; break;
thing->draw(x - m_drawElevation, y - m_drawElevation); thing->draw(p.x - m_drawElevation, p.y - m_drawElevation);
m_drawElevation += type.elevation; m_drawElevation += type.elevation;
if(m_drawElevation > MAX_DRAW_ELEVATION) if(m_drawElevation > MAX_DRAW_ELEVATION)
m_drawElevation = MAX_DRAW_ELEVATION; m_drawElevation = MAX_DRAW_ELEVATION;
@ -68,25 +68,25 @@ void Tile::draw(int x, int y)
for(int yi = -1; yi <= 1; ++yi) { for(int yi = -1; yi <= 1; ++yi) {
for(CreaturePtr creature : g_map.getTile(m_position + Position(xi, yi, 0))->getCreatures()) { for(CreaturePtr creature : g_map.getTile(m_position + Position(xi, yi, 0))->getCreatures()) {
auto& type = creature->getType(); auto& type = creature->getType();
Rect creatureRect(x + xi*32 + creature->getWalkOffsetX() - type.xDisplacement, y + yi*32 + creature->getWalkOffsetY() - type.yDisplacement, 32, 32); Rect creatureRect(p.x + xi*32 + creature->getWalkOffsetX() - type.xDisplacement, p.y + yi*32 + creature->getWalkOffsetY() - type.yDisplacement, 32, 32);
Rect thisTileRect(x, y, 32, 32); Rect thisTileRect(p.x, p.y, 32, 32);
// only render creatures where bottom right is inside our rect // only render creatures where bottom right is inside our rect
if(thisTileRect.contains(creatureRect.bottomRight())) if(thisTileRect.contains(creatureRect.bottomRight()))
creature->draw(x + xi*32 - m_drawElevation, y + yi*32 - m_drawElevation); creature->draw(p.x + xi*32 - m_drawElevation, p.y + yi*32 - m_drawElevation);
} }
} }
} }
// effects // effects
for(const EffectPtr& effect : m_effects) for(const EffectPtr& effect : m_effects)
effect->draw(x - m_drawElevation, y - m_drawElevation); effect->draw(p.x - m_drawElevation, p.y - m_drawElevation);
// top items // top items
for(const ThingPtr& thing : m_things) { for(const ThingPtr& thing : m_things) {
const ThingType& type = thing->getType(); const ThingType& type = thing->getType();
if(type.isOnTop) if(type.isOnTop)
thing->draw(x - m_drawElevation, y - m_drawElevation); thing->draw(p.x - m_drawElevation, p.y - m_drawElevation);
} }
} }
@ -183,6 +183,17 @@ ItemPtr Tile::getGround()
return nullptr; return nullptr;
} }
bool Tile::isFullGround()
{
ThingPtr ground = getThing(0);
if(!ground)
return false;
const ThingType& type = ground->getType();
if(type.isGround && type.isFullGround)
return true;
return false;
}
bool Tile::isFullyOpaque() bool Tile::isFullyOpaque()
{ {
ThingPtr firstObject = getThing(0); ThingPtr firstObject = getThing(0);
@ -193,3 +204,13 @@ bool Tile::isFullyOpaque()
} }
return false; return false;
} }
bool Tile::isLookPossible()
{
for(const ThingPtr& thing : m_things) {
const ThingType& type = thing->getType();
if(type.isUnsight)
return false;
}
return true;
}

View File

@ -34,7 +34,7 @@ class Tile : public LuaObject
public: public:
Tile(const Position& position); Tile(const Position& position);
void draw(int x, int y); void draw(const Point& p);
void clean(); void clean();
void addEffect(const EffectPtr& effect); void addEffect(const EffectPtr& effect);
@ -48,7 +48,9 @@ public:
int getDrawElevation() { return m_drawElevation; } int getDrawElevation() { return m_drawElevation; }
std::vector<CreaturePtr> getCreatures(); std::vector<CreaturePtr> getCreatures();
ItemPtr getGround(); ItemPtr getGround();
bool isFullGround();
bool isFullyOpaque(); bool isFullyOpaque();
bool isLookPossible();
TilePtr asTile() { return std::static_pointer_cast<Tile>(shared_from_this()); } TilePtr asTile() { return std::static_pointer_cast<Tile>(shared_from_this()); }

View File

@ -25,6 +25,7 @@
#include <otclient/const.h> #include <otclient/const.h>
#include <framework/util/types.h> #include <framework/util/types.h>
#include <framework/util/point.h>
class Position class Position
{ {
@ -70,10 +71,15 @@ public:
return std::abs(x-pos.x) <= xdif && std::abs(y-pos.y) <= ydif && std::abs(pos.z-z) <= zdif; return std::abs(x-pos.x) <= xdif && std::abs(y-pos.y) <= ydif && std::abs(pos.z-z) <= zdif;
} }
Point to2D(const Position& centerPos) const {
return Point((7 + (x - centerPos.x) - (centerPos.z - z)) * 32,
(5 + (y - centerPos.y) - (centerPos.z - z)) * 32);
};
void up(int n = 1) { z-=n; } void up(int n = 1) { z-=n; }
void down(int n = 1) { z+=n; } void down(int n = 1) { z+=n; }
void coveredUp(int n = 1) { x+=n; y+=n; z-=n; } void perspectiveUp(int n = 1) { x+=n; y+=n; z-=n; }
void coveredDown(int n = 1) { x-=n; y-=n; z+=n; } void coveredDown(int n = 1) { x-=n; y-=n; z+=n; }
int x; int x;