2019-11-23 20:27:39 +08:00
|
|
|
/****************************************************************************
|
|
|
|
Copyright (c) 2009-2010 Ricardo Quesada
|
|
|
|
Copyright (c) 2010-2012 cocos2d-x.org
|
|
|
|
Copyright (c) 2011 Zynga Inc.
|
|
|
|
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
|
|
|
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
|
|
|
|
2022-08-08 18:02:17 +08:00
|
|
|
https://axys1.github.io/
|
2019-11-23 20:27:39 +08:00
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
|
|
in the Software without restriction, including without limitation the rights
|
|
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
|
|
all copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
THE SOFTWARE.
|
|
|
|
****************************************************************************/
|
|
|
|
#include "2d/CCFastTMXTiledMap.h"
|
|
|
|
#include "2d/CCFastTMXLayer.h"
|
|
|
|
#include "base/ccUTF8.h"
|
|
|
|
|
2022-07-11 17:50:21 +08:00
|
|
|
NS_AX_BEGIN
|
2019-11-23 20:27:39 +08:00
|
|
|
|
|
|
|
// implementation FastTMXTiledMap
|
|
|
|
|
2021-12-31 12:12:40 +08:00
|
|
|
FastTMXTiledMap* FastTMXTiledMap::create(std::string_view tmxFile)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
FastTMXTiledMap* ret = new FastTMXTiledMap();
|
2019-11-23 20:27:39 +08:00
|
|
|
if (ret->initWithTMXFile(tmxFile))
|
|
|
|
{
|
|
|
|
ret->autorelease();
|
|
|
|
return ret;
|
|
|
|
}
|
2022-07-16 10:43:05 +08:00
|
|
|
AX_SAFE_DELETE(ret);
|
2019-11-23 20:27:39 +08:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2021-12-31 12:12:40 +08:00
|
|
|
FastTMXTiledMap* FastTMXTiledMap::createWithXML(std::string_view tmxString, std::string_view resourcePath)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
FastTMXTiledMap* ret = new FastTMXTiledMap();
|
2019-11-23 20:27:39 +08:00
|
|
|
if (ret->initWithXML(tmxString, resourcePath))
|
|
|
|
{
|
|
|
|
ret->autorelease();
|
|
|
|
return ret;
|
|
|
|
}
|
2022-07-16 10:43:05 +08:00
|
|
|
AX_SAFE_DELETE(ret);
|
2019-11-23 20:27:39 +08:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2021-12-31 12:12:40 +08:00
|
|
|
bool FastTMXTiledMap::initWithTMXFile(std::string_view tmxFile)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
2022-07-16 10:43:05 +08:00
|
|
|
AXASSERT(tmxFile.size() > 0, "FastTMXTiledMap: tmx file should not be empty");
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2021-10-23 23:27:14 +08:00
|
|
|
setContentSize(Vec2::ZERO);
|
2019-11-23 20:27:39 +08:00
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
TMXMapInfo* mapInfo = TMXMapInfo::create(tmxFile);
|
2019-11-23 20:27:39 +08:00
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
if (!mapInfo)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2022-07-16 10:43:05 +08:00
|
|
|
AXASSERT(!mapInfo->getTilesets().empty(), "FastTMXTiledMap: Map not found. Please check the filename.");
|
2019-11-23 20:27:39 +08:00
|
|
|
buildWithMapInfo(mapInfo);
|
|
|
|
|
2020-08-28 17:26:30 +08:00
|
|
|
_tmxFile = tmxFile;
|
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-12-31 12:12:40 +08:00
|
|
|
bool FastTMXTiledMap::initWithXML(std::string_view tmxString, std::string_view resourcePath)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
2021-10-23 23:27:14 +08:00
|
|
|
setContentSize(Vec2::ZERO);
|
2019-11-23 20:27:39 +08:00
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
TMXMapInfo* mapInfo = TMXMapInfo::createWithXML(tmxString, resourcePath);
|
2019-11-23 20:27:39 +08:00
|
|
|
|
2022-07-16 10:43:05 +08:00
|
|
|
AXASSERT(!mapInfo->getTilesets().empty(), "FastTMXTiledMap: Map not found. Please check the filename.");
|
2019-11-23 20:27:39 +08:00
|
|
|
buildWithMapInfo(mapInfo);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
FastTMXTiledMap::FastTMXTiledMap() : _mapSize(Vec2::ZERO), _tileSize(Vec2::ZERO) {}
|
2019-11-23 20:27:39 +08:00
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
FastTMXTiledMap::~FastTMXTiledMap() {}
|
2019-11-23 20:27:39 +08:00
|
|
|
|
|
|
|
// private
|
2021-12-25 10:04:45 +08:00
|
|
|
FastTMXLayer* FastTMXTiledMap::parseLayer(TMXLayerInfo* layerInfo, TMXMapInfo* mapInfo)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
TMXTilesetInfo* tileset = tilesetForLayer(layerInfo, mapInfo);
|
2019-11-23 20:27:39 +08:00
|
|
|
if (tileset == nullptr)
|
|
|
|
return nullptr;
|
2021-12-25 10:04:45 +08:00
|
|
|
|
|
|
|
FastTMXLayer* layer = FastTMXLayer::create(tileset, layerInfo, mapInfo);
|
2019-11-23 20:27:39 +08:00
|
|
|
|
|
|
|
// tell the layerinfo to release the ownership of the tiles map.
|
|
|
|
layerInfo->_ownTiles = false;
|
|
|
|
layer->setupTiles();
|
|
|
|
|
|
|
|
return layer;
|
|
|
|
}
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
TMXTilesetInfo* FastTMXTiledMap::tilesetForLayer(TMXLayerInfo* layerInfo, TMXMapInfo* mapInfo)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
Vec2 size = layerInfo->_layerSize;
|
2019-11-23 20:27:39 +08:00
|
|
|
auto& tilesets = mapInfo->getTilesets();
|
|
|
|
|
|
|
|
for (auto iter = tilesets.crbegin(), iterCrend = tilesets.crend(); iter != iterCrend; ++iter)
|
|
|
|
{
|
|
|
|
TMXTilesetInfo* tilesetInfo = *iter;
|
|
|
|
if (tilesetInfo)
|
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
for (int y = 0; y < size.height; y++)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
for (int x = 0; x < size.width; x++)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
uint32_t pos = static_cast<uint32_t>(x + size.width * y);
|
2021-12-25 10:04:45 +08:00
|
|
|
uint32_t gid = layerInfo->_tiles[pos];
|
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
// gid are stored in little endian.
|
|
|
|
// if host is big endian, then swap
|
2021-12-25 10:04:45 +08:00
|
|
|
// if( o == CFByteOrderBigEndian )
|
2019-11-23 20:27:39 +08:00
|
|
|
// gid = CFSwapInt32( gid );
|
|
|
|
/* We support little endian.*/
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
// FIXME: gid == 0 --> empty tile
|
2021-12-25 10:04:45 +08:00
|
|
|
if (gid != 0)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
// Optimization: quick return
|
|
|
|
// if the layer is invalid (more than 1 tileset per layer) an CCAssert will be thrown later
|
2021-12-25 10:04:45 +08:00
|
|
|
if ((gid & kTMXFlippedMask) >= static_cast<uint32_t>(tilesetInfo->_firstGid))
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
return tilesetInfo;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If all the tiles are 0, return empty tileset
|
2022-07-16 10:43:05 +08:00
|
|
|
AXLOG("cocos2d: Warning: TMX Layer '%s' has no tiles", layerInfo->_name.c_str());
|
2019-11-23 20:27:39 +08:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void FastTMXTiledMap::buildWithMapInfo(TMXMapInfo* mapInfo)
|
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
_mapSize = mapInfo->getMapSize();
|
|
|
|
_tileSize = mapInfo->getTileSize();
|
2019-11-23 20:27:39 +08:00
|
|
|
_mapOrientation = mapInfo->getOrientation();
|
|
|
|
|
|
|
|
_objectGroups = mapInfo->getObjectGroups();
|
|
|
|
|
|
|
|
_properties = mapInfo->getProperties();
|
|
|
|
|
|
|
|
_tileProperties = mapInfo->getTileProperties();
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
int idx = 0;
|
2019-11-23 20:27:39 +08:00
|
|
|
|
|
|
|
auto& layers = mapInfo->getLayers();
|
2021-12-25 10:04:45 +08:00
|
|
|
for (const auto& layerInfo : layers)
|
|
|
|
{
|
2019-11-23 20:27:39 +08:00
|
|
|
if (layerInfo->_visible)
|
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
FastTMXLayer* child = parseLayer(layerInfo, mapInfo);
|
|
|
|
if (child == nullptr)
|
|
|
|
{
|
2019-11-23 20:27:39 +08:00
|
|
|
idx++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
addChild(child, idx, idx);
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
// update content size with the max size
|
2021-10-23 23:27:14 +08:00
|
|
|
const Vec2& childSize = child->getContentSize();
|
2021-12-25 10:04:45 +08:00
|
|
|
Vec2 currentSize = this->getContentSize();
|
|
|
|
currentSize.width = std::max(currentSize.width, childSize.width);
|
|
|
|
currentSize.height = std::max(currentSize.height, childSize.height);
|
2019-11-23 20:27:39 +08:00
|
|
|
this->setContentSize(currentSize);
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
idx++;
|
|
|
|
}
|
|
|
|
}
|
2020-08-28 17:26:30 +08:00
|
|
|
|
|
|
|
_layerCount = idx;
|
2019-11-23 20:27:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// public
|
2021-12-31 12:12:40 +08:00
|
|
|
FastTMXLayer* FastTMXTiledMap::getLayer(std::string_view layerName) const
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
2022-07-16 10:43:05 +08:00
|
|
|
AXASSERT(!layerName.empty(), "Invalid layer name!");
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2022-07-21 19:19:08 +08:00
|
|
|
for (auto&& child : _children)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
FastTMXLayer* layer = dynamic_cast<FastTMXLayer*>(child);
|
2021-12-25 10:04:45 +08:00
|
|
|
if (layer)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
if (layerName.compare(layer->getLayerName()) == 0)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
return layer;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// layer not found
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2021-12-31 12:12:40 +08:00
|
|
|
TMXObjectGroup* FastTMXTiledMap::getObjectGroup(std::string_view groupName) const
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
2022-07-16 10:43:05 +08:00
|
|
|
AXASSERT(!groupName.empty(), "Invalid group name!");
|
2019-11-23 20:27:39 +08:00
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
if (_objectGroups.size() > 0)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
for (const auto& objectGroup : _objectGroups)
|
|
|
|
{
|
|
|
|
if (objectGroup && objectGroup->getGroupName() == groupName)
|
|
|
|
{
|
|
|
|
return objectGroup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// objectGroup not found
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2021-12-31 12:12:40 +08:00
|
|
|
Value FastTMXTiledMap::getProperty(std::string_view propertyName) const
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
auto propsItr = _properties.find(propertyName);
|
|
|
|
if (propsItr != _properties.end())
|
|
|
|
return propsItr->second;
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
return Value();
|
|
|
|
}
|
|
|
|
|
|
|
|
Value FastTMXTiledMap::getPropertiesForGID(int GID) const
|
|
|
|
{
|
|
|
|
auto propsItr = _tileProperties.find(GID);
|
|
|
|
if (propsItr != _tileProperties.end())
|
|
|
|
return propsItr->second;
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
return Value();
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string FastTMXTiledMap::getDescription() const
|
|
|
|
{
|
|
|
|
return StringUtils::format("<FastTMXTiledMap | Tag = %d, Layers = %d", _tag, static_cast<int>(_children.size()));
|
|
|
|
}
|
|
|
|
|
2020-08-28 16:33:52 +08:00
|
|
|
void FastTMXTiledMap::setTileAnimEnabled(bool enabled)
|
|
|
|
{
|
2022-07-21 19:19:08 +08:00
|
|
|
for (auto&& child : _children)
|
2020-08-28 16:33:52 +08:00
|
|
|
{
|
|
|
|
FastTMXLayer* layer = dynamic_cast<FastTMXLayer*>(child);
|
|
|
|
if (layer)
|
|
|
|
{
|
|
|
|
if (layer->hasTileAnimation())
|
|
|
|
{
|
|
|
|
if (enabled)
|
|
|
|
layer->getTileAnimManager()->startAll();
|
|
|
|
else
|
|
|
|
layer->getTileAnimManager()->stopAll();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-11 17:50:21 +08:00
|
|
|
NS_AX_END
|