isometric kind of working

This commit is contained in:
Ricardo Quesada 2014-02-06 16:19:46 -08:00
parent 02af5059bf
commit cf08d0b3f9
3 changed files with 102 additions and 253 deletions

View File

@ -164,36 +164,37 @@ void TMXLayer2::onDraw()
GLfloat *texcoords = (GLfloat *)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); GLfloat *texcoords = (GLfloat *)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
Point trans = convertToWorldSpace(Point::ZERO); Point trans = convertToWorldSpace(Point::ZERO);
Point baseTile = Point(floor(-trans.x / (_mapTileSize.width)), Point baseTile = Point(
floor(-trans.y / (_mapTileSize.height))); floor(-trans.x / (_mapTileSize.width)),
floor(-trans.y / (_mapTileSize.height)));
Size texSize = _tileSet->_imageSize; Size texSize = _tileSet->_imageSize;
for (int y=0; y < _screenGridSize.height; y++) for (int y=0; y < _screenGridSize.height; y++)
{ {
for (int x=0; x < _screenGridSize.width; x++) for (int x=0; x < _screenGridSize.width; x++)
{ {
int tileidx = (_layerSize.height - (baseTile.y + y) - 1) * _layerSize.width + baseTile.x + x; int tileidx = getTileIndex(x, y, baseTile);
unsigned int tile = 0; unsigned int tile = 0;
if(tileidx >=0) if(tileidx >=0)
tile = _tiles[tileidx]; tile = _tiles[tileidx];
int screenidx = (y * (_screenGridSize.width)) + x; // vertices are sorted from top to bottom to support overlapping, so we need to convert 'y' to the new index
Rect tileTexture = _tileSet->rectForGID(tile & kFlippedMask); int screenidx = ((_screenGridSize.height-y-1) * (_screenGridSize.width)) + x;
GLfloat *texbase = texcoords + screenidx * 4 * 2;
GLfloat *texbase = texcoords + screenidx * 4 * 2;
float left, right, top, bottom; float left, right, top, bottom;
if(!tile if(!tile)
|| baseTile.x + x < 0 || baseTile.x + x >= _layerSize.width
|| baseTile.y + y < 0 || baseTile.y + y >= _layerSize.height
)
{ {
left = bottom = top = right = 0; left = bottom = 0;
top = right = 0;
} }
else else
{ {
Rect tileTexture = _tileSet->rectForGID(tile);
left = (tileTexture.origin.x / texSize.width); left = (tileTexture.origin.x / texSize.width);
right = left + (tileTexture.size.width / texSize.width); right = left + (tileTexture.size.width / texSize.width);
bottom = (tileTexture.origin.y / texSize.height); bottom = (tileTexture.origin.y / texSize.height);
@ -208,8 +209,8 @@ void TMXLayer2::onDraw()
texbase[5] = bottom; texbase[5] = bottom;
texbase[6] = right; texbase[6] = right;
texbase[7] = bottom; texbase[7] = bottom;
} }
} }
glUnmapBuffer(GL_ARRAY_BUFFER); glUnmapBuffer(GL_ARRAY_BUFFER);
@ -233,6 +234,34 @@ void TMXLayer2::onDraw()
CC_INCREMENT_GL_DRAWS(1); CC_INCREMENT_GL_DRAWS(1);
} }
int TMXLayer2::getTileIndex(int x, int y, cocos2d::Point baseTile)
{
int tileidx = -1;
switch (_layerOrientation)
{
case TMXOrientationOrtho:
if( baseTile.x + x < 0 || baseTile.x + x >= _layerSize.width
|| baseTile.y + y < 0 || baseTile.y + y >= _layerSize.height)
tileidx = -1;
else
tileidx = (_layerSize.height - (baseTile.y + y) - 1) * _layerSize.width + baseTile.x + x;
break;
case TMXOrientationIso:
int xx = x + ((y+1)/2) - 2;
int yy = y/2 +1 - x;
if( xx < 0 || xx >= _layerSize.width
|| yy < 0 || yy >= _layerSize.height )
tileidx = -1;
else
tileidx = xx + _layerSize.width * yy;
break;
}
return tileidx;
}
void TMXLayer2::setupIndices() void TMXLayer2::setupIndices()
{ {
GLushort *indices = (GLushort *)malloc( _screenTileCount * 6 * sizeof(GLushort) ); GLushort *indices = (GLushort *)malloc( _screenTileCount * 6 * sizeof(GLushort) );
@ -261,23 +290,26 @@ void TMXLayer2::setupVertices()
GLfloat *vertices = (GLfloat *)malloc( _screenTileCount * 4 * 2 * sizeof(GLfloat) ); GLfloat *vertices = (GLfloat *)malloc( _screenTileCount * 4 * 2 * sizeof(GLfloat) );
GLfloat *tilePtr = vertices; GLfloat *tilePtr = vertices;
for (int y=0; y < _screenGridSize.height; y++)
// top to bottom sorting to support overlapping
for (int y=_screenGridSize.height-1; y >=0; y--)
{ {
GLfloat ypos_0 = _mapTileSize.height * y;
GLfloat ypos_1 = _mapTileSize.height * (y+1);
for (int x=0; x < _screenGridSize.width; x++, tilePtr += 4 * 2) for (int x=0; x < _screenGridSize.width; x++, tilePtr += 4 * 2)
{ {
GLfloat xpos_0 = _mapTileSize.width * x;
GLfloat xpos_1 = _mapTileSize.width * (x+1); GLfloat xpos0, xpos1, ypos0, ypos1;
setVerticesForPos(x, y, &xpos0, &xpos1, &ypos0, &ypos1);
// define the points of a quad here; we'll use the index buffer to make them triangles // define the points of a quad here; we'll use the index buffer to make them triangles
tilePtr[0] = xpos_0; tilePtr[0] = xpos0;
tilePtr[1] = ypos_0; tilePtr[1] = ypos0;
tilePtr[2] = xpos_1; tilePtr[2] = xpos1;
tilePtr[3] = ypos_0; tilePtr[3] = ypos0;
tilePtr[4] = xpos_0; tilePtr[4] = xpos0;
tilePtr[5] = ypos_1; tilePtr[5] = ypos1;
tilePtr[6] = xpos_1; tilePtr[6] = xpos1;
tilePtr[7] = ypos_1; tilePtr[7] = ypos1;
} }
} }
@ -288,6 +320,27 @@ void TMXLayer2::setupVertices()
free(vertices); free(vertices);
} }
void TMXLayer2::setVerticesForPos(int x, int y, GLfloat *xpos0, GLfloat *xpos1, GLfloat *ypos0, GLfloat *ypos1)
{
switch (_layerOrientation)
{
case TMXOrientationOrtho:
*xpos0 = _mapTileSize.width * x;
*xpos1 = *xpos0 + _tileSet->_tileSize.width;
*ypos0 = _mapTileSize.height * y;
*ypos1 = *ypos0 + _tileSet->_tileSize.height;
break;
case TMXOrientationIso:
*xpos0 = _mapTileSize.width * x + _mapTileSize.width/2 * (y%2);
*xpos1 = *xpos0 + _tileSet->_tileSize.width;
*ypos0 = _mapTileSize.height * y / 2;
*ypos1 = *ypos0 + _tileSet->_tileSize.height;
break;
case TMXOrientationHex:
break;
}
}
void TMXLayer2::setupVBO() void TMXLayer2::setupVBO()
{ {
glGenBuffers(3, &_buffersVBO[0]); glGenBuffers(3, &_buffersVBO[0]);
@ -341,92 +394,25 @@ void TMXLayer2::setupTiles()
Size screenSize = Director::getInstance()->getWinSize(); Size screenSize = Director::getInstance()->getWinSize();
_screenGridSize.width = (ceil(screenSize.width / (_mapTileSize.width)) + 1); switch (_layerOrientation)
_screenGridSize.height = (ceil(screenSize.height / (_mapTileSize.height)) + 1); {
case TMXOrientationOrtho:
_screenGridSize.width = (ceil(screenSize.width / (_mapTileSize.width)) + 1);
_screenGridSize.height = (ceil(screenSize.height / (_mapTileSize.height)) + 1);
break;
case TMXOrientationIso:
_screenGridSize.width = (ceil(screenSize.width / (_mapTileSize.width)) + 1);
_screenGridSize.height = (ceil(screenSize.height / (_mapTileSize.height/2)) + 1);
break;
case TMXOrientationHex:
break;
}
_screenTileCount = _screenGridSize.width * _screenGridSize.height; _screenTileCount = _screenGridSize.width * _screenGridSize.height;
setupVBO(); setupVBO();
} }
// used only when parsing the map. useless after the map was parsed
// since lot's of assumptions are no longer true
void TMXLayer2::appendTileForGID(int gid, const Point& pos)
{
}
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;
}
void TMXLayer2::setupTileSprite(Sprite* sprite, Point pos, int gid)
{
sprite->setPosition(getPositionAt(pos));
sprite->setVertexZ((float)getVertexZForPos(pos));
sprite->setAnchorPoint(Point::ZERO);
sprite->setOpacity(_opacity);
//issue 1264, flip can be undone as well
sprite->setFlippedX(false);
sprite->setFlippedY(false);
sprite->setRotation(0.0f);
sprite->setAnchorPoint(Point(0,0));
// 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);
}
}
}
// TMXLayer2 - Properties // TMXLayer2 - Properties
Value TMXLayer2::getProperty(const std::string& propertyName) const Value TMXLayer2::getProperty(const std::string& propertyName) const
@ -470,67 +456,6 @@ void TMXLayer2::parseInternalProperties()
} }
int TMXLayer2::getTileGIDAt(const Point& pos, ccTMXTileFlags* flags/* = nullptr*/)
{
CCASSERT(pos.x < _layerSize.width && pos.y < _layerSize.height && pos.x >=0 && pos.y >=0, "TMXLayer2: invalid position");
CCASSERT(_tiles && _atlasIndexArray, "TMXLayer2: the tiles map has been released");
int idx = static_cast<int>((pos.x + pos.y * _layerSize.width));
// Bits on the far end of the 32-bit global tile ID are used for tile flags
int tile = _tiles[idx];
// issue1264, flipped tiles can be changed dynamically
if (flags)
{
*flags = (ccTMXTileFlags)(tile & kFlipedAll);
}
return (tile & kFlippedMask);
}
// TMXLayer2 - atlasIndex and Z
static inline int compareInts(const void * a, const void * b)
{
return ((*(int*)a) - (*(int*)b));
}
ssize_t TMXLayer2::atlasIndexForExistantZ(int z)
{
int key=z;
int *item = (int*)bsearch((void*)&key, (void*)&_atlasIndexArray->arr[0], _atlasIndexArray->num, sizeof(void*), compareInts);
CCASSERT(item, "TMX atlas index not found. Shall not happen");
ssize_t index = ((size_t)item - (size_t)_atlasIndexArray->arr) / sizeof(void*);
return index;
}
ssize_t TMXLayer2::atlasIndexForNewZ(int z)
{
// XXX: This can be improved with a sort of binary search
ssize_t i=0;
for (i=0; i< _atlasIndexArray->num ; i++)
{
ssize_t val = (size_t) _atlasIndexArray->arr[i];
if (z < val)
{
break;
}
}
return i;
}
// TMXLayer2 - adding / remove tiles
void TMXLayer2::setTileGID(int gid, const Point& pos)
{
setTileGID(gid, pos, (ccTMXTileFlags)0);
}
void TMXLayer2::setTileGID(int gid, const Point& pos, ccTMXTileFlags flags)
{
}
//CCTMXLayer2 - obtaining positions, offset //CCTMXLayer2 - obtaining positions, offset
Point TMXLayer2::calculateLayerOffset(const Point& pos) Point TMXLayer2::calculateLayerOffset(const Point& pos)
@ -552,80 +477,6 @@ Point TMXLayer2::calculateLayerOffset(const Point& pos)
return ret; return ret;
} }
Point TMXLayer2::getPositionAt(const Point& pos)
{
Point ret = Point::ZERO;
switch (_layerOrientation)
{
case TMXOrientationOrtho:
ret = getPositionForOrthoAt(pos);
break;
case TMXOrientationIso:
ret = getPositionForIsoAt(pos);
break;
case TMXOrientationHex:
ret = getPositionForHexAt(pos);
break;
}
ret = CC_POINT_PIXELS_TO_POINTS( ret );
return ret;
}
Point TMXLayer2::getPositionForOrthoAt(const Point& pos)
{
return Point(pos.x * _mapTileSize.width,
(_layerSize.height - pos.y - 1) * _mapTileSize.height);
}
Point TMXLayer2::getPositionForIsoAt(const Point& pos)
{
return Point(_mapTileSize.width /2 * (_layerSize.width + pos.x - pos.y - 1),
_mapTileSize.height /2 * ((_layerSize.height * 2 - pos.x - pos.y) - 2));
}
Point TMXLayer2::getPositionForHexAt(const Point& pos)
{
float diffY = 0;
if ((int)pos.x % 2 == 1)
{
diffY = -_mapTileSize.height/2 ;
}
Point xy = Point(pos.x * _mapTileSize.width*3/4,
(_layerSize.height - pos.y - 1) * _mapTileSize.height + diffY);
return xy;
}
float TMXLayer2::getVertexZForPos(const Point& pos)
{
float ret = 0;
float maxVal = 0;
if (_useAutomaticVertexZ)
{
switch (_layerOrientation)
{
case TMXOrientationIso:
maxVal = _layerSize.width + _layerSize.height;
ret = -(maxVal - (pos.x + pos.y));
break;
case TMXOrientationOrtho:
ret = -(_layerSize.height-pos.y);
break;
case TMXOrientationHex:
CCASSERT(false, "TMX Hexa zOrder not supported");
break;
default:
CCASSERT(false, "TMX invalid value");
break;
}
}
else
{
ret = _vertexZvalue;
}
return ret;
}
std::string TMXLayer2::getDescription() const std::string TMXLayer2::getDescription() const
{ {

View File

@ -213,16 +213,13 @@ protected:
void setupIndices(); void setupIndices();
void setupVertices(); void setupVertices();
void setupVBO(); void setupVBO();
void setVerticesForPos(int x, int y, GLfloat *xpos0, GLfloat *xpos1, GLfloat *ypos0, GLfloat *ypos1);
Point getPositionForIsoAt(const Point& pos); int getTileIndex(int x, int y, Point base);
Point getPositionForOrthoAt(const Point& pos);
Point getPositionForHexAt(const Point& pos);
Point calculateLayerOffset(const Point& offset); Point calculateLayerOffset(const Point& offset);
/* The layer recognizes some special properties, like cc_vertez */ /* The layer recognizes some special properties, like cc_vertez */
void parseInternalProperties(); void parseInternalProperties();
float getVertexZForPos(const Point& pos);
void onDraw(); void onDraw();

View File

@ -283,7 +283,8 @@ TMXOrthoTest::TMXOrthoTest()
//auto color = LayerColor::create( Color4B(64,64,64,255) ); //auto color = LayerColor::create( Color4B(64,64,64,255) );
//addChild(color, -1); //addChild(color, -1);
auto map = TMXTiledMap2::create("TileMaps/orthogonal-test2.tmx"); auto map = TMXTiledMap2::create("TileMaps/iso-test.tmx");
// auto map = TMXTiledMap2::create("TileMaps/orthogonal-test2.tmx");
addChild(map, 0, kTagTileMap); addChild(map, 0, kTagTileMap);
Size CC_UNUSED s = map->getContentSize(); Size CC_UNUSED s = map->getContentSize();