2012-04-19 14:35:52 +08:00
|
|
|
/****************************************************************************
|
|
|
|
Copyright (c) 2009-2010 Ricardo Quesada
|
2014-01-07 11:25:07 +08:00
|
|
|
Copyright (c) 2010-2012 cocos2d-x.org
|
2012-04-19 14:35:52 +08:00
|
|
|
Copyright (c) 2011 Zynga Inc.
|
2016-08-05 09:42:15 +08:00
|
|
|
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
2012-04-19 14:35:52 +08:00
|
|
|
|
|
|
|
http://www.cocos2d-x.org
|
|
|
|
|
|
|
|
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.
|
|
|
|
****************************************************************************/
|
2014-08-28 17:03:29 +08:00
|
|
|
#include "2d/CCTMXTiledMap.h"
|
|
|
|
#include "2d/CCTMXXMLParser.h"
|
|
|
|
#include "2d/CCTMXLayer.h"
|
2014-04-27 01:11:22 +08:00
|
|
|
#include "2d/CCSprite.h"
|
2016-06-15 15:01:26 +08:00
|
|
|
#include "base/ccUTF8.h"
|
2014-04-09 22:30:49 +08:00
|
|
|
|
2012-04-19 14:35:52 +08:00
|
|
|
NS_CC_BEGIN
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
// implementation TMXTiledMap
|
2012-06-14 15:13:16 +08:00
|
|
|
|
2013-11-07 09:05:13 +08:00
|
|
|
TMXTiledMap * TMXTiledMap::create(const std::string& tmxFile)
|
2012-04-19 14:35:52 +08:00
|
|
|
{
|
2014-08-28 07:31:57 +08:00
|
|
|
TMXTiledMap *ret = new (std::nothrow) TMXTiledMap();
|
2013-11-07 09:05:13 +08:00
|
|
|
if (ret->initWithTMXFile(tmxFile))
|
2012-04-19 14:35:52 +08:00
|
|
|
{
|
2013-11-07 09:05:13 +08:00
|
|
|
ret->autorelease();
|
|
|
|
return ret;
|
2012-04-19 14:35:52 +08:00
|
|
|
}
|
2013-11-07 09:05:13 +08:00
|
|
|
CC_SAFE_DELETE(ret);
|
2013-11-29 11:36:42 +08:00
|
|
|
return nullptr;
|
2012-04-19 14:35:52 +08:00
|
|
|
}
|
|
|
|
|
2013-11-07 09:05:13 +08:00
|
|
|
TMXTiledMap* TMXTiledMap::createWithXML(const std::string& tmxString, const std::string& resourcePath)
|
2012-04-19 14:35:52 +08:00
|
|
|
{
|
2014-08-28 07:31:57 +08:00
|
|
|
TMXTiledMap *ret = new (std::nothrow) TMXTiledMap();
|
2013-11-07 09:05:13 +08:00
|
|
|
if (ret->initWithXML(tmxString, resourcePath))
|
2012-04-19 14:35:52 +08:00
|
|
|
{
|
2013-11-07 09:05:13 +08:00
|
|
|
ret->autorelease();
|
|
|
|
return ret;
|
2012-04-19 14:35:52 +08:00
|
|
|
}
|
2013-11-07 09:05:13 +08:00
|
|
|
CC_SAFE_DELETE(ret);
|
2013-11-29 11:36:42 +08:00
|
|
|
return nullptr;
|
2012-04-19 14:35:52 +08:00
|
|
|
}
|
|
|
|
|
2013-11-07 09:05:13 +08:00
|
|
|
bool TMXTiledMap::initWithTMXFile(const std::string& tmxFile)
|
2012-04-19 14:35:52 +08:00
|
|
|
{
|
2013-11-07 09:05:13 +08:00
|
|
|
CCASSERT(tmxFile.size()>0, "TMXTiledMap: tmx file should not be empty");
|
2015-11-12 09:49:49 +08:00
|
|
|
|
|
|
|
_tmxFile = tmxFile;
|
|
|
|
|
2013-07-12 14:47:36 +08:00
|
|
|
setContentSize(Size::ZERO);
|
2012-04-19 14:35:52 +08:00
|
|
|
|
2013-07-23 18:26:26 +08:00
|
|
|
TMXMapInfo *mapInfo = TMXMapInfo::create(tmxFile);
|
2012-04-19 14:35:52 +08:00
|
|
|
|
|
|
|
if (! mapInfo)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2013-11-29 11:36:42 +08:00
|
|
|
CCASSERT( !mapInfo->getTilesets().empty(), "TMXTiledMap: Map not found. Please check the filename.");
|
2012-04-19 14:35:52 +08:00
|
|
|
buildWithMapInfo(mapInfo);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-11-07 09:05:13 +08:00
|
|
|
bool TMXTiledMap::initWithXML(const std::string& tmxString, const std::string& resourcePath)
|
2012-04-19 14:35:52 +08:00
|
|
|
{
|
2015-11-12 09:49:49 +08:00
|
|
|
_tmxFile = tmxString;
|
|
|
|
|
2013-07-12 14:47:36 +08:00
|
|
|
setContentSize(Size::ZERO);
|
2012-04-19 14:35:52 +08:00
|
|
|
|
2013-07-23 18:26:26 +08:00
|
|
|
TMXMapInfo *mapInfo = TMXMapInfo::createWithXML(tmxString, resourcePath);
|
2012-04-19 14:35:52 +08:00
|
|
|
|
2013-11-29 11:36:42 +08:00
|
|
|
CCASSERT( !mapInfo->getTilesets().empty(), "TMXTiledMap: Map not found. Please check the filename.");
|
2012-04-19 14:35:52 +08:00
|
|
|
buildWithMapInfo(mapInfo);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
TMXTiledMap::TMXTiledMap()
|
2013-07-12 14:47:36 +08:00
|
|
|
:_mapSize(Size::ZERO)
|
|
|
|
,_tileSize(Size::ZERO)
|
2015-11-12 09:49:49 +08:00
|
|
|
,_tmxFile("")
|
|
|
|
, _tmxLayerNum(0)
|
2012-04-19 14:35:52 +08:00
|
|
|
{
|
|
|
|
}
|
2013-12-03 14:47:35 +08:00
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
TMXTiledMap::~TMXTiledMap()
|
2012-04-19 14:35:52 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
// private
|
2013-06-20 14:13:12 +08:00
|
|
|
TMXLayer * TMXTiledMap::parseLayer(TMXLayerInfo *layerInfo, TMXMapInfo *mapInfo)
|
2012-04-19 14:35:52 +08:00
|
|
|
{
|
2013-06-20 14:13:12 +08:00
|
|
|
TMXTilesetInfo *tileset = tilesetForLayer(layerInfo, mapInfo);
|
2015-05-20 11:29:52 +08:00
|
|
|
if (tileset == nullptr)
|
|
|
|
return nullptr;
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
TMXLayer *layer = TMXLayer::create(tileset, layerInfo, mapInfo);
|
2012-04-19 14:35:52 +08:00
|
|
|
|
2015-08-19 14:02:12 +08:00
|
|
|
if (nullptr != layer)
|
|
|
|
{
|
|
|
|
// tell the layerinfo to release the ownership of the tiles map.
|
|
|
|
layerInfo->_ownTiles = false;
|
|
|
|
layer->setupTiles();
|
|
|
|
}
|
2012-04-19 14:35:52 +08:00
|
|
|
|
|
|
|
return layer;
|
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
TMXTilesetInfo * TMXTiledMap::tilesetForLayer(TMXLayerInfo *layerInfo, TMXMapInfo *mapInfo)
|
2012-04-19 14:35:52 +08:00
|
|
|
{
|
2013-06-20 14:13:12 +08:00
|
|
|
Size size = layerInfo->_layerSize;
|
2013-11-29 11:36:42 +08:00
|
|
|
auto& tilesets = mapInfo->getTilesets();
|
2013-12-05 10:35:10 +08:00
|
|
|
if (tilesets.size()>0)
|
2012-04-19 14:35:52 +08:00
|
|
|
{
|
2013-11-29 11:36:42 +08:00
|
|
|
TMXTilesetInfo* tileset = nullptr;
|
|
|
|
for (auto iter = tilesets.crbegin(); iter != tilesets.crend(); ++iter)
|
2012-04-19 14:35:52 +08:00
|
|
|
{
|
2013-11-29 11:36:42 +08:00
|
|
|
tileset = *iter;
|
2012-04-19 14:35:52 +08:00
|
|
|
if (tileset)
|
|
|
|
{
|
2013-12-23 10:37:46 +08:00
|
|
|
for( int y=0; y < size.height; y++ )
|
2012-04-19 14:35:52 +08:00
|
|
|
{
|
2013-12-23 10:37:46 +08:00
|
|
|
for( int x=0; x < size.width; x++ )
|
2012-04-19 14:35:52 +08:00
|
|
|
{
|
2013-12-23 10:46:35 +08:00
|
|
|
int pos = static_cast<int>(x + size.width * y);
|
2013-12-23 10:37:46 +08:00
|
|
|
int gid = layerInfo->_tiles[ pos ];
|
2012-04-19 14:35:52 +08:00
|
|
|
|
|
|
|
// gid are stored in little endian.
|
|
|
|
// if host is big endian, then swap
|
|
|
|
//if( o == CFByteOrderBigEndian )
|
|
|
|
// gid = CFSwapInt32( gid );
|
|
|
|
/* We support little endian.*/
|
|
|
|
|
2014-08-30 03:54:24 +08:00
|
|
|
// FIXME:: gid == 0 --> empty tile
|
2012-04-19 14:35:52 +08:00
|
|
|
if( gid != 0 )
|
|
|
|
{
|
|
|
|
// Optimization: quick return
|
|
|
|
// if the layer is invalid (more than 1 tileset per layer) an CCAssert will be thrown later
|
2014-02-08 10:33:30 +08:00
|
|
|
if( (gid & kTMXFlippedMask) >= tileset->_firstGid )
|
2012-04-19 14:35:52 +08:00
|
|
|
return tileset;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If all the tiles are 0, return empty tileset
|
2013-06-15 14:03:30 +08:00
|
|
|
CCLOG("cocos2d: Warning: TMX Layer '%s' has no tiles", layerInfo->_name.c_str());
|
2013-11-29 11:36:42 +08:00
|
|
|
return nullptr;
|
2012-04-19 14:35:52 +08:00
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
void TMXTiledMap::buildWithMapInfo(TMXMapInfo* mapInfo)
|
2012-04-19 14:35:52 +08:00
|
|
|
{
|
2013-06-15 14:03:30 +08:00
|
|
|
_mapSize = mapInfo->getMapSize();
|
|
|
|
_tileSize = mapInfo->getTileSize();
|
|
|
|
_mapOrientation = mapInfo->getOrientation();
|
2012-04-19 14:35:52 +08:00
|
|
|
|
2013-06-15 14:03:30 +08:00
|
|
|
_objectGroups = mapInfo->getObjectGroups();
|
2012-04-19 14:35:52 +08:00
|
|
|
|
2013-06-15 14:03:30 +08:00
|
|
|
_properties = mapInfo->getProperties();
|
2012-04-19 14:35:52 +08:00
|
|
|
|
2013-06-15 14:03:30 +08:00
|
|
|
_tileProperties = mapInfo->getTileProperties();
|
2012-04-19 14:35:52 +08:00
|
|
|
|
2015-11-12 09:49:49 +08:00
|
|
|
int idx = 0;
|
2012-04-19 14:35:52 +08:00
|
|
|
|
2013-12-17 17:45:29 +08:00
|
|
|
auto& layers = mapInfo->getLayers();
|
2015-11-12 09:49:49 +08:00
|
|
|
for (const auto &layerInfo : layers) {
|
2015-05-20 11:29:52 +08:00
|
|
|
if (layerInfo->_visible) {
|
2013-11-29 11:36:42 +08:00
|
|
|
TMXLayer *child = parseLayer(layerInfo, mapInfo);
|
2015-05-20 11:29:52 +08:00
|
|
|
if (child == nullptr) {
|
|
|
|
idx++;
|
|
|
|
continue;
|
|
|
|
}
|
2015-12-09 15:07:58 +08:00
|
|
|
addChild(child, idx, idx);
|
2013-11-29 11:36:42 +08:00
|
|
|
// update content size with the max size
|
|
|
|
const Size& childSize = child->getContentSize();
|
|
|
|
Size currentSize = this->getContentSize();
|
2015-11-12 09:49:49 +08:00
|
|
|
currentSize.width = std::max(currentSize.width, childSize.width);
|
|
|
|
currentSize.height = std::max(currentSize.height, childSize.height);
|
2013-11-29 11:36:42 +08:00
|
|
|
this->setContentSize(currentSize);
|
2015-11-12 09:49:49 +08:00
|
|
|
|
2013-11-29 11:36:42 +08:00
|
|
|
idx++;
|
2012-04-19 14:35:52 +08:00
|
|
|
}
|
2013-12-20 05:34:41 +08:00
|
|
|
}
|
2015-11-12 09:49:49 +08:00
|
|
|
_tmxLayerNum = idx;
|
2012-04-19 14:35:52 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// public
|
2013-11-07 09:05:13 +08:00
|
|
|
TMXLayer * TMXTiledMap::getLayer(const std::string& layerName) const
|
2012-04-19 14:35:52 +08:00
|
|
|
{
|
2013-11-07 09:05:13 +08:00
|
|
|
CCASSERT(layerName.size() > 0, "Invalid layer name!");
|
2013-11-28 16:02:03 +08:00
|
|
|
|
|
|
|
for (auto& child : _children)
|
2012-04-19 14:35:52 +08:00
|
|
|
{
|
2013-11-28 16:02:03 +08:00
|
|
|
TMXLayer* layer = dynamic_cast<TMXLayer*>(child);
|
2012-04-19 14:35:52 +08:00
|
|
|
if(layer)
|
|
|
|
{
|
2013-11-07 09:05:13 +08:00
|
|
|
if(layerName.compare( layer->getLayerName()) == 0)
|
2012-04-19 14:35:52 +08:00
|
|
|
{
|
|
|
|
return layer;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// layer not found
|
2013-11-28 16:02:03 +08:00
|
|
|
return nullptr;
|
2012-04-19 14:35:52 +08:00
|
|
|
}
|
|
|
|
|
2013-11-07 09:05:13 +08:00
|
|
|
TMXObjectGroup * TMXTiledMap::getObjectGroup(const std::string& groupName) const
|
2012-04-19 14:35:52 +08:00
|
|
|
{
|
2013-11-07 09:05:13 +08:00
|
|
|
CCASSERT(groupName.size() > 0, "Invalid group name!");
|
2012-04-19 14:35:52 +08:00
|
|
|
|
2013-12-05 10:35:10 +08:00
|
|
|
if (_objectGroups.size()>0)
|
2012-04-19 14:35:52 +08:00
|
|
|
{
|
2013-11-29 11:36:42 +08:00
|
|
|
TMXObjectGroup* objectGroup = nullptr;
|
|
|
|
for (auto iter = _objectGroups.cbegin(); iter != _objectGroups.cend(); ++iter)
|
2012-04-19 14:35:52 +08:00
|
|
|
{
|
2013-11-29 11:36:42 +08:00
|
|
|
objectGroup = *iter;
|
2013-11-07 09:05:13 +08:00
|
|
|
if (objectGroup && objectGroup->getGroupName() == groupName)
|
2012-04-19 14:35:52 +08:00
|
|
|
{
|
|
|
|
return objectGroup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// objectGroup not found
|
2013-11-29 11:36:42 +08:00
|
|
|
return nullptr;
|
2012-04-19 14:35:52 +08:00
|
|
|
}
|
|
|
|
|
2013-12-03 14:47:35 +08:00
|
|
|
Value TMXTiledMap::getProperty(const std::string& propertyName) const
|
2012-04-19 14:35:52 +08:00
|
|
|
{
|
2013-12-03 14:47:35 +08:00
|
|
|
if (_properties.find(propertyName) != _properties.end())
|
|
|
|
return _properties.at(propertyName);
|
|
|
|
|
|
|
|
return Value();
|
2012-04-19 14:35:52 +08:00
|
|
|
}
|
|
|
|
|
2013-12-03 14:47:35 +08:00
|
|
|
Value TMXTiledMap::getPropertiesForGID(int GID) const
|
2012-04-19 14:35:52 +08:00
|
|
|
{
|
2013-12-03 14:47:35 +08:00
|
|
|
if (_tileProperties.find(GID) != _tileProperties.end())
|
|
|
|
return _tileProperties.at(GID);
|
|
|
|
|
|
|
|
return Value();
|
2012-04-19 14:35:52 +08:00
|
|
|
}
|
2013-12-13 06:30:22 +08:00
|
|
|
|
2014-02-01 06:57:26 +08:00
|
|
|
bool TMXTiledMap::getPropertiesForGID(int GID, Value** value)
|
|
|
|
{
|
|
|
|
if (_tileProperties.find(GID) != _tileProperties.end()) {
|
|
|
|
*value = &_tileProperties.at(GID);
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-13 06:30:22 +08:00
|
|
|
std::string TMXTiledMap::getDescription() const
|
|
|
|
{
|
2014-01-05 11:59:32 +08:00
|
|
|
return StringUtils::format("<TMXTiledMap | Tag = %d, Layers = %d", _tag, static_cast<int>(_children.size()));
|
2013-12-13 06:30:22 +08:00
|
|
|
}
|
|
|
|
|
2015-11-12 09:49:49 +08:00
|
|
|
int TMXTiledMap::getLayerNum()
|
|
|
|
{
|
|
|
|
return _tmxLayerNum;
|
|
|
|
}
|
|
|
|
|
2012-04-19 14:35:52 +08:00
|
|
|
NS_CC_END
|