Tilemap: Fix map viewport calculation

Calculation was completely off as it didn't take into
account the imposed viewport origin.

All in all, similar fixes as the previous ones to TilemapVX.
This commit is contained in:
Jonas Kulla 2015-07-19 17:30:25 +02:00
parent dd7545fcf2
commit 30465691ae
3 changed files with 27 additions and 49 deletions

View File

@ -61,6 +61,16 @@ tableGetWrapped(const Table &t, int x, int y, int z = 0)
z); z);
} }
/* Calculate the tile x/y on which this pixel x/y lies */
static inline Vec2i
getTilePos(const Vec2i &pixelPos)
{
/* Round the pixel position down to the nearest top left
* tile boundary, by masking off the lower 5 bits (2^5 = 32).
* Then divide by 32 to convert into tile units. */
return (pixelPos & ~(32-1)) / 32;
}
enum AtSubPos enum AtSubPos
{ {
TopLeft = 0, TopLeft = 0,

View File

@ -236,7 +236,7 @@ struct TilemapPrivate
Table *mapData; Table *mapData;
Table *priorities; Table *priorities;
bool visible; bool visible;
Vec2i offset; Vec2i origin;
Vec2i dispPos; Vec2i dispPos;
@ -294,7 +294,6 @@ struct TilemapPrivate
/* Used layers out of 'zlayers' (rest is hidden) */ /* Used layers out of 'zlayers' (rest is hidden) */
size_t activeLayers; size_t activeLayers;
Scene::Geometry sceneGeo; Scene::Geometry sceneGeo;
Vec2i sceneOffset;
} elem; } elem;
/* Affected by: autotiles, tileset */ /* Affected by: autotiles, tileset */
@ -394,7 +393,7 @@ struct TilemapPrivate
void updateFlashMapViewport() void updateFlashMapViewport()
{ {
flashMap.setViewport(IntRect(viewpPos.x, viewpPos.y, viewpW, viewpH)); flashMap.setViewport(IntRect(viewpPos, Vec2i(viewpW, viewpH)));
} }
void updateAtlasInfo() void updateAtlasInfo()
@ -442,13 +441,8 @@ struct TilemapPrivate
void updateSceneGeometry(const Scene::Geometry &geo) void updateSceneGeometry(const Scene::Geometry &geo)
{ {
elem.sceneOffset = geo.offset();
elem.sceneGeo = geo; elem.sceneGeo = geo;
} mapViewportDirty = true;
void updatePosition()
{
dispPos = -(offset - viewpPos * 32) + elem.sceneOffset;
} }
void invalidateAtlasSize() void invalidateAtlasSize()
@ -898,38 +892,17 @@ struct TilemapPrivate
void updateMapViewport() void updateMapViewport()
{ {
int tileOX, tileOY; const Vec2i combOrigin = origin + elem.sceneGeo.orig;
const Vec2i mvpPos = getTilePos(combOrigin);
if (offset.x >= 0) if (mvpPos != viewpPos)
tileOX = offset.x / 32;
else
tileOX = -(-(offset.x-31) / 32);
if (offset.y >= 0)
tileOY = offset.y / 32;
else
tileOY = -(-(offset.y-31) / 32);
bool dirty = false;
if (tileOX < viewpPos.x || tileOX + 21 > viewpPos.x + viewpW)
{
viewpPos.x = tileOX;
dirty = true;
}
if (tileOY < viewpPos.y || tileOY + 16 > viewpPos.y + viewpH)
{
viewpPos.y = tileOY;
dirty = true;
}
if (dirty)
{ {
viewpPos = mvpPos;
buffersDirty = true; buffersDirty = true;
updateFlashMapViewport(); updateFlashMapViewport();
updatePosition();
} }
dispPos = elem.sceneGeo.rect.pos() - wrap(combOrigin, 32);
} }
void prepare() void prepare()
@ -1024,7 +997,6 @@ void GroundLayer::drawInt()
void GroundLayer::onGeometryChange(const Scene::Geometry &geo) void GroundLayer::onGeometryChange(const Scene::Geometry &geo)
{ {
p->updateSceneGeometry(geo); p->updateSceneGeometry(geo);
p->updatePosition();
} }
ZLayer::ZLayer(TilemapPrivate *p, Viewport *viewport) ZLayer::ZLayer(TilemapPrivate *p, Viewport *viewport)
@ -1072,7 +1044,7 @@ void ZLayer::drawInt()
int ZLayer::calculateZ(TilemapPrivate *p, int index) int ZLayer::calculateZ(TilemapPrivate *p, int index)
{ {
return 32 * (index + p->viewpPos.y + 1) - p->offset.y; return 32 * (index + p->viewpPos.y + 1) - p->origin.y;
} }
void ZLayer::initUpdateZ() void ZLayer::initUpdateZ()
@ -1172,8 +1144,8 @@ DEF_ATTR_RD_SIMPLE(Tilemap, MapData, Table*, p->mapData)
DEF_ATTR_RD_SIMPLE(Tilemap, FlashData, Table*, p->flashMap.getData()) DEF_ATTR_RD_SIMPLE(Tilemap, FlashData, Table*, p->flashMap.getData())
DEF_ATTR_RD_SIMPLE(Tilemap, Priorities, Table*, p->priorities) DEF_ATTR_RD_SIMPLE(Tilemap, Priorities, Table*, p->priorities)
DEF_ATTR_RD_SIMPLE(Tilemap, Visible, bool, p->visible) DEF_ATTR_RD_SIMPLE(Tilemap, Visible, bool, p->visible)
DEF_ATTR_RD_SIMPLE(Tilemap, OX, int, p->offset.x) DEF_ATTR_RD_SIMPLE(Tilemap, OX, int, p->origin.x)
DEF_ATTR_RD_SIMPLE(Tilemap, OY, int, p->offset.y) DEF_ATTR_RD_SIMPLE(Tilemap, OY, int, p->origin.y)
void Tilemap::setTileset(Bitmap *value) void Tilemap::setTileset(Bitmap *value)
{ {
@ -1259,11 +1231,10 @@ void Tilemap::setOX(int value)
{ {
guardDisposed(); guardDisposed();
if (p->offset.x == value) if (p->origin.x == value)
return; return;
p->offset.x = value; p->origin.x = value;
p->updatePosition();
p->mapViewportDirty = true; p->mapViewportDirty = true;
} }
@ -1271,11 +1242,10 @@ void Tilemap::setOY(int value)
{ {
guardDisposed(); guardDisposed();
if (p->offset.y == value) if (p->origin.y == value)
return; return;
p->offset.y = value; p->origin.y = value;
p->updatePosition();
p->zOrderDirty = true; p->zOrderDirty = true;
p->mapViewportDirty = true; p->mapViewportDirty = true;
} }

View File

@ -186,9 +186,7 @@ struct TilemapVXPrivate : public ViewportElement, TileAtlasVX::Reader
const Vec2i combOrigin = origin + sceneGeo.orig; const Vec2i combOrigin = origin + sceneGeo.orig;
const Vec2i geoSize = sceneGeo.rect.size(); const Vec2i geoSize = sceneGeo.rect.size();
/* Round the combined origin (which is in pixels) down to the nearest newMvp.setPos(getTilePos(combOrigin));
* top left tile boundary, by masking off the lower 5 bits (2^5 = 32) */
newMvp.setPos((combOrigin & ~(32-1)) / 32);
/* Ensure that the size is big enough to cover the whole viewport, /* Ensure that the size is big enough to cover the whole viewport,
* and add one tile row/column as a buffer for scrolling */ * and add one tile row/column as a buffer for scrolling */