From 30465691ae3e9070880d780679b3fc15ab40e4ac Mon Sep 17 00:00:00 2001 From: Jonas Kulla Date: Sun, 19 Jul 2015 17:30:25 +0200 Subject: [PATCH] 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. --- src/tilemap-common.h | 10 +++++++ src/tilemap.cpp | 62 ++++++++++++-------------------------------- src/tilemapvx.cpp | 4 +-- 3 files changed, 27 insertions(+), 49 deletions(-) diff --git a/src/tilemap-common.h b/src/tilemap-common.h index 76dcf15..028dfd7 100644 --- a/src/tilemap-common.h +++ b/src/tilemap-common.h @@ -61,6 +61,16 @@ tableGetWrapped(const Table &t, int x, int y, int z = 0) 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 { TopLeft = 0, diff --git a/src/tilemap.cpp b/src/tilemap.cpp index f721e03..8b61ea7 100644 --- a/src/tilemap.cpp +++ b/src/tilemap.cpp @@ -236,7 +236,7 @@ struct TilemapPrivate Table *mapData; Table *priorities; bool visible; - Vec2i offset; + Vec2i origin; Vec2i dispPos; @@ -294,7 +294,6 @@ struct TilemapPrivate /* Used layers out of 'zlayers' (rest is hidden) */ size_t activeLayers; Scene::Geometry sceneGeo; - Vec2i sceneOffset; } elem; /* Affected by: autotiles, tileset */ @@ -394,7 +393,7 @@ struct TilemapPrivate void updateFlashMapViewport() { - flashMap.setViewport(IntRect(viewpPos.x, viewpPos.y, viewpW, viewpH)); + flashMap.setViewport(IntRect(viewpPos, Vec2i(viewpW, viewpH))); } void updateAtlasInfo() @@ -442,13 +441,8 @@ struct TilemapPrivate void updateSceneGeometry(const Scene::Geometry &geo) { - elem.sceneOffset = geo.offset(); elem.sceneGeo = geo; - } - - void updatePosition() - { - dispPos = -(offset - viewpPos * 32) + elem.sceneOffset; + mapViewportDirty = true; } void invalidateAtlasSize() @@ -898,38 +892,17 @@ struct TilemapPrivate void updateMapViewport() { - int tileOX, tileOY; + const Vec2i combOrigin = origin + elem.sceneGeo.orig; + const Vec2i mvpPos = getTilePos(combOrigin); - if (offset.x >= 0) - 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) + if (mvpPos != viewpPos) { + viewpPos = mvpPos; buffersDirty = true; updateFlashMapViewport(); - updatePosition(); } + + dispPos = elem.sceneGeo.rect.pos() - wrap(combOrigin, 32); } void prepare() @@ -1024,7 +997,6 @@ void GroundLayer::drawInt() void GroundLayer::onGeometryChange(const Scene::Geometry &geo) { p->updateSceneGeometry(geo); - p->updatePosition(); } ZLayer::ZLayer(TilemapPrivate *p, Viewport *viewport) @@ -1072,7 +1044,7 @@ void ZLayer::drawInt() 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() @@ -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, Priorities, Table*, p->priorities) DEF_ATTR_RD_SIMPLE(Tilemap, Visible, bool, p->visible) -DEF_ATTR_RD_SIMPLE(Tilemap, OX, int, p->offset.x) -DEF_ATTR_RD_SIMPLE(Tilemap, OY, int, p->offset.y) +DEF_ATTR_RD_SIMPLE(Tilemap, OX, int, p->origin.x) +DEF_ATTR_RD_SIMPLE(Tilemap, OY, int, p->origin.y) void Tilemap::setTileset(Bitmap *value) { @@ -1259,11 +1231,10 @@ void Tilemap::setOX(int value) { guardDisposed(); - if (p->offset.x == value) + if (p->origin.x == value) return; - p->offset.x = value; - p->updatePosition(); + p->origin.x = value; p->mapViewportDirty = true; } @@ -1271,11 +1242,10 @@ void Tilemap::setOY(int value) { guardDisposed(); - if (p->offset.y == value) + if (p->origin.y == value) return; - p->offset.y = value; - p->updatePosition(); + p->origin.y = value; p->zOrderDirty = true; p->mapViewportDirty = true; } diff --git a/src/tilemapvx.cpp b/src/tilemapvx.cpp index 5773110..cd91c66 100644 --- a/src/tilemapvx.cpp +++ b/src/tilemapvx.cpp @@ -186,9 +186,7 @@ struct TilemapVXPrivate : public ViewportElement, TileAtlasVX::Reader const Vec2i combOrigin = origin + sceneGeo.orig; const Vec2i geoSize = sceneGeo.rect.size(); - /* Round the combined origin (which is in pixels) down to the nearest - * top left tile boundary, by masking off the lower 5 bits (2^5 = 32) */ - newMvp.setPos((combOrigin & ~(32-1)) / 32); + newMvp.setPos(getTilePos(combOrigin)); /* Ensure that the size is big enough to cover the whole viewport, * and add one tile row/column as a buffer for scrolling */