mirror of https://github.com/axmolengine/axmol.git
fixed #69, complete CCTMXLayer
This commit is contained in:
parent
ac60be16e0
commit
92f2528ede
|
@ -452,6 +452,10 @@
|
|||
RelativePath=".\include\CCTileMapAtlas.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\CCTMXLayer.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\CCTMXObjectGroup.h"
|
||||
>
|
||||
|
@ -772,6 +776,10 @@
|
|||
RelativePath=".\tileMap_parallax_nodes\CCTileMapAtlas.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\tileMap_parallax_nodes\CCTMXLayer.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\tileMap_parallax_nodes\CCTMXObjectGroup.cpp"
|
||||
>
|
||||
|
|
|
@ -169,6 +169,21 @@ protected:
|
|||
|
||||
// all descendants: chlidren, gran children, etc...
|
||||
NSArray<CCSprite*> *m_pobDescendants;
|
||||
protected:
|
||||
/* IMPORTANT XXX IMPORTNAT:
|
||||
* These 2 methods can't be part of CCTMXLayer since they call [super add...], and CCSpriteSheet#add SHALL not be called
|
||||
*/
|
||||
|
||||
/* Adds a quad into the texture atlas but it won't be added into the children array.
|
||||
This method should be called only when you are dealing with very big AtlasSrite and when most of the CCSprite won't be updated.
|
||||
For example: a tile map (CCTMXMap) or a label with lots of characgers (BitmapFontAtlas)
|
||||
*/
|
||||
void addQuadFromSprite(CCSprite *sprite, unsigned int index);
|
||||
/* This is the opposite of "addQuadFromSprite.
|
||||
It add the sprite to the children and descendants array, but it doesn't update add it to the texture atlas
|
||||
*/
|
||||
CCSpriteSheet * addSpriteWithoutQuad(CCSprite*child, unsigned int z, int aTag);
|
||||
|
||||
};
|
||||
}//namespace cocos2d
|
||||
|
||||
|
|
|
@ -0,0 +1,168 @@
|
|||
/****************************************************************************
|
||||
Copyright (c) 2010 cocos2d-x.org
|
||||
|
||||
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.
|
||||
****************************************************************************/
|
||||
#ifndef __CCTMX_LAYER_H__
|
||||
#define __CCTMX_LAYER_H__
|
||||
#include "CCTMXObjectGroup.h"
|
||||
#include "CCAtlasNode.h"
|
||||
#include "CCSpriteSheet.h"
|
||||
#include "support/data_support/ccArray.h"
|
||||
namespace cocos2d {
|
||||
|
||||
class CCTMXMapInfo;
|
||||
class CCTMXLayerInfo;
|
||||
class CCTMXTilesetInfo;
|
||||
|
||||
/** CCTMXLayer represents the TMX layer.
|
||||
|
||||
It is a subclass of CCSpriteSheet. By default the tiles are rendered using a CCTextureAtlas.
|
||||
If you mofify a tile on runtime, then, that tile will become a CCSprite.
|
||||
The benefits of using CCSprite objects as tiles are:
|
||||
- tiles (CCSprite) can be rotated/scaled/moved with a nice API
|
||||
|
||||
If the layer contains a property named "cc_vertexz" with an integer (in can be positive or negative),
|
||||
then all the tiles belonging to the layer will use that value as their OpenGL vertex Z for depth.
|
||||
|
||||
On the other hand, if the "cc_vertexz" property has the "automatic" value, then the tiles will use an automatic vertex Z value.
|
||||
Also before drawing the tiles, GL_ALPHA_TEST will be enabled, and disabled after drawin them. The used alpha func will be:
|
||||
|
||||
glAlphaFunc( GL_GREATER, value )
|
||||
|
||||
"value" by default is 0, but you can change it from Tiled by adding the "cc_alpha_func" property to the layer.
|
||||
The value 0 should work for most cases, but if you have tiles that are semi-transparent, then you might want to use a differnt
|
||||
value, like 0.5.
|
||||
|
||||
For further information, please see the programming guide:
|
||||
|
||||
http://www.cocos2d-iphone.org/wiki/doku.php/prog_guide:tiled_maps
|
||||
|
||||
@since v0.8.1
|
||||
*/
|
||||
class CCX_DLL CCTMXLayer : public CCSpriteSheet
|
||||
{
|
||||
/** name of the layer */
|
||||
CCX_SYNTHESIZE(std::string, m_sLayerName, LayerName);
|
||||
/** size of the layer in tiles */
|
||||
CCX_SYNTHESIZE(CGSize, m_tLayerSize, LayerSize);
|
||||
/** size of the map's tile (could be differnt from the tile's size) */
|
||||
CCX_SYNTHESIZE(CGSize, m_tMapTileSize, MapTileSize);
|
||||
/** pointer to the map of tiles */
|
||||
CCX_SYNTHESIZE(unsigned int*, m_pTiles, Tiles);
|
||||
/** Tilset information for the layer */
|
||||
CCX_SYNTHESIZE(CCTMXTilesetInfo*, m_pTileSet, TileSet);
|
||||
/** Layer orientation, which is the same as the map orientation */
|
||||
CCX_SYNTHESIZE(int, m_nLayerOrientation, LayerOrientation);
|
||||
/** properties from the layer. They can be added using Tiled */
|
||||
CCX_SYNTHESIZE(StringToStringDictionary*, m_pProperties, Properties);
|
||||
public:
|
||||
CCTMXLayer();
|
||||
virtual ~CCTMXLayer();
|
||||
/** creates a CCTMXLayer with an tileset info, a layer info and a map info */
|
||||
static CCTMXLayer * layerWithTilesetInfo(CCTMXTilesetInfo *tilesetInfo, CCTMXLayerInfo *layerInfo, CCTMXMapInfo *mapInfo);
|
||||
/** initializes a CCTMXLayer with a tileset info, a layer info and a map info */
|
||||
bool initWithTilesetInfo(CCTMXTilesetInfo *tilesetInfo, CCTMXLayerInfo *layerInfo, CCTMXMapInfo *mapInfo);
|
||||
|
||||
/** dealloc the map that contains the tile position from memory.
|
||||
Unless you want to know at runtime the tiles positions, you can safely call this method.
|
||||
If you are going to call [layer tileGIDAt:] then, don't release the map
|
||||
*/
|
||||
void releaseMap();
|
||||
|
||||
/** returns the tile (CCSprite) at a given a tile coordinate.
|
||||
The returned CCSprite will be already added to the CCTMXLayer. Don't add it again.
|
||||
The CCSprite can be treated like any other CCSprite: rotated, scaled, translated, opacity, color, etc.
|
||||
You can remove either by calling:
|
||||
- [layer removeChild:sprite cleanup:cleanup];
|
||||
- or [layer removeTileAt:ccp(x,y)];
|
||||
*/
|
||||
CCSprite* tileAt(CGPoint tileCoordinate);
|
||||
|
||||
/** returns the tile gid at a given tile coordinate.
|
||||
if it returns 0, it means that the tile is empty.
|
||||
This method requires the the tile map has not been previously released (eg. don't call [layer releaseMap])
|
||||
*/
|
||||
unsigned int tileGIDAt(CGPoint tileCoordinate);
|
||||
|
||||
/** sets the tile gid (gid = tile global id) at a given tile coordinate.
|
||||
The Tile GID can be obtained by using the method "tileGIDAt" or by using the TMX editor -> Tileset Mgr +1.
|
||||
If a tile is already placed at that position, then it will be removed.
|
||||
*/
|
||||
void setTileGID(unsigned int gid, CGPoint tileCoordinate);
|
||||
|
||||
/** removes a tile at given tile coordinate */
|
||||
void removeTileAt(CGPoint tileCoordinate);
|
||||
|
||||
/** returns the position in pixels of a given tile coordinate */
|
||||
CGPoint positionAt(CGPoint tileCoordinate);
|
||||
|
||||
/** return the value for the specific property name */
|
||||
const char *propertyNamed(const char *propertyName);
|
||||
|
||||
/** Creates the tiles */
|
||||
void setupTiles();
|
||||
|
||||
/** CCTMXLayer doesn't support adding a CCSprite manually.
|
||||
@warning addchild:z:tag: is not supported on CCTMXLayer. Instead of setTileGID:at:/tileAt:
|
||||
*/
|
||||
CCNode * addChild(CCNode * child, int zOrder, int tag);
|
||||
// super method
|
||||
void removeChild(CCNode* child, bool cleanup);
|
||||
void draw();
|
||||
private:
|
||||
CGPoint positionForIsoAt(CGPoint pos);
|
||||
CGPoint positionForOrthoAt(CGPoint pos);
|
||||
CGPoint positionForHexAt(CGPoint pos);
|
||||
|
||||
CGPoint calculateLayerOffset(CGPoint offset);
|
||||
|
||||
/* optimization methos */
|
||||
CCSprite* appendTileForGID(unsigned int gid, CGPoint pos);
|
||||
CCSprite* insertTileForGID(unsigned int gid, CGPoint pos);
|
||||
CCSprite* updateTileForGID(unsigned int gid, CGPoint pos);
|
||||
|
||||
/* The layer recognizes some special properties, like cc_vertez */
|
||||
void parseInternalProperties();
|
||||
int vertexZForPos(CGPoint pos);
|
||||
|
||||
// index
|
||||
unsigned int atlasIndexForExistantZ(unsigned int z);
|
||||
unsigned int atlasIndexForNewZ(int z);
|
||||
protected:
|
||||
unsigned char m_cOpacity; // TMX Layer supports opacity
|
||||
|
||||
unsigned int m_uMinGID;
|
||||
unsigned int m_uMaxGID;
|
||||
|
||||
// Only used when vertexZ is used
|
||||
int m_nVertexZvalue;
|
||||
bool m_bUseAutomaticVertexZ;
|
||||
float m_fAlphaFuncValue;
|
||||
|
||||
// used for optimization
|
||||
CCSprite *m_pReusedTile;
|
||||
ccCArray *m_pAtlasIndexArray;
|
||||
};
|
||||
|
||||
}// namespace cocos2d
|
||||
#endif //__CCTMX_LAYER_H__
|
||||
|
|
@ -34,6 +34,7 @@ namespace cocos2d {
|
|||
|
||||
typedef std::map<std::string, std::string> StringToStringDictionary;
|
||||
typedef std::pair<std::string, std::string> StringToStringPair;
|
||||
/** only used in StringToStringDictionary, return "" if not found*/
|
||||
const char * valueForKey(std::string key, StringToStringDictionary *dict);
|
||||
|
||||
/** CCTMXObjectGroup represents the TMX object group.
|
||||
|
|
|
@ -56,7 +56,7 @@ namespace cocos2d {
|
|||
/** creates a CCTileMap with a tile file (atlas) with a map file and the width and height of each tile.
|
||||
The tile file will be loaded using the TextureMgr.
|
||||
*/
|
||||
CCTileMapAtlas * tileMapAtlasWithTileFile(const char *tile, const char *mapFile, int tileWidth, int tileHeight);
|
||||
static CCTileMapAtlas * tileMapAtlasWithTileFile(const char *tile, const char *mapFile, int tileWidth, int tileHeight);
|
||||
/** initializes a CCTileMap with a tile file (atlas) with a map file and the width and height of each tile.
|
||||
The file will be loaded using the TextureMgr.
|
||||
*/
|
||||
|
|
|
@ -596,4 +596,60 @@ void CCSpriteSheet::setTexture(CCTexture2D *texture)
|
|||
{
|
||||
m_pobTextureAtlas->setTexture(texture);
|
||||
}
|
||||
|
||||
// CCSpriteSheet Extension
|
||||
//implementation CCSpriteSheet (TMXTiledMapExtension)
|
||||
|
||||
void CCSpriteSheet::addQuadFromSprite(CCSprite *sprite, unsigned int index)
|
||||
{
|
||||
NSAssert( sprite != NULL, "Argument must be non-nil");
|
||||
/// @todo NSAssert( [sprite isKindOfClass:[CCSprite class]], @"CCSpriteSheet only supports CCSprites as children");
|
||||
|
||||
while(index >= m_pobTextureAtlas->getCapacity() || m_pobTextureAtlas->getCapacity() == m_pobTextureAtlas->getTotalQuads())
|
||||
{
|
||||
this->increaseAtlasCapacity();
|
||||
}
|
||||
//
|
||||
// update the quad directly. Don't add the sprite to the scene graph
|
||||
//
|
||||
sprite->useSpriteSheetRender(this);
|
||||
sprite->setAtlasIndex(index);
|
||||
|
||||
ccV3F_C4B_T2F_Quad quad = sprite->getQuad();
|
||||
m_pobTextureAtlas->insertQuad(&quad, index);
|
||||
|
||||
// XXX: updateTransform will update the textureAtlas too using updateQuad.
|
||||
// XXX: so, it should be AFTER the insertQuad
|
||||
sprite->updateTransform();
|
||||
}
|
||||
|
||||
CCSpriteSheet * CCSpriteSheet::addSpriteWithoutQuad(CCSprite*child, unsigned int z, int aTag)
|
||||
{
|
||||
NSAssert( child != NULL, "Argument must be non-nil");
|
||||
/// @todo NSAssert( [child isKindOfClass:[CCSprite class]], @"CCSpriteSheet only supports CCSprites as children");
|
||||
|
||||
// quad index is Z
|
||||
child->setAtlasIndex(z);
|
||||
|
||||
// XXX: optimize with a binary search
|
||||
int i=0;
|
||||
if (m_pobDescendants && m_pobDescendants->count() > 0)
|
||||
{
|
||||
NSMutableArray<CCSprite*>::NSMutableArrayIterator iter;
|
||||
for (iter = m_pobDescendants->begin(); iter != m_pobDescendants->end(); ++iter)
|
||||
{
|
||||
// fast dispatch
|
||||
if (!(*iter) || (*iter)->getAtlasIndex() >=z)
|
||||
{
|
||||
break;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
m_pobDescendants->insertObjectAtIndex(child, i);
|
||||
|
||||
// IMPORTANT: Call super, and not self. Avoid adding it to the texture atlas array
|
||||
__super::addChild(child, z, aTag);
|
||||
return this;
|
||||
}
|
||||
}//namespace cocos2d
|
||||
|
|
|
@ -0,0 +1,632 @@
|
|||
/****************************************************************************
|
||||
Copyright (c) 2010 cocos2d-x.org
|
||||
|
||||
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.
|
||||
****************************************************************************/
|
||||
#include "CCLayer.h"
|
||||
#include "CCTMXLayer.h"
|
||||
#include "CCTMXXMLParser.h"
|
||||
#include "CCSprite.h"
|
||||
#include "CCSpriteSheet.h"
|
||||
#include "CCTextureCache.h"
|
||||
#include "CGPointExtension.h"
|
||||
|
||||
namespace cocos2d {
|
||||
|
||||
|
||||
// CCTMXLayer - init & alloc & dealloc
|
||||
CCTMXLayer * CCTMXLayer::layerWithTilesetInfo(CCTMXTilesetInfo *tilesetInfo, CCTMXLayerInfo *layerInfo, CCTMXMapInfo *mapInfo)
|
||||
{
|
||||
CCTMXLayer *pRet = new CCTMXLayer();
|
||||
if (pRet->initWithTilesetInfo(tilesetInfo, layerInfo, mapInfo))
|
||||
{
|
||||
pRet->autorelease();
|
||||
return pRet;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
bool CCTMXLayer::initWithTilesetInfo(CCTMXTilesetInfo *tilesetInfo, CCTMXLayerInfo *layerInfo, CCTMXMapInfo *mapInfo)
|
||||
{
|
||||
// XXX: is 35% a good estimate ?
|
||||
CGSize size = layerInfo->m_tLayerSize;
|
||||
float totalNumberOfTiles = size.width * size.height;
|
||||
float capacity = totalNumberOfTiles * 0.35f + 1; // 35 percent is occupied ?
|
||||
|
||||
CCTexture2D *texture = NULL;
|
||||
if( tilesetInfo )
|
||||
{
|
||||
texture = CCTextureCache::sharedTextureCache()->addImage(tilesetInfo->m_sSourceImage.c_str());
|
||||
}
|
||||
|
||||
if (__super::initWithTexture(texture, (unsigned int)capacity))
|
||||
{
|
||||
// layerInfo
|
||||
m_sLayerName = layerInfo->m_sName;
|
||||
m_tLayerSize = layerInfo->m_tLayerSize;
|
||||
m_pTiles = layerInfo->m_pTiles;
|
||||
m_uMinGID = layerInfo->m_uMinGID;
|
||||
m_uMaxGID = layerInfo->m_uMaxGID;
|
||||
m_cOpacity = layerInfo->m_cOpacity;
|
||||
if (!layerInfo->m_pProperties && layerInfo->m_pProperties->size()>0)
|
||||
{
|
||||
StringToStringDictionary::iterator it;
|
||||
for (it = layerInfo->m_pProperties->begin(); it != layerInfo->m_pProperties->end(); ++it)
|
||||
{
|
||||
m_pProperties->insert(*it);
|
||||
}
|
||||
}
|
||||
|
||||
// tilesetInfo
|
||||
m_pTileSet = tilesetInfo;
|
||||
|
||||
// mapInfo
|
||||
m_tMapTileSize = mapInfo->getTileSize();
|
||||
m_nLayerOrientation = mapInfo->getOrientation();
|
||||
|
||||
// offset (after layer orientation is set);
|
||||
CGPoint offset = this->calculateLayerOffset(layerInfo->m_tOffset);
|
||||
this->setPosition(offset);
|
||||
|
||||
m_pAtlasIndexArray = ccCArrayNew((unsigned int)totalNumberOfTiles);
|
||||
|
||||
this->setContentSize(CGSizeMake(m_tLayerSize.width * m_tMapTileSize.width, m_tLayerSize.height * m_tMapTileSize.height));
|
||||
|
||||
m_bUseAutomaticVertexZ = false;
|
||||
m_nVertexZvalue = 0;
|
||||
m_fAlphaFuncValue = 0;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
CCTMXLayer::CCTMXLayer()
|
||||
:m_pTiles(NULL)
|
||||
,m_pTileSet(NULL)
|
||||
,m_pProperties(NULL)
|
||||
,m_pReusedTile(NULL)
|
||||
,m_pAtlasIndexArray(NULL)
|
||||
{}
|
||||
CCTMXLayer::~CCTMXLayer()
|
||||
{
|
||||
CCX_SAFE_RELEASE(m_pTileSet);
|
||||
CCX_SAFE_RELEASE(m_pReusedTile);
|
||||
if (m_pProperties)
|
||||
{
|
||||
m_pProperties->clear();
|
||||
delete m_pProperties;
|
||||
}
|
||||
|
||||
if( m_pAtlasIndexArray )
|
||||
{
|
||||
ccCArrayFree(m_pAtlasIndexArray);
|
||||
m_pAtlasIndexArray = NULL;
|
||||
}
|
||||
|
||||
if( m_pTiles )
|
||||
{
|
||||
delete [] m_pTiles;
|
||||
m_pTiles = NULL;
|
||||
}
|
||||
}
|
||||
void CCTMXLayer::releaseMap()
|
||||
{
|
||||
if( m_pTiles )
|
||||
{
|
||||
delete [] m_pTiles;
|
||||
m_pTiles = NULL;
|
||||
}
|
||||
|
||||
if( m_pAtlasIndexArray )
|
||||
{
|
||||
ccCArrayFree(m_pAtlasIndexArray);
|
||||
m_pAtlasIndexArray = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// CCTMXLayer - setup Tiles
|
||||
void CCTMXLayer::setupTiles()
|
||||
{
|
||||
// Optimization: quick hack that sets the image size on the tileset
|
||||
m_pTileSet->m_tImageSize = m_pobTextureAtlas->getTexture()->getContentSize();
|
||||
|
||||
// By default all the tiles are aliased
|
||||
// pros:
|
||||
// - easier to render
|
||||
// cons:
|
||||
// - difficult to scale / rotate / etc.
|
||||
m_pobTextureAtlas->getTexture()->setAliasTexParameters();
|
||||
|
||||
// CFByteOrder o = CFByteOrderGetCurrent();
|
||||
|
||||
// Parse cocos2d properties
|
||||
this->parseInternalProperties();
|
||||
|
||||
for( unsigned int y=0; y < m_tLayerSize.height; y++ )
|
||||
{
|
||||
for( unsigned int x=0; x < m_tLayerSize.width; x++ )
|
||||
{
|
||||
unsigned int pos = x + (unsigned int)m_tLayerSize.width * y;
|
||||
unsigned int gid = m_pTiles[ pos ];
|
||||
|
||||
// gid are stored in little endian.
|
||||
// if host is big endian, then swap
|
||||
//if( o == CFByteOrderBigEndian )
|
||||
// gid = CFSwapInt32( gid );
|
||||
/* We support little endian.*/
|
||||
|
||||
// XXX: gid == 0 --> empty tile
|
||||
if( gid != 0 )
|
||||
{
|
||||
this->appendTileForGID(gid, ccp((float)x, (float)y));
|
||||
|
||||
// Optimization: update min and max GID rendered by the layer
|
||||
m_uMinGID = MIN(gid, m_uMinGID);
|
||||
m_uMaxGID = MAX(gid, m_uMaxGID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NSAssert( m_uMaxGID >= m_pTileSet->m_uFirstGid &&
|
||||
m_uMinGID >= m_pTileSet->m_uFirstGid, "TMX: Only 1 tilset per layer is supported");
|
||||
}
|
||||
|
||||
// CCTMXLayer - Properties
|
||||
const char *CCTMXLayer::propertyNamed(const char *propertyName)
|
||||
{
|
||||
return valueForKey(propertyName, m_pProperties);
|
||||
}
|
||||
void CCTMXLayer::parseInternalProperties()
|
||||
{
|
||||
// if cc_vertex=automatic, then tiles will be rendered using vertexz
|
||||
|
||||
std::string vertexz = propertyNamed("cc_vertexz");
|
||||
if( vertexz != "" )
|
||||
{
|
||||
if( vertexz == "automatic" )
|
||||
{
|
||||
m_bUseAutomaticVertexZ = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_nVertexZvalue = atoi(vertexz.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
std::string alphaFuncVal = propertyNamed("cc_alpha_func");
|
||||
m_fAlphaFuncValue = (float)atof(alphaFuncVal.c_str());
|
||||
}
|
||||
|
||||
// CCTMXLayer - obtaining tiles/gids
|
||||
CCSprite * CCTMXLayer::tileAt(CGPoint pos)
|
||||
{
|
||||
NSAssert( pos.x < m_tLayerSize.width && pos.y < m_tLayerSize.height && pos.x >=0 && pos.y >=0, "TMXLayer: invalid position");
|
||||
NSAssert( m_pTiles && m_pAtlasIndexArray, "TMXLayer: the tiles map has been released");
|
||||
|
||||
CCSprite *tile = NULL;
|
||||
unsigned int gid = this->tileGIDAt(pos);
|
||||
|
||||
// if GID == 0, then no tile is present
|
||||
if( gid )
|
||||
{
|
||||
int z = (int)(pos.x + pos.y * m_tLayerSize.width);
|
||||
tile = (CCSprite*) this->getChildByTag(z);
|
||||
|
||||
// tile not created yet. create it
|
||||
if( ! tile )
|
||||
{
|
||||
CGRect rect = m_pTileSet->rectForGID(gid);
|
||||
tile = new CCSprite();
|
||||
tile->initWithSpriteSheet(this, rect);
|
||||
tile->setPosition(positionAt(pos));
|
||||
tile->setVertexZ((float)vertexZForPos(pos));
|
||||
tile->setAnchorPoint(CGPointZero);
|
||||
tile->setOpacity(m_cOpacity);
|
||||
|
||||
unsigned int indexForZ = atlasIndexForExistantZ(z);
|
||||
this->addSpriteWithoutQuad(tile, indexForZ, z);
|
||||
tile->release();
|
||||
}
|
||||
}
|
||||
return tile;
|
||||
}
|
||||
unsigned int CCTMXLayer::tileGIDAt(CGPoint pos)
|
||||
{
|
||||
NSAssert( pos.x < m_tLayerSize.width && pos.y < m_tLayerSize.height && pos.x >=0 && pos.y >=0, "TMXLayer: invalid position");
|
||||
NSAssert( m_pTiles && m_pAtlasIndexArray, "TMXLayer: the tiles map has been released");
|
||||
|
||||
int idx = (int)(pos.x + pos.y * m_tLayerSize.width);
|
||||
return m_pTiles[ idx ];
|
||||
}
|
||||
|
||||
// CCTMXLayer - adding helper methods
|
||||
CCSprite * CCTMXLayer::insertTileForGID(unsigned int gid, CGPoint pos)
|
||||
{
|
||||
CGRect rect = m_pTileSet->rectForGID(gid);
|
||||
|
||||
int z = (int)(pos.x + pos.y * m_tLayerSize.width);
|
||||
|
||||
if( ! m_pReusedTile )
|
||||
{
|
||||
m_pReusedTile = new CCSprite();
|
||||
m_pReusedTile->initWithSpriteSheet(this, rect);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pReusedTile->initWithSpriteSheet(this, rect);
|
||||
}
|
||||
m_pReusedTile->setPosition(positionAt(pos));
|
||||
m_pReusedTile->setVertexZ((float)vertexZForPos(pos));
|
||||
m_pReusedTile->setAnchorPoint(CGPointZero);
|
||||
m_pReusedTile->setOpacity(m_cOpacity);
|
||||
|
||||
// get atlas index
|
||||
unsigned int indexForZ = atlasIndexForNewZ(z);
|
||||
|
||||
// Optimization: add the quad without adding a child
|
||||
this->addQuadFromSprite(m_pReusedTile, indexForZ);
|
||||
|
||||
// insert it into the local atlasindex array
|
||||
ccCArrayInsertValueAtIndex(m_pAtlasIndexArray, (void*)z, indexForZ);
|
||||
|
||||
// update possible children
|
||||
if (m_pChildren && m_pChildren->count()>0)
|
||||
{
|
||||
NSMutableArray<CCNode*>::NSMutableArrayIterator it;
|
||||
CCSprite *pSprite = NULL;
|
||||
for (it = m_pChildren->begin(); it != m_pChildren->end(); ++it)
|
||||
{
|
||||
pSprite = (CCSprite*)(*it);
|
||||
if (pSprite)
|
||||
{
|
||||
unsigned int ai = pSprite->getAtlasIndex();
|
||||
if ( ai >= indexForZ )
|
||||
{
|
||||
pSprite->setAtlasIndex(ai+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
m_pTiles[z] = gid;
|
||||
return m_pReusedTile;
|
||||
}
|
||||
CCSprite * CCTMXLayer::updateTileForGID(unsigned int gid, CGPoint pos)
|
||||
{
|
||||
CGRect rect = m_pTileSet->rectForGID(gid);
|
||||
int z = (int)(pos.x + pos.y * m_tLayerSize.width);
|
||||
|
||||
if( ! m_pReusedTile )
|
||||
{
|
||||
m_pReusedTile = new CCSprite();
|
||||
m_pReusedTile->initWithSpriteSheet(this, rect);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pReusedTile->initWithSpriteSheet(this, rect);
|
||||
}
|
||||
|
||||
m_pReusedTile->setPosition(positionAt(pos));
|
||||
m_pReusedTile->setVertexZ((float)vertexZForPos(pos));
|
||||
m_pReusedTile->setAnchorPoint(CGPointZero);
|
||||
m_pReusedTile->setOpacity(m_cOpacity);
|
||||
|
||||
// get atlas index
|
||||
unsigned int indexForZ = atlasIndexForExistantZ(z);
|
||||
m_pReusedTile->setAtlasIndex(indexForZ);
|
||||
m_pReusedTile->updateTransform();
|
||||
m_pTiles[z] = gid;
|
||||
|
||||
return m_pReusedTile;
|
||||
}
|
||||
|
||||
// used only when parsing the map. useless after the map was parsed
|
||||
// since lot's of assumptions are no longer true
|
||||
CCSprite * CCTMXLayer::appendTileForGID(unsigned int gid, CGPoint pos)
|
||||
{
|
||||
CGRect rect = m_pTileSet->rectForGID(gid);
|
||||
|
||||
int z = (int)(pos.x + pos.y * m_tLayerSize.width);
|
||||
|
||||
if( ! m_pReusedTile )
|
||||
{
|
||||
m_pReusedTile = new CCSprite();
|
||||
m_pReusedTile->initWithSpriteSheet(this, rect);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pReusedTile->initWithSpriteSheet(this, rect);
|
||||
}
|
||||
|
||||
m_pReusedTile->setPosition(positionAt(pos));
|
||||
m_pReusedTile->setVertexZ((float)vertexZForPos(pos));
|
||||
m_pReusedTile->setAnchorPoint(CGPointZero);
|
||||
m_pReusedTile->setOpacity(m_cOpacity);
|
||||
|
||||
// optimization:
|
||||
// The difference between appendTileForGID and insertTileforGID is that append is faster, since
|
||||
// it appends the tile at the end of the texture atlas
|
||||
unsigned int indexForZ = m_pAtlasIndexArray->num;
|
||||
|
||||
// don't add it using the "standard" way.
|
||||
addQuadFromSprite(m_pReusedTile, indexForZ);
|
||||
|
||||
// append should be after addQuadFromSprite since it modifies the quantity values
|
||||
ccCArrayInsertValueAtIndex(m_pAtlasIndexArray, (void*)z, indexForZ);
|
||||
|
||||
return m_pReusedTile;
|
||||
}
|
||||
|
||||
// CCTMXLayer - atlasIndex and Z
|
||||
int compareInts(const void * a, const void * b)
|
||||
{
|
||||
return ( *(int*)a - *(int*)b );
|
||||
}
|
||||
unsigned int CCTMXLayer::atlasIndexForExistantZ(unsigned int z)
|
||||
{
|
||||
int key=z;
|
||||
int *item = (int*)bsearch((void*)&key, (void*)&m_pAtlasIndexArray->arr[0], m_pAtlasIndexArray->num, sizeof(void*), compareInts);
|
||||
|
||||
NSAssert( item, "TMX atlas index not found. Shall not happen");
|
||||
|
||||
int index = ((int)item - (int)m_pAtlasIndexArray->arr) / sizeof(void*);
|
||||
return index;
|
||||
}
|
||||
unsigned int CCTMXLayer::atlasIndexForNewZ(int z)
|
||||
{
|
||||
// XXX: This can be improved with a sort of binary search
|
||||
unsigned int i=0;
|
||||
for( i=0; i< m_pAtlasIndexArray->num ; i++)
|
||||
{
|
||||
int val = (int) m_pAtlasIndexArray->arr[i];
|
||||
if( z < val )
|
||||
break;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
// CCTMXLayer - adding / remove tiles
|
||||
void CCTMXLayer::setTileGID(unsigned int gid, CGPoint pos)
|
||||
{
|
||||
NSAssert( pos.x < m_tLayerSize.width && pos.y < m_tLayerSize.height && pos.x >=0 && pos.y >=0, "TMXLayer: invalid position");
|
||||
NSAssert( m_pTiles && m_pAtlasIndexArray, "TMXLayer: the tiles map has been released");
|
||||
|
||||
unsigned int currentGID = tileGIDAt(pos);
|
||||
|
||||
if( currentGID != gid )
|
||||
{
|
||||
// setting gid=0 is equal to remove the tile
|
||||
if( gid == 0 )
|
||||
{
|
||||
removeTileAt(pos);
|
||||
}
|
||||
|
||||
// empty tile. create a new one
|
||||
else if( currentGID == 0 )
|
||||
{
|
||||
insertTileForGID(gid, pos);
|
||||
}
|
||||
|
||||
// modifying an existing tile with a non-empty tile
|
||||
else
|
||||
{
|
||||
unsigned int z = (unsigned int)(pos.x + pos.y * m_tLayerSize.width);
|
||||
CCSprite *sprite = (CCSprite*)getChildByTag(z);
|
||||
if( sprite )
|
||||
{
|
||||
CGRect rect = m_pTileSet->rectForGID(gid);
|
||||
sprite->setTextureRect(rect);
|
||||
m_pTiles[z] = gid;
|
||||
}
|
||||
else
|
||||
{
|
||||
updateTileForGID(gid, pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
CCNode * CCTMXLayer::addChild(CCNode * child, int zOrder, int tag)
|
||||
{
|
||||
NSAssert(0, "addChild: is not supported on CCTMXLayer. Instead use setTileGID:at:/tileAt:");
|
||||
return NULL;
|
||||
}
|
||||
void CCTMXLayer::removeChild(CCNode* node, bool cleanup)
|
||||
{
|
||||
CCSprite *sprite = (CCSprite*)node;
|
||||
// allows removing nil objects
|
||||
if( ! sprite )
|
||||
return;
|
||||
|
||||
NSAssert( m_pChildren->containsObject(sprite), "Tile does not belong to TMXLayer");
|
||||
|
||||
unsigned int atlasIndex = sprite->getAtlasIndex();
|
||||
unsigned int zz = (unsigned int) m_pAtlasIndexArray->arr[atlasIndex];
|
||||
m_pTiles[zz] = 0;
|
||||
ccCArrayRemoveValueAtIndex(m_pAtlasIndexArray, atlasIndex);
|
||||
__super::removeChild(sprite, cleanup);
|
||||
}
|
||||
void CCTMXLayer::removeTileAt(CGPoint pos)
|
||||
{
|
||||
NSAssert( pos.x < m_tLayerSize.width && pos.y < m_tLayerSize.height && pos.x >=0 && pos.y >=0, "TMXLayer: invalid position");
|
||||
NSAssert( m_pTiles && m_pAtlasIndexArray, "TMXLayer: the tiles map has been released");
|
||||
|
||||
unsigned int gid = tileGIDAt(pos);
|
||||
|
||||
if( gid )
|
||||
{
|
||||
unsigned int z = (unsigned int)(pos.x + pos.y * m_tLayerSize.width);
|
||||
unsigned atlasIndex = atlasIndexForExistantZ(z);
|
||||
|
||||
// remove tile from GID map
|
||||
m_pTiles[z] = 0;
|
||||
|
||||
// remove tile from atlas position array
|
||||
ccCArrayRemoveValueAtIndex(m_pAtlasIndexArray, atlasIndex);
|
||||
|
||||
// remove it from sprites and/or texture atlas
|
||||
CCSprite *sprite = (CCSprite*)getChildByTag(z);
|
||||
if( sprite )
|
||||
{
|
||||
__super::removeChild(sprite, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pobTextureAtlas->removeQuadAtIndex(atlasIndex);
|
||||
|
||||
// update possible children
|
||||
if (m_pChildren && m_pChildren->count()>0)
|
||||
{
|
||||
NSMutableArray<CCNode*>::NSMutableArrayIterator it;
|
||||
CCSprite *pSprite = NULL;
|
||||
for (it = m_pChildren->begin(); it != m_pChildren->end(); ++it)
|
||||
{
|
||||
pSprite = (CCSprite*)(*it);
|
||||
if (pSprite)
|
||||
{
|
||||
unsigned int ai = pSprite->getAtlasIndex();
|
||||
if ( ai >= atlasIndex )
|
||||
{
|
||||
pSprite->setAtlasIndex(ai-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Possible oritentations of the TMX map */
|
||||
enum
|
||||
{
|
||||
/** Orthogonal orientation */
|
||||
CCTMXOrientationOrtho,
|
||||
|
||||
/** Hexagonal orientation */
|
||||
CCTMXOrientationHex,
|
||||
|
||||
/** Isometric orientation */
|
||||
CCTMXOrientationIso,
|
||||
};/// @todo to be deleted
|
||||
//CCTMXLayer - obtaining positions, offset
|
||||
CGPoint CCTMXLayer::calculateLayerOffset(CGPoint pos)
|
||||
{
|
||||
CGPoint ret = CGPointZero;
|
||||
switch( m_nLayerOrientation )
|
||||
{
|
||||
case CCTMXOrientationOrtho:
|
||||
ret = ccp( pos.x * m_tMapTileSize.width, -pos.y *m_tMapTileSize.height);
|
||||
break;
|
||||
case CCTMXOrientationIso:
|
||||
ret = ccp( (m_tMapTileSize.width /2) * (pos.x - pos.y),
|
||||
(m_tMapTileSize.height /2 ) * (-pos.x - pos.y) );
|
||||
break;
|
||||
case CCTMXOrientationHex:
|
||||
NSAssert(CGPoint::CGPointEqualToPoint(pos, CGPointZero), "offset for hexagonal map not implemented yet");
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
CGPoint CCTMXLayer::positionAt(CGPoint pos)
|
||||
{
|
||||
CGPoint ret = CGPointZero;
|
||||
switch( m_nLayerOrientation )
|
||||
{
|
||||
case CCTMXOrientationOrtho:
|
||||
ret = positionForOrthoAt(pos);
|
||||
break;
|
||||
case CCTMXOrientationIso:
|
||||
ret = positionForIsoAt(pos);
|
||||
break;
|
||||
case CCTMXOrientationHex:
|
||||
ret = positionForHexAt(pos);
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
CGPoint CCTMXLayer::positionForOrthoAt(CGPoint pos)
|
||||
{
|
||||
float x = pos.x * m_tMapTileSize.width + 0.49f;
|
||||
float y = (m_tLayerSize.height - pos.y - 1) * m_tMapTileSize.height + 0.49f;
|
||||
return ccp(x,y);
|
||||
}
|
||||
CGPoint CCTMXLayer::positionForIsoAt(CGPoint pos)
|
||||
{
|
||||
float x = m_tMapTileSize.width /2 * ( m_tLayerSize.width + pos.x - pos.y - 1) + 0.49f;
|
||||
float y = m_tMapTileSize.height /2 * (( m_tLayerSize.height * 2 - pos.x - pos.y) - 2) + 0.49f;
|
||||
return ccp(x, y);
|
||||
}
|
||||
CGPoint CCTMXLayer::positionForHexAt(CGPoint pos)
|
||||
{
|
||||
float diffY = 0;
|
||||
if( (int)pos.x % 2 == 1 )
|
||||
diffY = -m_tMapTileSize.height/2 ;
|
||||
|
||||
float x = pos.x * m_tMapTileSize.width*3/4 + 0.49f;
|
||||
float y = (m_tLayerSize.height - pos.y - 1) * m_tMapTileSize.height + diffY + 0.49f;
|
||||
return ccp(x,y);
|
||||
}
|
||||
int CCTMXLayer::vertexZForPos(CGPoint pos)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned int maxVal = 0;
|
||||
if( m_bUseAutomaticVertexZ )
|
||||
{
|
||||
switch( m_nLayerOrientation )
|
||||
{
|
||||
case CCTMXOrientationIso:
|
||||
maxVal = (unsigned int)(m_tLayerSize.width + m_tLayerSize.height);
|
||||
ret = (int)(-(maxVal - (pos.x + pos.y)));
|
||||
break;
|
||||
case CCTMXOrientationOrtho:
|
||||
ret = (int)(-(m_tLayerSize.height-pos.y));
|
||||
break;
|
||||
case CCTMXOrientationHex:
|
||||
NSAssert(0, "TMX Hexa zOrder not supported");
|
||||
break;
|
||||
default:
|
||||
NSAssert(0, "TMX invalid value");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = m_nVertexZvalue;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// CCTMXLayer - draw
|
||||
void CCTMXLayer::draw()
|
||||
{
|
||||
if( m_bUseAutomaticVertexZ )
|
||||
{
|
||||
glEnable(GL_ALPHA_TEST);
|
||||
glAlphaFunc(GL_GREATER, m_fAlphaFuncValue);
|
||||
}
|
||||
|
||||
__super::draw();
|
||||
|
||||
if( m_bUseAutomaticVertexZ )
|
||||
{
|
||||
glDisable(GL_ALPHA_TEST);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}// namespace cocos2d
|
||||
|
|
@ -33,7 +33,7 @@ namespace cocos2d {
|
|||
CCTileMapAtlas * CCTileMapAtlas::tileMapAtlasWithTileFile(const char *tile, const char *mapFile, int tileWidth, int tileHeight)
|
||||
{
|
||||
CCTileMapAtlas *pRet = new CCTileMapAtlas();
|
||||
if (initWithTileFile(tile, mapFile, tileWidth, tileHeight))
|
||||
if (pRet->initWithTileFile(tile, mapFile, tileWidth, tileHeight))
|
||||
{
|
||||
pRet->autorelease();
|
||||
return pRet;
|
||||
|
|
Loading…
Reference in New Issue