issue #4437: add new tmx.

This commit is contained in:
boyu0 2014-06-06 16:15:46 +08:00
parent bd00e17190
commit a8a5f6b230
6 changed files with 1592 additions and 0 deletions

View File

@ -1775,6 +1775,14 @@
B3AF01A31842FBA400A98B85 /* b2MotorJoint.h in Headers */ = {isa = PBXBuildFile; fileRef = B3AF019F1842FBA400A98B85 /* b2MotorJoint.h */; };
B3B12A5A17E7F44000026B4A /* libchipmunk Mac.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A03F2CB81780BD04006731B9 /* libchipmunk Mac.a */; };
B3B12A5B17E7F45C00026B4A /* libchipmunk iOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A07A4F3B178387670073F6A7 /* libchipmunk iOS.a */; };
C0940CAC19419BDA00B8BB48 /* CCTMXLayer2.h in Headers */ = {isa = PBXBuildFile; fileRef = C0940CA819419BDA00B8BB48 /* CCTMXLayer2.h */; };
C0940CAD19419BDA00B8BB48 /* CCTMXLayer2.h in Headers */ = {isa = PBXBuildFile; fileRef = C0940CA819419BDA00B8BB48 /* CCTMXLayer2.h */; };
C0940CAE19419BDA00B8BB48 /* CCTMXTiledMap2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C0940CA919419BDA00B8BB48 /* CCTMXTiledMap2.cpp */; };
C0940CAF19419BDA00B8BB48 /* CCTMXTiledMap2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C0940CA919419BDA00B8BB48 /* CCTMXTiledMap2.cpp */; };
C0940CB019419BDA00B8BB48 /* CCTMXTiledMap2.h in Headers */ = {isa = PBXBuildFile; fileRef = C0940CAA19419BDA00B8BB48 /* CCTMXTiledMap2.h */; };
C0940CB119419BDA00B8BB48 /* CCTMXTiledMap2.h in Headers */ = {isa = PBXBuildFile; fileRef = C0940CAA19419BDA00B8BB48 /* CCTMXTiledMap2.h */; };
C0940CB219419BDA00B8BB48 /* CCTMXLayer2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C0940CAB19419BDA00B8BB48 /* CCTMXLayer2.cpp */; };
C0940CB319419BDA00B8BB48 /* CCTMXLayer2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C0940CAB19419BDA00B8BB48 /* CCTMXLayer2.cpp */; };
ED9C6A9418599AD8000A5232 /* CCNodeGrid.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ED9C6A9218599AD8000A5232 /* CCNodeGrid.cpp */; };
ED9C6A9518599AD8000A5232 /* CCNodeGrid.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ED9C6A9218599AD8000A5232 /* CCNodeGrid.cpp */; };
ED9C6A9618599AD8000A5232 /* CCNodeGrid.h in Headers */ = {isa = PBXBuildFile; fileRef = ED9C6A9318599AD8000A5232 /* CCNodeGrid.h */; };
@ -2810,6 +2818,10 @@
B375104F1823AC7B00B3BA6A /* CCPhysicsWorldInfo_chipmunk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCPhysicsWorldInfo_chipmunk.h; sourceTree = "<group>"; };
B3AF019E1842FBA400A98B85 /* b2MotorJoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2MotorJoint.cpp; sourceTree = "<group>"; };
B3AF019F1842FBA400A98B85 /* b2MotorJoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2MotorJoint.h; sourceTree = "<group>"; };
C0940CA819419BDA00B8BB48 /* CCTMXLayer2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCTMXLayer2.h; sourceTree = "<group>"; };
C0940CA919419BDA00B8BB48 /* CCTMXTiledMap2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CCTMXTiledMap2.cpp; sourceTree = "<group>"; };
C0940CAA19419BDA00B8BB48 /* CCTMXTiledMap2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCTMXTiledMap2.h; sourceTree = "<group>"; };
C0940CAB19419BDA00B8BB48 /* CCTMXLayer2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CCTMXLayer2.cpp; sourceTree = "<group>"; };
ED9C6A9218599AD8000A5232 /* CCNodeGrid.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = CCNodeGrid.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
ED9C6A9318599AD8000A5232 /* CCNodeGrid.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCNodeGrid.h; sourceTree = "<group>"; };
/* End PBXFileReference section */
@ -3307,6 +3319,10 @@
1A5702DF180BCE610088DEC7 /* tilemap-parallax-nodes */ = {
isa = PBXGroup;
children = (
C0940CA819419BDA00B8BB48 /* CCTMXLayer2.h */,
C0940CAB19419BDA00B8BB48 /* CCTMXLayer2.cpp */,
C0940CA919419BDA00B8BB48 /* CCTMXTiledMap2.cpp */,
C0940CAA19419BDA00B8BB48 /* CCTMXTiledMap2.h */,
1A5702FE180BCE890088DEC7 /* CCParallaxNode.cpp */,
1A5702FF180BCE890088DEC7 /* CCParallaxNode.h */,
1A5702E0180BCE750088DEC7 /* CCTileMapAtlas.cpp */,
@ -4998,6 +5014,7 @@
50ABBED51925AB6F00A911A9 /* utlist.h in Headers */,
50FCEBAD18C72017004AD434 /* PageViewReader.h in Headers */,
1A5702F4180BCE750088DEC7 /* CCTMXObjectGroup.h in Headers */,
C0940CB019419BDA00B8BB48 /* CCTMXTiledMap2.h in Headers */,
50ABBDAF1925AB4100A911A9 /* CCRenderer.h in Headers */,
1A5702F8180BCE750088DEC7 /* CCTMXTiledMap.h in Headers */,
5034CA21191D591100CE6051 /* ccShader_PositionTextureColorAlphaTest.frag in Headers */,
@ -5114,6 +5131,7 @@
1AAF536C180E3374000584C8 /* HttpClient.h in Headers */,
50ABBD9D1925AB4100A911A9 /* ccGLStateCache.h in Headers */,
50ABBEB91925AB6F00A911A9 /* ccUTF8.h in Headers */,
C0940CAC19419BDA00B8BB48 /* CCTMXLayer2.h in Headers */,
1AAF536E180E3374000584C8 /* HttpRequest.h in Headers */,
29CB8F551929D7A900C841D6 /* UIScrollInterface.h in Headers */,
1AAF5370180E3374000584C8 /* HttpResponse.h in Headers */,
@ -5467,6 +5485,7 @@
1A570230180BCC1A0088DEC7 /* CCParticleSystemQuad.h in Headers */,
5034CA2C191D591100CE6051 /* ccShader_PositionTextureA8Color.vert in Headers */,
50ABBE981925AB6F00A911A9 /* CCProtocols.h in Headers */,
C0940CB119419BDA00B8BB48 /* CCTMXTiledMap2.h in Headers */,
2905FA8B18CF08D100240AA3 /* UITextField.h in Headers */,
50FCEBA618C72017004AD434 /* ListViewReader.h in Headers */,
50ABBD431925AB0000A911A9 /* CCMathBase.h in Headers */,
@ -5478,6 +5497,7 @@
50ABBE701925AB6F00A911A9 /* CCEventListenerKeyboard.h in Headers */,
1A57028D180BCC900088DEC7 /* CCSpriteFrameCache.h in Headers */,
1A570295180BCCAB0088DEC7 /* CCAnimation.h in Headers */,
C0940CAD19419BDA00B8BB48 /* CCTMXLayer2.h in Headers */,
50ABBDB81925AB4100A911A9 /* CCTexture2D.h in Headers */,
50ABBE341925AB6F00A911A9 /* CCConfiguration.h in Headers */,
1A570299180BCCAB0088DEC7 /* CCAnimationCache.h in Headers */,
@ -6121,6 +6141,7 @@
50ABBD831925AB4100A911A9 /* CCBatchCommand.cpp in Sources */,
1A5701C7180BCB5A0088DEC7 /* CCLabelTextFormatter.cpp in Sources */,
1A5701CB180BCB5A0088DEC7 /* CCLabelTTF.cpp in Sources */,
C0940CAE19419BDA00B8BB48 /* CCTMXTiledMap2.cpp in Sources */,
50ABBE711925AB6F00A911A9 /* CCEventListenerMouse.cpp in Sources */,
1A5701DE180BCB8C0088DEC7 /* CCLayer.cpp in Sources */,
1A5701E2180BCB8C0088DEC7 /* CCScene.cpp in Sources */,
@ -6208,6 +6229,7 @@
1AD71DE5180E26E600808F54 /* CCMenuItemImageLoader.cpp in Sources */,
50ABBD8B1925AB4100A911A9 /* CCGLProgram.cpp in Sources */,
1AD71DE9180E26E600808F54 /* CCMenuItemLoader.cpp in Sources */,
C0940CB219419BDA00B8BB48 /* CCTMXLayer2.cpp in Sources */,
50ABBDA31925AB4100A911A9 /* CCQuadCommand.cpp in Sources */,
2905FA6A18CF08D100240AA3 /* UIPageView.cpp in Sources */,
B29594C61926D61F003EEF37 /* CCObjLoader.cpp in Sources */,
@ -6550,6 +6572,7 @@
503DD8E21926736A00CD74DD /* CCCommon.mm in Sources */,
1A5701A2180BCB590088DEC7 /* CCFontAtlas.cpp in Sources */,
50ABC00E1926664800A911A9 /* CCFileUtils.cpp in Sources */,
C0940CB319419BDA00B8BB48 /* CCTMXLayer2.cpp in Sources */,
50ABBE241925AB6F00A911A9 /* base64.cpp in Sources */,
1A5701A6180BCB590088DEC7 /* CCFontAtlasCache.cpp in Sources */,
1A5701B2180BCB590088DEC7 /* CCFontFNT.cpp in Sources */,
@ -6733,6 +6756,7 @@
50ABC0001926664800A911A9 /* CCFileUtilsApple.mm in Sources */,
2905FA7918CF08D100240AA3 /* UISlider.cpp in Sources */,
1A8C59A4180E930E00EF57C3 /* CCArmatureAnimation.cpp in Sources */,
C0940CAF19419BDA00B8BB48 /* CCTMXTiledMap2.cpp in Sources */,
1A8C59A8180E930E00EF57C3 /* CCArmatureDataManager.cpp in Sources */,
2905FA8918CF08D100240AA3 /* UITextField.cpp in Sources */,
1A8C59AC180E930E00EF57C3 /* CCArmatureDefine.cpp in Sources */,

805
cocos/2d/CCTMXLayer2.cpp Normal file
View File

@ -0,0 +1,805 @@
/****************************************************************************
Copyright (c) 2008-2010 Ricardo Quesada
Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2011 Zynga Inc.
Copyright (c) 2013-2014 Chukong Technologies Inc.
Copyright (c) 2011 HKASoftware
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.
****************************************************************************/
/*
Original rewrite of TMXLayer was based on HKTMXTiledMap by HKASoftware http://hkasoftware.com
Further info: http://www.cocos2d-iphone.org/forums/topic/hktmxtiledmap/
It was rewritten again, and only a small part of the original HK ideas/code remains in this implementation
*/
#include "CCTMXLayer2.h"
#include "CCTMXXMLParser.h"
#include "CCTMXTiledMap.h"
#include "CCSprite.h"
#include "CCTextureCache.h"
#include "CCGLProgramCache.h"
#include "CCGLProgram.h"
#include "ccCArray.h"
#include "CCDirector.h"
#include "CCConfiguration.h"
#include "renderer/CCRenderer.h"
#include "deprecated/CCString.h"
NS_CC_BEGIN
namespace
{
static const int MAX_QUADS_COUNT = 65536 / 6;
}
// TMXLayer2 - init & alloc & dealloc
TMXLayer2 * TMXLayer2::create(TMXTilesetInfo *tilesetInfo, TMXLayerInfo *layerInfo, TMXMapInfo *mapInfo)
{
TMXLayer2 *ret = new TMXLayer2();
if (ret->initWithTilesetInfo(tilesetInfo, layerInfo, mapInfo))
{
ret->autorelease();
return ret;
}
return nullptr;
}
bool TMXLayer2::initWithTilesetInfo(TMXTilesetInfo *tilesetInfo, TMXLayerInfo *layerInfo, TMXMapInfo *mapInfo)
{
if( tilesetInfo )
{
_texture = Director::getInstance()->getTextureCache()->addImage(tilesetInfo->_sourceImage);
_texture->retain();
}
// layerInfo
_layerName = layerInfo->_name;
_layerSize = layerInfo->_layerSize;
_tiles = layerInfo->_tiles;
setOpacity( layerInfo->_opacity );
setProperties(layerInfo->getProperties());
// tilesetInfo
_tileSet = tilesetInfo;
CC_SAFE_RETAIN(_tileSet);
// mapInfo
_mapTileSize = mapInfo->getTileSize();
_layerOrientation = mapInfo->getOrientation();
// offset (after layer orientation is set);
Point offset = this->calculateLayerOffset(layerInfo->_offset);
this->setPosition(CC_POINT_PIXELS_TO_POINTS(offset));
this->setContentSize(CC_SIZE_PIXELS_TO_POINTS(Size(_layerSize.width * _mapTileSize.width, _layerSize.height * _mapTileSize.height)));
this->tileToNodeTransform();
// shader, and other stuff
setGLProgram(GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR));
_useAutomaticVertexZ = false;
_vertexZvalue = 0;
return true;
}
TMXLayer2::TMXLayer2()
:_layerName("")
,_layerSize(Size::ZERO)
,_mapTileSize(Size::ZERO)
,_tiles(nullptr)
,_tileSet(nullptr)
,_layerOrientation(TMXOrientationOrtho)
,_texture(nullptr)
,_reusedTile(nullptr)
,_previousRect(0,0,0,0)
,_verticesToDraw(0)
,_vertexZvalue(0)
,_useAutomaticVertexZ(false)
,_quads(nullptr)
,_indices(nullptr)
,_numQuads(0)
{}
TMXLayer2::~TMXLayer2()
{
CC_SAFE_RELEASE(_tileSet);
CC_SAFE_RELEASE(_texture);
CC_SAFE_DELETE_ARRAY(_tiles);
CC_SAFE_FREE(_quads);
CC_SAFE_FREE(_indices);
}
void TMXLayer2::draw(Renderer *renderer, const Mat4& transform, uint32_t flags)
{
_customCommand.init(_globalZOrder);
_customCommand.func = CC_CALLBACK_0(TMXLayer2::onDraw, this, transform, flags);
renderer->addCommand(&_customCommand);
}
void TMXLayer2::onDraw(const Mat4 &transform, bool transformUpdated)
{
GL::enableVertexAttribs(GL::VERTEX_ATTRIB_FLAG_POSITION | GL::VERTEX_ATTRIB_FLAG_TEX_COORD);
GL::bindTexture2D( _texture->getName() );
// tex coords + indices
glBindBuffer(GL_ARRAY_BUFFER, _buffersVBO[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _buffersVBO[1]);
if( transformUpdated ) {
Size s = Director::getInstance()->getWinSize();
auto rect = Rect(0, 0, s.width, s.height);
Mat4 inv = transform;
inv.inverse();
rect = RectApplyTransform(rect, inv);
if( !rect.equals(_previousRect) )
{
if (Configuration::getInstance()->supportsShareableVAO())
{
V2F_T2F_Quad* quads = (V2F_T2F_Quad*)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
GLushort* indices = (GLushort *)glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY);
_verticesToDraw = updateTiles(rect, quads, indices);
glUnmapBuffer(GL_ARRAY_BUFFER);
glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
}
else
{
_verticesToDraw = updateTiles(rect, nullptr, nullptr);
if (_quads != nullptr && _indices != nullptr && _verticesToDraw > 0)
{
glBufferData(GL_ARRAY_BUFFER, sizeof(_quads[0]) * _numQuads , _quads, GL_DYNAMIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(_indices[0]) * _numQuads * 6 , _indices, GL_STATIC_DRAW);
}
}
_previousRect = rect;
}
// don't draw more than 65535 vertices since we are using GL_UNSIGNED_SHORT for indices
_verticesToDraw = std::min(_verticesToDraw, 65535);
}
if(_verticesToDraw > 0) {
getGLProgram()->use();
getGLProgram()->setUniformsForBuiltins(_modelViewTransform);
// vertices
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(V2F_T2F), (GLvoid*) offsetof(V2F_T2F, vertices));
// tex coords
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORDS, 2, GL_FLOAT, GL_FALSE, sizeof(V2F_T2F), (GLvoid*) offsetof(V2F_T2F, texCoords));
// color
glVertexAttrib4f(GLProgram::VERTEX_ATTRIB_COLOR, _displayedColor.r/255.0f, _displayedColor.g/255.0f, _displayedColor.b/255.0f, _displayedOpacity/255.0f);
glDrawElements(GL_TRIANGLES, _verticesToDraw, GL_UNSIGNED_SHORT, nullptr);
CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1,_verticesToDraw);
}
// cleanup
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
int TMXLayer2::updateTiles(const Rect& culledRect, V2F_T2F_Quad *quads, GLushort *indices)
{
int tilesUsed = 0;
Rect visibleTiles = culledRect;
Size mapTileSize = CC_SIZE_PIXELS_TO_POINTS(_mapTileSize);
Size tileSize = CC_SIZE_PIXELS_TO_POINTS(_tileSet->_tileSize);
Mat4 nodeToTile = _tileToNodeTransform;
nodeToTile.inverse();
//transform to tile
visibleTiles = RectApplyTransform(visibleTiles, nodeToTile);
visibleTiles.origin.x = floor(visibleTiles.origin.x);
visibleTiles.origin.y = floor(visibleTiles.origin.y);
visibleTiles.size.width = ceil(visibleTiles.size.width);
visibleTiles.size.height = ceil(visibleTiles.size.height);
V2F_T2F_Quad* quadsTmp = quads;
GLushort* indicesTmp = indices;
// doesn't support VBO
if (quadsTmp == nullptr)
{
int quadsNeed = std::min(static_cast<int>((visibleTiles.size.width + 1) * (visibleTiles.size.height + 1)), MAX_QUADS_COUNT);
if (_numQuads < quadsNeed)
{
_numQuads = quadsNeed;
_quads = (V2F_T2F_Quad*)realloc(_quads, _numQuads * sizeof(V2F_T2F_Quad));
_indices = (GLushort*)realloc(_indices, _numQuads * 6 * sizeof(GLushort));
}
quadsTmp = _quads;
indicesTmp = _indices;
}
int rows_per_tile = ceil(tileSize.height / mapTileSize.height) - 1;
Size texSize = _tileSet->_imageSize;
for (int y = visibleTiles.origin.y - rows_per_tile; y <= visibleTiles.origin.y + visibleTiles.size.height; ++y)
{
if(y<0 || y >= _layerSize.height)
continue;
for (int x = visibleTiles.origin.x; x <= visibleTiles.origin.x + visibleTiles.size.width; x++)
{
if(x<0 || x >= _layerSize.width)
continue;
int tileGID = _tiles[x + y * (int)_layerSize.width];
// GID==0 empty tile
if(tileGID!=0) {
V2F_T2F_Quad *quad = &quadsTmp[tilesUsed];
Vec3 nodePos(static_cast<float>(x), static_cast<float>(y), 0);
_tileToNodeTransform.transformPoint(&nodePos);
float left, right, top, bottom;
// vertices
left = nodePos.x;
right = nodePos.x + tileSize.width;
bottom = nodePos.y + tileSize.height;
top = nodePos.y;
if(tileGID & kTMXTileVerticalFlag)
std::swap(top, bottom);
if(tileGID & kTMXTileHorizontalFlag)
std::swap(left, right);
if(tileGID & kTMXTileDiagonalFlag)
{
// XXX: not working correcly
quad->bl.vertices.x = left;
quad->bl.vertices.y = bottom;
quad->br.vertices.x = left;
quad->br.vertices.y = top;
quad->tl.vertices.x = right;
quad->tl.vertices.y = bottom;
quad->tr.vertices.x = right;
quad->tr.vertices.y = top;
}
else
{
quad->bl.vertices.x = left;
quad->bl.vertices.y = bottom;
quad->br.vertices.x = right;
quad->br.vertices.y = bottom;
quad->tl.vertices.x = left;
quad->tl.vertices.y = top;
quad->tr.vertices.x = right;
quad->tr.vertices.y = top;
}
// texcoords
Rect tileTexture = _tileSet->getRectForGID(tileGID);
left = (tileTexture.origin.x / texSize.width);
right = left + (tileTexture.size.width / texSize.width);
bottom = (tileTexture.origin.y / texSize.height);
top = bottom + (tileTexture.size.height / texSize.height);
quad->bl.texCoords.u = left;
quad->bl.texCoords.v = bottom;
quad->br.texCoords.u = right;
quad->br.texCoords.v = bottom;
quad->tl.texCoords.u = left;
quad->tl.texCoords.v = top;
quad->tr.texCoords.u = right;
quad->tr.texCoords.v = top;
GLushort *idxbase = indicesTmp + tilesUsed * 6;
int vertexbase = tilesUsed * 4;
idxbase[0] = vertexbase;
idxbase[1] = vertexbase + 1;
idxbase[2] = vertexbase + 2;
idxbase[3] = vertexbase + 3;
idxbase[4] = vertexbase + 2;
idxbase[5] = vertexbase + 1;
tilesUsed++;
}
if (tilesUsed >= MAX_QUADS_COUNT)
{
break;
}
} // for x
if (tilesUsed >= MAX_QUADS_COUNT)
{
break;
}
} // for y
return tilesUsed * 6;
}
void TMXLayer2::setupVBO()
{
glGenBuffers(2, &_buffersVBO[0]);
// 10922 = 65536/6
int total = std::min(static_cast<int>(_layerSize.width * _layerSize.height), MAX_QUADS_COUNT);
// Vertex + Tex Coords
glBindBuffer(GL_ARRAY_BUFFER, _buffersVBO[0]);
glBufferData(GL_ARRAY_BUFFER, total * sizeof(V2F_T2F_Quad), NULL, GL_DYNAMIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// Indices
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _buffersVBO[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, total * 6 * sizeof(GLushort), NULL, GL_DYNAMIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
CHECK_GL_ERROR_DEBUG();
}
// TMXLayer2 - setup Tiles
void TMXLayer2::setupTiles()
{
// Optimization: quick hack that sets the image size on the tileset
_tileSet->_imageSize = _texture->getContentSizeInPixels();
// By default all the tiles are aliased
// pros: easier to render
// cons: difficult to scale / rotate / etc.
_texture->setAliasTexParameters();
//CFByteOrder o = CFByteOrderGetCurrent();
// Parse cocos2d properties
this->parseInternalProperties();
Size screenSize = Director::getInstance()->getWinSize();
switch (_layerOrientation)
{
case TMXOrientationOrtho:
_screenGridSize.width = ceil(screenSize.width / _mapTileSize.width) + 1;
_screenGridSize.height = ceil(screenSize.height / _mapTileSize.height) + 1;
// tiles could be bigger than the grid, add additional rows if needed
_screenGridSize.height += _tileSet->_tileSize.height / _mapTileSize.height;
break;
case TMXOrientationIso:
_screenGridSize.width = ceil(screenSize.width / _mapTileSize.width) + 2;
_screenGridSize.height = ceil(screenSize.height / (_mapTileSize.height/2)) + 4;
break;
case TMXOrientationHex:
break;
}
_screenTileCount = _screenGridSize.width * _screenGridSize.height;
setupVBO();
}
Mat4 TMXLayer2::tileToNodeTransform()
{
float w = _mapTileSize.width / CC_CONTENT_SCALE_FACTOR();
float h = _mapTileSize.height / CC_CONTENT_SCALE_FACTOR();
float offY = (_layerSize.height - 1) * h;
switch(_layerOrientation)
{
case TMXOrientationOrtho:
{
_tileToNodeTransform = Mat4
(
w, 0.0f, 0.0f, 0.0f,
0.0f, -h, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, offY, 0.0f, 1.0f
);
return _tileToNodeTransform;
}
case TMXOrientationIso:
{
float offX = (_layerSize.width - 1) * w / 2;
_tileToNodeTransform = Mat4
(
w/2, -h/2, 0.0f, 0.0f,
-w/2, -h/2, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
offX, offY, 0.0f, 1.0f
);
return _tileToNodeTransform;
}
case TMXOrientationHex:
{
_tileToNodeTransform = Mat4::IDENTITY;
return _tileToNodeTransform;
}
default:
{
_tileToNodeTransform = Mat4::IDENTITY;
return _tileToNodeTransform;
}
}
}
// removing / getting tiles
Sprite* TMXLayer2::getTileAt(const Point& tileCoordinate)
{
CCASSERT( tileCoordinate.x < _layerSize.width && tileCoordinate.y < _layerSize.height && tileCoordinate.x >=0 && tileCoordinate.y >=0, "TMXLayer: invalid position");
CCASSERT( _tiles, "TMXLayer: the tiles map has been released");
Sprite *tile = nullptr;
int gid = this->getTileGIDAt(tileCoordinate);
// if GID == 0, then no tile is present
if( gid ) {
int index = tileCoordinate.x + tileCoordinate.y * _layerSize.width;
auto it = _spriteContainer.find(index);
if (it != _spriteContainer.end())
{
tile = it->second.first;
}
else
{
// tile not created yet. create it
Rect rect = _tileSet->getRectForGID(gid);
rect = CC_RECT_PIXELS_TO_POINTS(rect);
tile = Sprite::createWithTexture(_texture, rect);
Point p = this->getPositionAt(tileCoordinate);
tile->setAnchorPoint(Point::ZERO);
tile->setPosition(p);
tile->setPositionZ((float)getVertexZForPos(tileCoordinate));
tile->setOpacity(this->getOpacity());
tile->setTag(index);
this->addChild(tile, -index);
_spriteContainer.insert(std::pair<int, std::pair<Sprite*, int> >(index, std::pair<Sprite*, int>(tile, gid)));
// tile is converted to sprite.
_tiles[index] = 0;
}
}
return tile;
}
int TMXLayer2::getTileGIDAt(const Point& tileCoordinate, TMXTileFlags* flags/* = nullptr*/)
{
CCASSERT(tileCoordinate.x < _layerSize.width && tileCoordinate.y < _layerSize.height && tileCoordinate.x >=0 && tileCoordinate.y >=0, "TMXLayer: invalid position");
CCASSERT(_tiles, "TMXLayer: the tiles map has been released");
int idx = static_cast<int>((tileCoordinate.x + tileCoordinate.y * _layerSize.width));
// Bits on the far end of the 32-bit global tile ID are used for tile flags
int tile = _tiles[idx];
auto it = _spriteContainer.find(idx);
// converted to sprite.
if (tile == 0 && it != _spriteContainer.end())
{
tile = it->second.second;
}
// issue1264, flipped tiles can be changed dynamically
if (flags)
{
*flags = (TMXTileFlags)(tile & kTMXFlipedAll);
}
return (tile & kTMXFlippedMask);
}
Point TMXLayer2::getPositionAt(const Point& pos)
{
return PointApplyTransform(pos, _tileToNodeTransform);
}
int TMXLayer2::getVertexZForPos(const Point& pos)
{
int ret = 0;
int maxVal = 0;
if (_useAutomaticVertexZ)
{
switch (_layerOrientation)
{
case TMXOrientationIso:
maxVal = static_cast<int>(_layerSize.width + _layerSize.height);
ret = static_cast<int>(-(maxVal - (pos.x + pos.y)));
break;
case TMXOrientationOrtho:
ret = static_cast<int>(-(_layerSize.height-pos.y));
break;
case TMXOrientationHex:
CCASSERT(0, "TMX Hexa zOrder not supported");
break;
default:
CCASSERT(0, "TMX invalid value");
break;
}
}
else
{
ret = _vertexZvalue;
}
return ret;
}
void TMXLayer2::removeTileAt(const Point& tileCoordinate)
{
CCASSERT( tileCoordinate.x < _layerSize.width && tileCoordinate.y < _layerSize.height && tileCoordinate.x >=0 && tileCoordinate.y >=0, "TMXLayer: invalid position");
CCASSERT( _tiles, "TMXLayer: the tiles map has been released");
uint32_t gid = this->getTileGIDAt(tileCoordinate);
if( gid ) {
int z = tileCoordinate.x + tileCoordinate.y * _layerSize.width;
// remove tile from GID map
_tiles[z] = 0;
// remove it from sprites
auto it = _spriteContainer.find(z);
if (it != _spriteContainer.end())
{
this->removeChild(it->second.first);
}
}
}
void TMXLayer2::removeChild(Node* node, bool cleanup)
{
int tag = node->getTag();
auto it = _spriteContainer.find(tag);
if (it != _spriteContainer.end() && it->second.first == node)
{
_spriteContainer.erase(it);
}
Node::removeChild(node, cleanup);
}
// TMXLayer2 - Properties
Value TMXLayer2::getProperty(const std::string& propertyName) const
{
if (_properties.find(propertyName) != _properties.end())
return _properties.at(propertyName);
return Value();
}
void TMXLayer2::parseInternalProperties()
{
auto vertexz = getProperty("cc_vertexz");
if (!vertexz.isNull())
{
std::string vertexZStr = vertexz.asString();
// If "automatic" is on, then parse the "cc_alpha_func" too
if (vertexZStr == "automatic")
{
_useAutomaticVertexZ = true;
auto alphaFuncVal = getProperty("cc_alpha_func");
float alphaFuncValue = alphaFuncVal.asFloat();
setGLProgram(GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_ALPHA_TEST));
GLint alphaValueLocation = glGetUniformLocation(getGLProgram()->getProgram(), GLProgram::UNIFORM_NAME_ALPHA_TEST_VALUE);
// NOTE: alpha test shader is hard-coded to use the equivalent of a glAlphaFunc(GL_GREATER) comparison
// use shader program to set uniform
getGLProgram()->use();
getGLProgram()->setUniformLocationWith1f(alphaValueLocation, alphaFuncValue);
CHECK_GL_ERROR_DEBUG();
}
else
{
_vertexZvalue = vertexz.asInt();
}
}
}
//CCTMXLayer2 - obtaining positions, offset
Point TMXLayer2::calculateLayerOffset(const Point& pos)
{
Point ret = Point::ZERO;
switch (_layerOrientation)
{
case TMXOrientationOrtho:
ret = Point( pos.x * _mapTileSize.width, -pos.y *_mapTileSize.height);
break;
case TMXOrientationIso:
ret = Point((_mapTileSize.width /2) * (pos.x - pos.y),
(_mapTileSize.height /2 ) * (-pos.x - pos.y));
break;
case TMXOrientationHex:
CCASSERT(pos.equals(Point::ZERO), "offset for hexagonal map not implemented yet");
break;
}
return ret;
}
//void TMXLayer2::releaseMap()
//{
// if (_tiles)
// {
// delete [] _tiles;
// _tiles = nullptr;
// }
//}
// TMXLayer - adding / remove tiles
void TMXLayer2::setTileGID(int gid, const Point& tileCoordinate)
{
setTileGID(gid, tileCoordinate, (TMXTileFlags)0);
}
void TMXLayer2::setTileGID(int gid, const Point& tileCoordinate, TMXTileFlags flags)
{
CCASSERT(tileCoordinate.x < _layerSize.width && tileCoordinate.y < _layerSize.height && tileCoordinate.x >=0 && tileCoordinate.y >=0, "TMXLayer: invalid position");
CCASSERT(_tiles, "TMXLayer: the tiles map has been released");
CCASSERT(gid == 0 || gid >= _tileSet->_firstGid, "TMXLayer: invalid gid" );
TMXTileFlags currentFlags;
int currentGID = getTileGIDAt(tileCoordinate, &currentFlags);
if (currentGID != gid || currentFlags != flags)
{
int gidAndFlags = gid | flags;
// setting gid=0 is equal to remove the tile
if (gid == 0)
{
removeTileAt(tileCoordinate);
}
// empty tile. create a new one
else if (currentGID == 0)
{
int z = tileCoordinate.x + tileCoordinate.y * _layerSize.width;
_tiles[z] = gidAndFlags;
}
// modifying an existing tile with a non-empty tile
else
{
int z = tileCoordinate.x + tileCoordinate.y * _layerSize.width;
auto it = _spriteContainer.find(z);
if (it != _spriteContainer.end())
{
Sprite *sprite = it->second.first;
Rect rect = _tileSet->getRectForGID(gid);
rect = CC_RECT_PIXELS_TO_POINTS(rect);
sprite->setTextureRect(rect, false, rect.size);
this->reorderChild(sprite, z);
if (flags)
{
setupTileSprite(sprite, sprite->getPosition(), gidAndFlags);
}
it->second.second = gidAndFlags;
}
else
{
_tiles[z] = gidAndFlags;
}
}
}
}
void TMXLayer2::setupTileSprite(Sprite* sprite, Point pos, int gid)
{
sprite->setPosition(getPositionAt(pos));
sprite->setPositionZ((float)getVertexZForPos(pos));
sprite->setAnchorPoint(Point::ZERO);
sprite->setOpacity(this->getOpacity());
//issue 1264, flip can be undone as well
sprite->setFlippedX(false);
sprite->setFlippedY(false);
sprite->setRotation(0.0f);
// Rotation in tiled is achieved using 3 flipped states, flipping across the horizontal, vertical, and diagonal axes of the tiles.
if (gid & kTMXTileDiagonalFlag)
{
// put the anchor in the middle for ease of rotation.
sprite->setAnchorPoint(Point(0.5f,0.5f));
sprite->setPosition(Point(getPositionAt(pos).x + sprite->getContentSize().height/2,
getPositionAt(pos).y + sprite->getContentSize().width/2 ) );
int flag = gid & (kTMXTileHorizontalFlag | kTMXTileVerticalFlag );
// handle the 4 diagonally flipped states.
if (flag == kTMXTileHorizontalFlag)
{
sprite->setRotation(90.0f);
}
else if (flag == kTMXTileVerticalFlag)
{
sprite->setRotation(270.0f);
}
else if (flag == (kTMXTileVerticalFlag | kTMXTileHorizontalFlag) )
{
sprite->setRotation(90.0f);
sprite->setFlippedX(true);
}
else
{
sprite->setRotation(270.0f);
sprite->setFlippedX(true);
}
}
else
{
if (gid & kTMXTileHorizontalFlag)
{
sprite->setFlippedX(true);
}
if (gid & kTMXTileVerticalFlag)
{
sprite->setFlippedY(true);
}
}
}
Sprite* TMXLayer2::reusedTileWithRect(Rect rect)
{
if (! _reusedTile)
{
_reusedTile = Sprite::createWithTexture(_texture, rect);
_reusedTile->retain();
}
else
{
// Re-init the sprite
_reusedTile->setTextureRect(rect, false, rect.size);
}
return _reusedTile;
}
std::string TMXLayer2::getDescription() const
{
return StringUtils::format("<TMXLayer2 | tag = %d, size = %d,%d>", _tag, (int)_mapTileSize.width, (int)_mapTileSize.height);
}
NS_CC_END

261
cocos/2d/CCTMXLayer2.h Normal file
View File

@ -0,0 +1,261 @@
/****************************************************************************
Copyright (c) 2008-2010 Ricardo Quesada
Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2011 Zynga Inc.
Copyright (c) 2013-2014 Chukong Technologies Inc.
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_LAYER2_H__
#define __CCTMX_LAYER2_H__
#include "CCTMXObjectGroup.h"
#include "CCTMXXMLParser.h"
#include "CCNode.h"
#include "renderer/CCCustomCommand.h"
#include <map>
NS_CC_BEGIN
class TMXMapInfo;
class TMXLayerInfo;
class TMXTilesetInfo;
class Texture2D;
class Sprite;
struct _ccCArray;
/**
* @addtogroup tilemap_parallax_nodes
* @{
*/
/** @brief TMXLayer2 represents the TMX layer.
It is a subclass of SpriteBatchNode. By default the tiles are rendered using a TextureAtlas.
If you modify a tile on runtime, then, that tile will become a Sprite, otherwise no Sprite objects are created.
The benefits of using Sprite objects as tiles are:
- tiles (Sprite) 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 drawing 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 different
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
Tiles can have tile flags for additional properties. At the moment only flip horizontal and flip vertical are used. These bit flags are defined in TMXXMLParser.h.
@since 1.1
*/
class CC_DLL TMXLayer2 : public Node
{
public:
/** creates a TMXLayer2 with an tileset info, a layer info and a map info */
static TMXLayer2 * create(TMXTilesetInfo *tilesetInfo, TMXLayerInfo *layerInfo, TMXMapInfo *mapInfo);
/**
* @js ctor
*/
TMXLayer2();
/**
* @js NA
* @lua NA
*/
virtual ~TMXLayer2();
/** returns the tile gid at a given tile coordinate. It also returns the tile flags.
*/
int getTileGIDAt(const Point& tileCoordinate, TMXTileFlags* flags = nullptr);
CC_DEPRECATED_ATTRIBUTE int tileGIDAt(const Point& tileCoordinate, TMXTileFlags* flags = nullptr){
return getTileGIDAt(tileCoordinate, flags);
};
/** 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(int gid, const Point& 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.
Use withFlags if the tile flags need to be changed as well
*/
void setTileGID(int gid, const Point& tileCoordinate, TMXTileFlags flags);
/** removes a tile at given tile coordinate */
void removeTileAt(const Point& tileCoordinate);
/** returns the position in points of a given tile coordinate */
Point getPositionAt(const Point& tileCoordinate);
CC_DEPRECATED_ATTRIBUTE Point positionAt(const Point& tileCoordinate) { return getPositionAt(tileCoordinate); };
/** return the value for the specific property name */
Value getProperty(const std::string& propertyName) const;
CC_DEPRECATED_ATTRIBUTE Value propertyNamed(const std::string& propertyName) const { return getProperty(propertyName); };
/** Creates the tiles */
void setupTiles();
inline const std::string& getLayerName(){ return _layerName; }
inline void setLayerName(const std::string& layerName){ _layerName = layerName; }
/** size of the layer in tiles */
inline const Size& getLayerSize() const { return _layerSize; };
inline void setLayerSize(const Size& size) { _layerSize = size; };
/** size of the map's tile (could be different from the tile's size) */
inline const Size& getMapTileSize() const { return _mapTileSize; };
inline void setMapTileSize(const Size& size) { _mapTileSize = size; };
/** pointer to the map of tiles
* @js NA
* @lua NA
*/
uint32_t* getTiles() const { return _tiles; };
void setTiles(uint32_t* tiles) { _tiles = tiles; };
/** Tileset information for the layer */
inline TMXTilesetInfo* getTileSet() const { return _tileSet; };
inline void setTileSet(TMXTilesetInfo* info) {
CC_SAFE_RETAIN(info);
CC_SAFE_RELEASE(_tileSet);
_tileSet = info;
};
/** Layer orientation, which is the same as the map orientation */
inline int getLayerOrientation() const { return _layerOrientation; };
inline void setLayerOrientation(int orientation) { _layerOrientation = orientation; };
/** properties from the layer. They can be added using Tiled */
inline const ValueMap& getProperties() const { return _properties; };
inline ValueMap& getProperties() { return _properties; };
inline void setProperties(const ValueMap& properties) {
_properties = properties;
};
/** returns the tile (Sprite) at a given a tile coordinate.
The returned Sprite will be already added to the TMXLayer. Don't add it again.
The Sprite can be treated like any other Sprite: rotated, scaled, translated, opacity, color, etc.
You can remove either by calling:
- layer->removeChild(sprite, cleanup);
*/
Sprite* getTileAt(const Point& tileCoordinate);
Sprite* reusedTileWithRect(Rect rect);
Sprite* updateTileForGID(int gid, const Point& pos);
void setupTileSprite(Sprite* sprite, Point pos, int gid);
//
// Override
//
virtual std::string getDescription() const override;
virtual void draw(Renderer *renderer, const Mat4& transform, uint32_t flags) override;
void removeChild(Node* child, bool cleanup = true) override;
protected:
bool initWithTilesetInfo(TMXTilesetInfo *tilesetInfo, TMXLayerInfo *layerInfo, TMXMapInfo *mapInfo);
int updateTiles(const Rect& culledRect, V2F_T2F_Quad *quads, GLushort *indices);
void setupVBO();
Point calculateLayerOffset(const Point& offset);
/* The layer recognizes some special properties, like cc_vertez */
void parseInternalProperties();
Mat4 tileToNodeTransform();
Rect tileBoundsForClipTransform(const Mat4 &tileToClip);
void onDraw(const Mat4 &transform, bool transformUpdated);
int getVertexZForPos(const Point& pos);
void insertTileForGID(int gid, const Point& pos);
protected:
CustomCommand _customCommand;
//! name of the layer
std::string _layerName;
/** size of the layer in tiles */
Size _layerSize;
/** size of the map's tile (could be different from the tile's size) */
Size _mapTileSize;
/** pointer to the map of tiles */
uint32_t* _tiles;
/** Tileset information for the layer */
TMXTilesetInfo* _tileSet;
/** Layer orientation, which is the same as the map orientation */
int _layerOrientation;
/** properties from the layer. They can be added using Tiled */
ValueMap _properties;
Texture2D *_texture;
Sprite* _reusedTile;
/** container for sprite children. map<index, pair<sprite, gid> > */
std::map<int, std::pair<Sprite*, int> > _spriteContainer;
GLuint _buffersVBO[3]; //0: vertex, 1: tex coords, 2: indices
Size _screenGridSize;
Rect _screenGridRect;
int _screenTileCount;
Rect _previousRect;
int _verticesToDraw;
int _vertexZvalue;
bool _useAutomaticVertexZ;
/** tile coordinate to node coordinate transform */
Mat4 _tileToNodeTransform;
/** quads to be rendered */
V2F_T2F_Quad* _quads;
/** number of quads */
int _numQuads;
/** indices */
GLushort* _indices;
};
// end of tilemap_parallax_nodes group
/// @}
NS_CC_END
#endif //__CCTMX_LAYER2_H__

259
cocos/2d/CCTMXTiledMap2.cpp Normal file
View File

@ -0,0 +1,259 @@
/****************************************************************************
Copyright (c) 2009-2010 Ricardo Quesada
Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2011 Zynga Inc.
Copyright (c) 2013-2014 Chukong Technologies Inc.
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 "CCTMXTiledMap2.h"
#include <algorithm>
#include "CCTMXXMLParser.h"
#include "CCTMXLayer2.h"
#include "CCSprite.h"
#include "deprecated/CCString.h"
NS_CC_BEGIN
// implementation TMXTiledMap2
TMXTiledMap2 * TMXTiledMap2::create(const std::string& tmxFile)
{
TMXTiledMap2 *ret = new TMXTiledMap2();
if (ret->initWithTMXFile(tmxFile))
{
ret->autorelease();
return ret;
}
CC_SAFE_DELETE(ret);
return nullptr;
}
TMXTiledMap2* TMXTiledMap2::createWithXML(const std::string& tmxString, const std::string& resourcePath)
{
TMXTiledMap2 *ret = new TMXTiledMap2();
if (ret->initWithXML(tmxString, resourcePath))
{
ret->autorelease();
return ret;
}
CC_SAFE_DELETE(ret);
return nullptr;
}
bool TMXTiledMap2::initWithTMXFile(const std::string& tmxFile)
{
CCASSERT(tmxFile.size()>0, "TMXTiledMap2: tmx file should not be empty");
setContentSize(Size::ZERO);
TMXMapInfo *mapInfo = TMXMapInfo::create(tmxFile);
if (! mapInfo)
{
return false;
}
CCASSERT( !mapInfo->getTilesets().empty(), "TMXTiledMap2: Map not found. Please check the filename.");
buildWithMapInfo(mapInfo);
return true;
}
bool TMXTiledMap2::initWithXML(const std::string& tmxString, const std::string& resourcePath)
{
setContentSize(Size::ZERO);
TMXMapInfo *mapInfo = TMXMapInfo::createWithXML(tmxString, resourcePath);
CCASSERT( !mapInfo->getTilesets().empty(), "TMXTiledMap2: Map not found. Please check the filename.");
buildWithMapInfo(mapInfo);
return true;
}
TMXTiledMap2::TMXTiledMap2()
:_mapSize(Size::ZERO)
,_tileSize(Size::ZERO)
{
}
TMXTiledMap2::~TMXTiledMap2()
{
}
// private
TMXLayer2 * TMXTiledMap2::parseLayer(TMXLayerInfo *layerInfo, TMXMapInfo *mapInfo)
{
TMXTilesetInfo *tileset = tilesetForLayer(layerInfo, mapInfo);
TMXLayer2 *layer = TMXLayer2::create(tileset, layerInfo, mapInfo);
// tell the layerinfo to release the ownership of the tiles map.
layerInfo->_ownTiles = false;
layer->setupTiles();
return layer;
}
TMXTilesetInfo * TMXTiledMap2::tilesetForLayer(TMXLayerInfo *layerInfo, TMXMapInfo *mapInfo)
{
Size size = layerInfo->_layerSize;
auto& tilesets = mapInfo->getTilesets();
if (tilesets.size()>0)
{
TMXTilesetInfo* tileset = nullptr;
for (auto iter = tilesets.crbegin(); iter != tilesets.crend(); ++iter)
{
tileset = *iter;
if (tileset)
{
for( int y=0; y < size.height; y++ )
{
for( int x=0; x < size.width; x++ )
{
int pos = static_cast<int>(x + size.width * y);
int gid = layerInfo->_tiles[ 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 )
{
// Optimization: quick return
// if the layer is invalid (more than 1 tileset per layer) an CCAssert will be thrown later
if( (gid & kTMXFlippedMask) >= tileset->_firstGid )
return tileset;
}
}
}
}
}
}
// If all the tiles are 0, return empty tileset
CCLOG("cocos2d: Warning: TMX Layer '%s' has no tiles", layerInfo->_name.c_str());
return nullptr;
}
void TMXTiledMap2::buildWithMapInfo(TMXMapInfo* mapInfo)
{
_mapSize = mapInfo->getMapSize();
_tileSize = mapInfo->getTileSize();
_mapOrientation = mapInfo->getOrientation();
_objectGroups = mapInfo->getObjectGroups();
_properties = mapInfo->getProperties();
_tileProperties = mapInfo->getTileProperties();
int idx=0;
auto& layers = mapInfo->getLayers();
for(const auto &layerInfo : layers) {
if (layerInfo->_visible)
{
TMXLayer2 *child = parseLayer(layerInfo, mapInfo);
addChild(child, idx, idx);
// update content size with the max size
const Size& childSize = child->getContentSize();
Size currentSize = this->getContentSize();
currentSize.width = std::max( currentSize.width, childSize.width );
currentSize.height = std::max( currentSize.height, childSize.height );
this->setContentSize(currentSize);
idx++;
}
}
}
// public
TMXLayer2 * TMXTiledMap2::getLayer(const std::string& layerName) const
{
CCASSERT(layerName.size() > 0, "Invalid layer name!");
for (auto& child : _children)
{
TMXLayer2* layer = dynamic_cast<TMXLayer2*>(child);
if(layer)
{
if(layerName.compare( layer->getLayerName()) == 0)
{
return layer;
}
}
}
// layer not found
return nullptr;
}
TMXObjectGroup * TMXTiledMap2::getObjectGroup(const std::string& groupName) const
{
CCASSERT(groupName.size() > 0, "Invalid group name!");
if (_objectGroups.size()>0)
{
TMXObjectGroup* objectGroup = nullptr;
for (auto iter = _objectGroups.cbegin(); iter != _objectGroups.cend(); ++iter)
{
objectGroup = *iter;
if (objectGroup && objectGroup->getGroupName() == groupName)
{
return objectGroup;
}
}
}
// objectGroup not found
return nullptr;
}
Value TMXTiledMap2::getProperty(const std::string& propertyName) const
{
if (_properties.find(propertyName) != _properties.end())
return _properties.at(propertyName);
return Value();
}
Value TMXTiledMap2::getPropertiesForGID(int GID) const
{
if (_tileProperties.find(GID) != _tileProperties.end())
return _tileProperties.at(GID);
return Value();
}
std::string TMXTiledMap2::getDescription() const
{
return StringUtils::format("<TMXTiledMap2 | Tag = %d, Layers = %d", _tag, static_cast<int>(_children.size()));
}
NS_CC_END

222
cocos/2d/CCTMXTiledMap2.h Normal file
View File

@ -0,0 +1,222 @@
/****************************************************************************
Copyright (c) 2009-2010 Ricardo Quesada
Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2011 Zynga Inc.
Copyright (c) 2013-2014 Chukong Technologies Inc.
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_TILE_MAP2_H__
#define __CCTMX_TILE_MAP2_H__
#include "CCNode.h"
#include "CCTMXObjectGroup.h"
#include "CCValue.h"
NS_CC_BEGIN
class TMXObjectGroup;
class TMXLayer2;
class TMXLayerInfo;
class TMXTilesetInfo;
class TMXMapInfo;
/**
* @addtogroup tilemap_parallax_nodes
* @{
*/
/** Possible orientations of the TMX map */
enum
{
/** Orthogonal orientation */
TMXOrientationOrtho2,
/** Hexagonal orientation */
TMXOrientationHex2,
/** Isometric orientation */
TMXOrientationIso2,
};
/** @brief TMXTiledMap2 knows how to parse and render a TMX map.
It adds support for the TMX tiled map format used by http://www.mapeditor.org
It supports isometric, hexagonal and orthogonal tiles.
It also supports object groups, objects, and properties.
Features:
- Each tile will be treated as an Sprite
- The sprites are created on demand. They will be created only when you call "layer->tileAt(position)"
- Each tile can be rotated / moved / scaled / tinted / "opaqued", since each tile is a Sprite
- Tiles can be added/removed in runtime
- The z-order of the tiles can be modified in runtime
- Each tile has an anchorPoint of (0,0)
- The anchorPoint of the TMXTileMap is (0,0)
- The TMX layers will be added as a child
- The TMX layers will be aliased by default
- The tileset image will be loaded using the TextureCache
- Each tile will have a unique tag
- Each tile will have a unique z value. top-left: z=1, bottom-right: z=max z
- Each object group will be treated as an MutableArray
- Object class which will contain all the properties in a dictionary
- Properties can be assigned to the Map, Layer, Object Group, and Object
Limitations:
- It only supports one tileset per layer.
- Embedded images are not supported
- It only supports the XML format (the JSON format is not supported)
Technical description:
Each layer is created using an TMXLayer2 (subclass of SpriteBatchNode). If you have 5 layers, then 5 TMXLayer2 will be created,
unless the layer visibility is off. In that case, the layer won't be created at all.
You can obtain the layers (TMXLayer2 objects) at runtime by:
- map->getChildByTag(tag_number); // 0=1st layer, 1=2nd layer, 2=3rd layer, etc...
- map->getLayer(name_of_the_layer);
Each object group is created using a TMXObjectGroup which is a subclass of MutableArray.
You can obtain the object groups at runtime by:
- map->getObjectGroup(name_of_the_object_group);
Each object is a TMXObject.
Each property is stored as a key-value pair in an MutableDictionary.
You can obtain the properties at runtime by:
map->getProperty(name_of_the_property);
layer->getProperty(name_of_the_property);
objectGroup->getProperty(name_of_the_property);
object->getProperty(name_of_the_property);
@since v0.8.1
*/
class CC_DLL TMXTiledMap2 : public Node
{
public:
/** creates a TMX Tiled Map with a TMX file.*/
static TMXTiledMap2* create(const std::string& tmxFile);
/** initializes a TMX Tiled Map with a TMX formatted XML string and a path to TMX resources */
static TMXTiledMap2* createWithXML(const std::string& tmxString, const std::string& resourcePath);
/** return the TMXLayer2 for the specific layer */
TMXLayer2* getLayer(const std::string& layerName) const;
/**
* @js NA
* @lua NA
*/
CC_DEPRECATED_ATTRIBUTE TMXLayer2* layerNamed(const std::string& layerName) const { return getLayer(layerName); };
/** return the TMXObjectGroup for the specific group */
TMXObjectGroup* getObjectGroup(const std::string& groupName) const;
/**
* @js NA
* @lua NA
*/
CC_DEPRECATED_ATTRIBUTE TMXObjectGroup* objectGroupNamed(const std::string& groupName) const { return getObjectGroup(groupName); };
/** return the value for the specific property name */
Value getProperty(const std::string& propertyName) const;
/**
* @js NA
* @lua NA
*/
CC_DEPRECATED_ATTRIBUTE Value propertyNamed(const char *propertyName) const { return getProperty(propertyName); };
/** return properties dictionary for tile GID */
Value getPropertiesForGID(int GID) const;
CC_DEPRECATED_ATTRIBUTE Value propertiesForGID(int GID) const { return getPropertiesForGID(GID); };
/** the map's size property measured in tiles */
inline const Size& getMapSize() const { return _mapSize; };
inline void setMapSize(const Size& mapSize) { _mapSize = mapSize; };
/** the tiles's size property measured in pixels */
inline const Size& getTileSize() const { return _tileSize; };
inline void setTileSize(const Size& tileSize) { _tileSize = tileSize; };
/** map orientation */
inline int getMapOrientation() const { return _mapOrientation; };
inline void setMapOrientation(int mapOrientation) { _mapOrientation = mapOrientation; };
/** object groups */
inline const Vector<TMXObjectGroup*>& getObjectGroups() const { return _objectGroups; };
inline Vector<TMXObjectGroup*>& getObjectGroups() { return _objectGroups; };
inline void setObjectGroups(const Vector<TMXObjectGroup*>& groups) {
_objectGroups = groups;
};
/** properties */
inline ValueMap& getProperties() { return _properties; };
inline void setProperties(const ValueMap& properties) {
_properties = properties;
};
virtual std::string getDescription() const override;
protected:
/**
* @js ctor
*/
TMXTiledMap2();
/**
* @js NA
* @lua NA
*/
virtual ~TMXTiledMap2();
/** initializes a TMX Tiled Map with a TMX file */
bool initWithTMXFile(const std::string& tmxFile);
/** initializes a TMX Tiled Map with a TMX formatted XML string and a path to TMX resources */
bool initWithXML(const std::string& tmxString, const std::string& resourcePath);
TMXLayer2 * parseLayer(TMXLayerInfo *layerInfo, TMXMapInfo *mapInfo);
TMXTilesetInfo * tilesetForLayer(TMXLayerInfo *layerInfo, TMXMapInfo *mapInfo);
void buildWithMapInfo(TMXMapInfo* mapInfo);
/** the map's size property measured in tiles */
Size _mapSize;
/** the tiles's size property measured in pixels */
Size _tileSize;
/** map orientation */
int _mapOrientation;
/** object groups */
Vector<TMXObjectGroup*> _objectGroups;
/** properties */
ValueMap _properties;
//! tile properties
ValueMapIntKey _tileProperties;
private:
CC_DISALLOW_COPY_AND_ASSIGN(TMXTiledMap2);
};
// end of tilemap_parallax_nodes group
/// @}
NS_CC_END
#endif //__CCTMX_TILE_MAP2_H__

View File

@ -254,6 +254,15 @@ struct V3F_C4B_T2F
Tex2F texCoords; // 8 bytes
};
//! a Vec2 with a vertex point, a tex coord point
struct V2F_T2F
{
//! vertices (2F)
Vec2 vertices;
//! tex coords (2F)
Tex2F texCoords;
};
//! A Triangle of V2F_C4B_T2F
struct V2F_C4B_T2F_Triangle
{
@ -304,6 +313,18 @@ struct V2F_C4F_T2F_Quad
V2F_C4F_T2F tr;
};
struct V2F_T2F_Quad
{
//! bottom left
V2F_T2F bl;
//! bottom right
V2F_T2F br;
//! top left
V2F_T2F tl;
//! top right
V2F_T2F tr;
};
//! Blend Function used for textures
struct BlendFunc
{