[BUG] TileMap flipped/rotated animated tiles incorrect rendering. (#1098)

* Add test cases

* Delete default_hrtf.txt

* Fix rotated/flipped animated tile maps

* Optimize bitwise operations

* improve bitwise operations
This commit is contained in:
Turky Mohammed 2023-03-07 07:26:37 -08:00 committed by GitHub
parent 8d52ad2e56
commit 969c2257f8
5 changed files with 77 additions and 12 deletions

View File

@ -356,7 +356,12 @@ void FastTMXLayer::setupTiles()
}
int pos = static_cast<int>(newX + _layerSize.width * y);
int gid = _tiles[pos];
uint32_t gid = _tiles[pos];
uint32_t flags = 0;
// issue#1098 TileMap flipped/rotated animation bug.
flags |= gid & kTMXFlipedAll;
gid &= ~kTMXFlipedAll;
// gid are stored in little endian.
// if host is big endian, then swap
@ -369,7 +374,7 @@ void FastTMXLayer::setupTiles()
{
if (_tileSet->_animationInfo.find(gid) != _tileSet->_animationInfo.end())
{
_animTileCoord[gid].emplace_back(Vec2(newX, y));
_animTileCoord[gid].emplace_back(TMXTileAnimFlag{Vec2(newX, y), flags});
}
}
}
@ -960,9 +965,9 @@ TMXTileAnimManager::TMXTileAnimManager(FastTMXLayer* layer)
_layer = layer;
for (const auto& p : *_layer->getAnimTileCoord())
{
for (auto&& tilePos : p.second)
for (auto&& tile : p.second)
{
_tasks.pushBack(TMXTileAnimTask::create(_layer, _layer->getTileSet()->_animationInfo.at(p.first), tilePos));
_tasks.pushBack(TMXTileAnimTask::create(_layer, _layer->getTileSet()->_animationInfo.at(p.first), tile._tilePos, tile._flag));
}
}
}
@ -996,12 +1001,13 @@ void TMXTileAnimManager::stopAll()
}
}
TMXTileAnimTask::TMXTileAnimTask(FastTMXLayer* layer, TMXTileAnimInfo* animation, const Vec2& tilePos)
TMXTileAnimTask::TMXTileAnimTask(FastTMXLayer* layer, TMXTileAnimInfo* animation, const Vec2& tilePos, uint32_t flag)
{
_layer = layer;
_animation = animation;
_frameCount = static_cast<uint32_t>(_animation->_frames.size());
_tilePosition = tilePos;
_flag = flag;
std::stringstream ss;
ss << "TickAnimOnTilePos(" << _tilePosition.x << "," << _tilePosition.y << ")";
_key = ss.str();
@ -1028,13 +1034,13 @@ void TMXTileAnimTask::stop()
void TMXTileAnimTask::setCurrFrame()
{
_layer->setTileGID(_animation->_frames[_currentFrame]._tileID, _tilePosition);
_layer->setTileGID(_animation->_frames[_currentFrame]._tileID, _tilePosition, (TMXTileFlags)_flag);
_currentFrame = (_currentFrame + 1) % _frameCount;
}
TMXTileAnimTask* TMXTileAnimTask::create(FastTMXLayer* layer, TMXTileAnimInfo* animation, const Vec2& tilePos)
TMXTileAnimTask* TMXTileAnimTask::create(FastTMXLayer* layer, TMXTileAnimInfo* animation, const Vec2& tilePos, uint32_t flag)
{
TMXTileAnimTask* ret = new TMXTileAnimTask(layer, animation, tilePos);
TMXTileAnimTask* ret = new TMXTileAnimTask(layer, animation, tilePos, flag);
ret->autorelease();
return ret;
}

View File

@ -286,7 +286,7 @@ public:
*
* @return Map from gid of animated tile to its instance.
*/
const std::unordered_map<uint32_t, std::vector<Vec2>>* getAnimTileCoord() { return &_animTileCoord; }
const std::unordered_map<uint32_t, std::vector<TMXTileAnimFlag>>* getAnimTileCoord() { return &_animTileCoord; }
bool hasTileAnimation() const { return !_animTileCoord.empty(); }
@ -341,7 +341,7 @@ protected:
ValueMap _properties;
/** map from gid of animated tile to its instance. Also useful for optimization*/
std::unordered_map<uint32_t, std::vector<Vec2>> _animTileCoord;
std::unordered_map<uint32_t, std::vector<TMXTileAnimFlag>> _animTileCoord;
/** pointer to the tile animation manager of this layer */
TMXTileAnimManager* _tileAnimManager = nullptr;
@ -389,8 +389,8 @@ protected:
class AX_DLL TMXTileAnimTask : public Ref
{
public:
TMXTileAnimTask(FastTMXLayer* layer, TMXTileAnimInfo* animation, const Vec2& tilePos);
static TMXTileAnimTask* create(FastTMXLayer* layer, TMXTileAnimInfo* animation, const Vec2& tilePos);
TMXTileAnimTask(FastTMXLayer* layer, TMXTileAnimInfo* animation, const Vec2& tilePos, uint32_t flag = 0);
static TMXTileAnimTask* create(FastTMXLayer* layer, TMXTileAnimInfo* animation, const Vec2& tilePos, uint32_t flag = 0);
/** start the animation task */
void start();
/** stop the animation task */
@ -398,6 +398,9 @@ public:
bool isRunning() const { return _isRunning; }
protected:
/** tile flag */
uint32_t _flag = 0;
/** set texture of tile to current frame */
void setCurrFrame();
/** tick to next frame and schedule next tick */

View File

@ -143,6 +143,17 @@ struct AX_DLL TMXTileAnimFrame
float _duration = 0.0f;
};
/** @brief TMXTileAnimFlag contains animated tile position and flag
This information is obtained from the TMX file.
*/
struct AX_DLL TMXTileAnimFlag
{
/** position of tile */
ax::Vec2 _tilePos;
/** flag of a tile */
uint32_t _flag = 0;
};
/** @brief TMXTileAnimInfo contains the information about the animated tile like:
- Animated Tile gid
- frames the animated tile contains

View File

@ -67,6 +67,7 @@ FastTileMapTests::FastTileMapTests()
ADD_TEST_CASE(TMXBug787New);
ADD_TEST_CASE(TMXGIDObjectsTestNew);
ADD_TEST_CASE(TileAnimTestNew);
ADD_TEST_CASE(TileAnimTestNew2);
}
TileDemoNew::TileDemoNew()
@ -1398,3 +1399,35 @@ void TileAnimTestNew::onTouchBegan(const std::vector<ax::Touch*>& touches, ax::E
_animStarted = !_animStarted;
map->setTileAnimEnabled(_animStarted);
}
//------------------------------------------------------------------
//
// TileAnimTestNew2
//
//------------------------------------------------------------------
TileAnimTestNew2::TileAnimTestNew2()
{
map = FastTMXTiledMap::create("TileMaps/tile_animation_test_2.tmx");
addChild(map, 0, kTagTileMap);
auto listener = EventListenerTouchAllAtOnce::create();
listener->onTouchesBegan = AX_CALLBACK_2(TileAnimTestNew2::onTouchBegan, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
Size AX_UNUSED s = map->getContentSize();
AXLOG("ContentSize: %f, %f", s.width, s.height);
map->setTileAnimEnabled(_animStarted);
}
std::string TileAnimTestNew2::title() const
{
return "Tile animation test with flipped/rotated. Click to toggle the animation";
}
void TileAnimTestNew2::onTouchBegan(const std::vector<ax::Touch*>& touches, ax::Event* event)
{
_animStarted = !_animStarted;
map->setTileAnimEnabled(_animStarted);
}

View File

@ -351,4 +351,16 @@ public:
void onTouchBegan(const std::vector<ax::Touch*>& touches, ax::Event* event);
};
class TileAnimTestNew2 : public TileDemoNew
{
public:
CREATE_FUNC(TileAnimTestNew2);
TileAnimTestNew2();
virtual std::string title() const override;
ax::FastTMXTiledMap* map;
bool _animStarted = true;
void onTouchBegan(const std::vector<ax::Touch*>& touches, ax::Event* event);
};
#endif