Created
March 22, 2012 00:09
-
-
Save rakkarage/2154328 to your computer and use it in GitHub Desktop.
HKTMXTiledMap: anytime onetime animations
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* HKTMXTiledMap | |
* | |
* cocos2d-extensions | |
* https://github.com/cocos2d/cocos2d-iphone-extensions | |
* | |
* HKASoftware | |
* http://hkasoftware.com | |
* | |
* Copyright (c) 2011 HKASoftware | |
* | |
* 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. | |
* | |
* TMX Tiled Map support: | |
* http://www.mapeditor.org | |
* | |
*/ | |
#import "HKTMXLayer.h" | |
#import "CCTMXTiledMap.h" | |
#import "CCTMXXMLParser.h" | |
#import "CCTextureCache.h" | |
#import "CCDirector.h" | |
#import "CGPointExtension.h" | |
#import "ccMacros.h" | |
#import "CCSprite.h" | |
#pragma mark - | |
#pragma mark HKTMXLayer | |
@interface HKTMXLayer (Private) | |
-(CGPoint) positionForOrthoAt:(CGPoint)pos; | |
-(CGPoint) calculateLayerOffset:(CGPoint)offset; | |
/* The layer recognizes some special properties, like cc_vertez */ | |
-(void) parseInternalProperties; | |
@end | |
@implementation HKTMXLayer | |
@synthesize layerSize = layerSize_, layerName = layerName_, tiles=tiles_; | |
@synthesize tileset=tileset_; | |
@synthesize layerOrientation=layerOrientation_; | |
@synthesize mapTileSize=mapTileSize_; | |
@synthesize properties=properties_; | |
@synthesize opacity=opacity_; | |
@synthesize color=color_; | |
@synthesize blendFunc = blendFunc_; | |
#pragma mark CCTMXLayer - init & alloc & dealloc | |
+(id) layerWithTilesetInfo:(CCTMXTilesetInfo*)tilesetInfo layerInfo:(CCTMXLayerInfo*)layerInfo mapInfo:(CCTMXMapInfo*)mapInfo | |
{ | |
return [[[self alloc] initWithTilesetInfo:tilesetInfo layerInfo:layerInfo mapInfo:mapInfo] autorelease]; | |
} | |
-(id) initWithTilesetInfo:(CCTMXTilesetInfo*)tilesetInfo layerInfo:(CCTMXLayerInfo*)layerInfo mapInfo:(CCTMXMapInfo*)mapInfo | |
{ | |
// JEB - A layer must have at least one tile to be able to associated a tileset spritesheet with it. | |
// This tile can be always be cleared with removeTileAt: after initialisation. | |
NSAssert1((tilesetInfo != nil), @"TMX Layer '%@' has no associated tileset", layerInfo.name); | |
if((self=[super init])) | |
{ | |
// JEB - default blend function | |
blendFunc_ = (ccBlendFunc) { CC_BLEND_SRC, CC_BLEND_DST }; | |
// JEB - default colour | |
color_.r = 255; | |
color_.g = 255; | |
color_.b = 255; | |
texture_ = [[CCTextureCache sharedTextureCache] addImage:tilesetInfo.sourceImage]; | |
tilesetInfo.imageSize = texture_.contentSizeInPixels; | |
// layerInfo | |
layerName_ = [layerInfo.name copy]; | |
layerSize_ = layerInfo.layerSize; | |
tiles_ = layerInfo.tiles; | |
minGID_ = tilesetInfo.firstGid; | |
maxGID_ = minGID_ | |
+ (tilesetInfo.imageSize.width - tilesetInfo.margin * 2 + tilesetInfo.spacing) | |
/ (tilesetInfo.tileSize.width + tilesetInfo.spacing) | |
* (tilesetInfo.imageSize.height - tilesetInfo.margin * 2 + tilesetInfo.spacing) | |
/ (tilesetInfo.tileSize.height + tilesetInfo.spacing) | |
- 1; | |
opacity_ = layerInfo.opacity; | |
properties_ = [layerInfo.properties mutableCopy]; | |
// tilesetInfo | |
tileset_ = [tilesetInfo retain]; | |
// mapInfo | |
mapTileSize_ = mapInfo.tileSize; | |
layerOrientation_ = mapInfo.orientation; | |
// offset (after layer orientation is set); | |
CGPoint offset = [self calculateLayerOffset:layerInfo.offset]; | |
[self setPositionInPixels:offset]; | |
[self setContentSizeInPixels: CGSizeMake( layerSize_.width * mapTileSize_.width, layerSize_.height * mapTileSize_.height )]; | |
// adjust and validate tile IDs | |
NSAssert1(minGID_ <= maxGID_ + 1 && maxGID_ - minGID_ < 1000000, | |
@"TMX: Bad minGID/maxGID for layer %@", layerName_); | |
int tileCount = layerSize_.height * layerSize_.width; | |
for(int i=0; i < tileCount; i++) | |
{ | |
#ifdef __BIG_ENDIAN__ | |
tiles_[i] = CFSwapInt32(tiles_[i]); | |
#endif | |
// JEB flip bits masked to compare true GID | |
NSAssert((tiles_[i] & kFlippedMask) == 0 || | |
(((tiles_[i] & kFlippedMask) >= minGID_) && ((tiles_[i] & kFlippedMask) <= maxGID_)), | |
@"TMX: Only one tileset per layer is supported"); | |
} | |
CGSize screenSize = [CCDirector sharedDirector].winSizeInPixels; | |
// JEB - Added support for tilemap scaling | |
screenGridSize_.width = (ceil(screenSize.width / (mapTileSize_.width * HKTMX_LAYER_SCALE_LIMIT)) + 1); | |
screenGridSize_.height = (ceil(screenSize.height / (mapTileSize_.height * HKTMX_LAYER_SCALE_LIMIT)) + 1); | |
zoomGridSize_ = screenGridSize_; | |
int screenTileCount = screenGridSize_.width * screenGridSize_.height; | |
// create buffer objects | |
glGenBuffers(3, buffers_); | |
// generate a static vertex array covering the screen | |
glBindBuffer(GL_ARRAY_BUFFER, buffers_[0]); | |
glBufferData(GL_ARRAY_BUFFER, screenTileCount * 4 * 2 * sizeof(GLfloat), NULL, GL_STATIC_DRAW); | |
#if __IPHONE_OS_VERSION_MAX_ALLOWED | |
GLfloat *screenGrid = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES); | |
#elif __MAC_OS_X_VERSION_MAX_ALLOWED | |
GLfloat *screenGrid = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); | |
#endif | |
GLfloat *tilePtr = screenGrid; | |
for (int y=0; y < screenGridSize_.height; 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) | |
{ | |
GLfloat xpos_0 = mapTileSize_.width * x; | |
GLfloat xpos_1 = mapTileSize_.width * (x+1); | |
// define the points of a quad here; we'll use the index buffer to make them triangles | |
tilePtr[0] = xpos_0; | |
tilePtr[1] = ypos_0; | |
tilePtr[2] = xpos_1; | |
tilePtr[3] = ypos_0; | |
tilePtr[4] = xpos_0; | |
tilePtr[5] = ypos_1; | |
tilePtr[6] = xpos_1; | |
tilePtr[7] = ypos_1; | |
} | |
} | |
#if __IPHONE_OS_VERSION_MAX_ALLOWED | |
glUnmapBufferOES(GL_ARRAY_BUFFER); | |
#elif __MAC_OS_X_VERSION_MAX_ALLOWED | |
glUnmapBuffer(GL_ARRAY_BUFFER); | |
#endif | |
// allocate texcoord buffer | |
glBindBuffer(GL_ARRAY_BUFFER, buffers_[1]); | |
glBufferData(GL_ARRAY_BUFFER, screenTileCount * 4 * 2 * sizeof(GLfloat), NULL, GL_DYNAMIC_DRAW); | |
// allocate index buffer | |
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers_[2]); | |
glBufferData(GL_ELEMENT_ARRAY_BUFFER, screenTileCount * 6 * sizeof(GLushort), NULL, GL_DYNAMIC_DRAW); | |
glBindBuffer(GL_ARRAY_BUFFER, 0); | |
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); | |
// --= set up animations =-- | |
// XXX should belong to tileset or map to avoid redundancy | |
__block int animCount = 0; | |
// read relevant tile properties from the map | |
animRules_ = calloc(maxGID_ - minGID_ + 1, sizeof *animRules_); | |
animCache_ = calloc(maxGID_ - minGID_ + 1, sizeof *animCache_); | |
#if NS_BLOCKS_AVAILABLE | |
[mapInfo.tileProperties enumerateKeysAndObjectsUsingBlock: | |
^(id key, id obj, BOOL *stop) | |
{ | |
unsigned int idx = [key unsignedIntValue] - minGID_; | |
if (idx > maxGID_) return; | |
unsigned int next = [[obj objectForKey:@"Next"] intValue]; | |
double delay = [[obj objectForKey:@"Delay"] doubleValue]; | |
if (next && delay > 0) { | |
animRules_[idx].delay = delay; | |
animRules_[idx].next = next; | |
animCount++; | |
} | |
}]; | |
#else | |
for(id key in [mapInfo.tileProperties keyEnumerator]) | |
{ | |
unsigned int idx = [key unsignedIntValue] - minGID_; | |
if (idx > maxGID_) continue; | |
id obj = [mapInfo.tileProperties objectForKey:key]; | |
unsigned int next = [[obj objectForKey:@"Next"] intValue]; | |
double delay = [[obj objectForKey:@"Delay"] doubleValue]; | |
if (next && delay > 0) { | |
animRules_[idx].delay = delay; | |
animRules_[idx].next = next; | |
animCount++; | |
} | |
} | |
#endif | |
// find animation cycles and annotate | |
for (int gid=minGID_; gid <= maxGID_; gid++) | |
{ | |
struct HKTMXAnimRule *rule = animRules_ + (gid - minGID_); | |
if (!rule->next) | |
{ | |
// no animation here | |
rule->last = gid; | |
} | |
else if (!rule->cycleTime && !rule->last) | |
{ | |
animCount++; | |
rule->cycleTime = rule->delay; | |
unsigned int state = rule->next; | |
while (1) | |
{ | |
// found loop | |
if (state == gid) break; | |
// found endpoint | |
if (!animRules_[state - minGID_].next) | |
{ | |
rule->last = state; | |
break; | |
} | |
// keep looking | |
rule->cycleTime += animRules_[state - minGID_].delay; | |
state = animRules_[state - minGID_].next; | |
} | |
// XXX propagate result forward through the cycle to avoid quadratic startup lag | |
} | |
} | |
animClock_ = 0.0; | |
dirtyAt_ = -INFINITY; | |
if (animCount > 0) | |
[self scheduleUpdate]; | |
} | |
return self; | |
} | |
- (void) dealloc | |
{ | |
glDeleteBuffers(3, buffers_); | |
[layerName_ release]; | |
[tileset_ release]; | |
[properties_ release]; | |
free(tiles_); | |
free(animRules_); | |
free(animCache_); | |
[super dealloc]; | |
} | |
- (void) update: (ccTime) delta | |
{ | |
animClock_ += delta; | |
} | |
#pragma mark CCTMXLayer - setup Tiles | |
-(void) setupTiles | |
{ | |
// Parse cocos2d properties | |
[self parseInternalProperties]; | |
} | |
#pragma mark CCTMXLayer - Properties | |
-(id) propertyNamed:(NSString *)propertyName | |
{ | |
return [properties_ valueForKey:propertyName]; | |
} | |
-(void) parseInternalProperties | |
{ | |
} | |
#pragma mark CCTMXLayer - obtaining tiles/gids | |
-(uint32_t) tileGIDAt:(CGPoint)pos | |
{ | |
NSAssert( pos.x < layerSize_.width && pos.y < layerSize_.height && pos.x >=0 && pos.y >=0, @"TMXLayer: invalid position"); | |
// NSAssert( tiles_ && atlasIndexArray_, @"TMXLayer: the tiles map has been released"); | |
NSInteger idx = pos.x + pos.y * layerSize_.width; | |
// JEB - Return true GID | |
return (tiles_[ idx ] & kFlippedMask); | |
} | |
// JEB - Returns flipbits of tile at coords | |
-(unsigned int) tileFlipBitsAt:(CGPoint)pos | |
{ | |
NSAssert( pos.x < layerSize_.width && pos.y < layerSize_.height && pos.x >=0 && pos.y >=0, @"TMXLayer: invalid position"); | |
NSInteger idx = pos.x + pos.y * layerSize_.width; | |
return (tiles_[ idx ] & kGIDMask); | |
} | |
#pragma mark CCTMXLayer - adding / remove tiles | |
static double startTime = 0.0; | |
// JEB - Change GID at location. Flip bits preserved | |
-(void) setTileGID:(unsigned int)gid at:(CGPoint)pos | |
{ | |
NSAssert( pos.x < layerSize_.width && pos.y < layerSize_.height && pos.x >=0 && pos.y >=0, @"TMXLayer: invalid position"); | |
NSAssert1(gid == 0 || (gid >= minGID_ && gid <= maxGID_), @"invalid gid (%u) for tileset", gid); | |
int idx = (int)pos.y * (int)layerSize_.width + pos.x; | |
unsigned int flipbits = tiles_[idx] & kGIDMask; | |
tiles_[idx] = flipbits | gid; | |
dirtyAt_ = -INFINITY; | |
int temp = tiles_[idx]; | |
unsigned int tile_noflags = (temp & kFlippedMask); | |
struct HKTMXAnimCacheEntry *AC = animCache_ - minGID_; | |
struct HKTMXAnimRule *AR = animRules_ - minGID_; | |
struct HKTMXAnimRule *ar = &AR[tile_noflags]; if (ar) {} | |
struct HKTMXAnimCacheEntry *ac = &AC[tile_noflags]; if (ac) {} | |
if (ar->delay && ar->next) | |
{ | |
startTime = animClock_; | |
ac->state = gid; | |
ac->validUntil = -INFINITY; | |
} | |
} | |
// JEB - Change the flip bits at location | |
-(void) setTileFlipBits:(unsigned int)flipbits at:(CGPoint)pos | |
{ | |
NSAssert( pos.x < layerSize_.width && pos.y < layerSize_.height && pos.x >=0 && pos.y >=0, @"TMXLayer: invalid position"); | |
NSAssert(!((flipbits & kFlippedMask) || ((flipbits & ~kFlippedMask)==~kFlippedMask) ), @"invalid flipbits"); | |
int idx = (int)pos.y * (int)layerSize_.width + pos.x; | |
unsigned int gid = tiles_[idx] & kFlippedMask; | |
tiles_[idx] = flipbits | gid; | |
dirtyAt_ = -INFINITY; | |
} | |
// JEB - Although sprite tiles can be added though setTile:at: I have left this | |
// to prevent abuse. | |
-(void) addChild: (CCNode*)node z:(NSInteger)z tag:(NSInteger)tag | |
{ | |
NSAssert(NO, @"addChild: is not supported on CCTMXLayer. Instead use setTileGID:at:/tileGIDAt:"); | |
} | |
// JEB - Ensured both flip bits and GID are cleared. | |
-(void) removeTileAt:(CGPoint)pos | |
{ | |
[self setTileGID:0 at:pos]; | |
[self setTileFlipBits:0 at:pos]; | |
} | |
#pragma mark CCTMXLayer - obtaining positions, offset | |
-(CGPoint) calculateLayerOffset:(CGPoint)pos | |
{ | |
CGPoint ret = CGPointZero; | |
switch( layerOrientation_ ) { | |
case CCTMXOrientationOrtho: | |
ret = ccp( pos.x * mapTileSize_.width, -pos.y *mapTileSize_.height); | |
break; | |
case CCTMXOrientationIso: | |
ret = ccp( (mapTileSize_.width /2) * (pos.x - pos.y), | |
(mapTileSize_.height /2 ) * (-pos.x - pos.y) ); | |
break; | |
case CCTMXOrientationHex: | |
NSAssert(CGPointEqualToPoint(pos, CGPointZero), @"offset for hexagonal map not implemented yet"); | |
break; | |
} | |
return ret; | |
} | |
-(CGPoint) positionAt:(CGPoint)pos | |
{ | |
CGPoint ret = CGPointZero; | |
switch( layerOrientation_ ) { | |
case CCTMXOrientationOrtho: | |
ret = [self positionForOrthoAt:pos]; | |
break; | |
} | |
return ret; | |
} | |
-(CGPoint) positionForOrthoAt:(CGPoint)pos | |
{ | |
int x = pos.x * mapTileSize_.width + 0.49f; | |
int y = (layerSize_.height - pos.y - 1) * mapTileSize_.height + 0.49f; | |
return ccp(x,y); | |
} | |
#pragma mark CCTMXLayer - draw | |
// updates grid based on a certain scale. This way you can optimize how much you want to draw. | |
// this is strictly for performance tuning based on your individual needs | |
-(void)updateScale:(float)s | |
{ | |
if(s >= HKTMX_LAYER_SCALE_LIMIT) | |
{ | |
CGSize screenSize = [CCDirector sharedDirector].winSizeInPixels; | |
zoomGridSize_.width = (ceil(screenSize.width / (mapTileSize_.width * s)) + 1); | |
zoomGridSize_.height = (ceil(screenSize.height / (mapTileSize_.height * s)) + 1); | |
} | |
else | |
{ | |
CCLOG(@"HKTMX: Warning layer scale passed HKTMX_LAYER_SCALE_LIMIT"); | |
} | |
} | |
-(void) draw | |
{ | |
// JEB Set Blend mode | |
BOOL newBlend = ((blendFunc_.src != CC_BLEND_SRC) || (blendFunc_.dst != CC_BLEND_DST)); | |
if( newBlend ) | |
{ | |
glBlendFunc( blendFunc_.src, blendFunc_.dst ); | |
} | |
else if( opacity_ != 255 ) | |
{ | |
newBlend = YES; | |
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | |
} | |
glBindTexture(GL_TEXTURE_2D, texture_.name); | |
// TODO: Do we EVER want a tiled map to be anti-aliased? | |
ccTexParams texParams = { GL_NEAREST, GL_NEAREST, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE }; | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, texParams.minFilter ); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, texParams.magFilter ); | |
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, texParams.wrapS ); | |
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, texParams.wrapT ); | |
glBindBuffer(GL_ARRAY_BUFFER, buffers_[0]); | |
glVertexPointer(2, GL_FLOAT, 0, NULL); | |
glBindBuffer(GL_ARRAY_BUFFER, buffers_[1]); | |
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers_[2]); | |
CGAffineTransform trans = [self worldToNodeTransform]; | |
CGPoint baseTile = CGPointMake(floor(trans.tx / (mapTileSize_.width)), | |
floor(trans.ty / (mapTileSize_.height))); | |
unsigned int vertexCount = 0; | |
if (dirtyAt_ > animClock_ && baseTile.x == lastBaseTile_.x && baseTile.y == lastBaseTile_.y) | |
{ | |
vertexCount = lastVertexCount_; | |
goto texdone; | |
} | |
dirtyAt_ = INFINITY; | |
struct HKTMXAnimRule *AR = animRules_ - minGID_; | |
struct HKTMXAnimCacheEntry *AC = animCache_ - minGID_; | |
#if __IPHONE_OS_VERSION_MAX_ALLOWED | |
GLfloat *texcoords = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES); | |
GLushort *indices = glMapBufferOES(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY_OES); | |
#elif __MAC_OS_X_VERSION_MAX_ALLOWED | |
GLfloat *texcoords = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); | |
GLushort *indices = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY); | |
#endif | |
CGSize texSize = tileset_.imageSize; | |
for (int y=0; y < zoomGridSize_.height; y++) | |
{ | |
if (baseTile.y + y < 0 || baseTile.y + y >= layerSize_.height) | |
continue; | |
for (int x=0; x < zoomGridSize_.width; x++) | |
{ | |
if (baseTile.x + x < 0 || baseTile.x + x >= layerSize_.width) | |
continue; | |
int tileidx = (layerSize_.height - (baseTile.y + y) - 1) * layerSize_.width | |
+ baseTile.x + x; | |
unsigned int tile = tiles_[tileidx]; | |
if (!tile) continue; | |
unsigned int showtile; | |
// *** JEB index does not included flip bits *** | |
unsigned int tile_noflags = (tile & kFlippedMask); | |
if (AC[tile_noflags].validUntil <= animClock_) | |
{ | |
CGFloat time = animClock_ - startTime; | |
if (AR[tile_noflags].last && time >= AR[tile_noflags].cycleTime) | |
{ | |
showtile = AR[tile_noflags].last; | |
AC[tile_noflags].state = showtile; | |
AC[tile_noflags].validUntil = INFINITY; | |
startTime = 0.0; | |
if (AR[tile_noflags].delay) | |
{ | |
[self removeTileAt:ccp(baseTile.x + x, layerSize_.height - (baseTile.y + y + 1))]; | |
} | |
} | |
else | |
{ | |
double phase = AR[tile_noflags].last ? time : fmod(animClock_, AR[tile_noflags].cycleTime); | |
showtile = tile_noflags; | |
while (phase > AR[showtile].delay) | |
{ | |
phase -= AR[showtile].delay; | |
showtile = AR[showtile].next; | |
} | |
AC[tile_noflags].state = showtile; | |
AC[tile_noflags].validUntil = animClock_ + AR[showtile].delay - phase; | |
} | |
} | |
else | |
showtile = AC[tile_noflags].state; | |
dirtyAt_ = MIN(dirtyAt_, AC[tile_noflags].validUntil); | |
int screenidx = (y * (screenGridSize_.width)) + x; | |
CGRect tileTexture = [tileset_ rectForGID:(showtile & kFlippedMask)]; | |
GLfloat *texbase = texcoords + screenidx * 4 * 2; | |
GLushort *idxbase = indices + vertexCount; | |
int vertexbase = screenidx * 4; | |
// **************************************** | |
// * JEB Handle flipped and rotated tiles * | |
// **************************************** | |
float left, right, top, bottom; | |
#if CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL | |
left = (2*tileTexture.origin.x + 1) / (2* texSize.width); | |
right = left + (2*tileTexture.size.width-2)/(2*texSize.width); | |
bottom = (2*tileTexture.origin.y+1) / (2*texSize.height); | |
top = bottom + (2*tileTexture.size.height-2)/(2*texSize.height); | |
#else | |
left = (tileTexture.origin.x / texSize.width); | |
right = left + (tileTexture.size.width / texSize.width); | |
bottom = (tileTexture.origin.y / texSize.width); | |
top = bottom + (tileTexture.size.height / texSize.width); | |
#endif | |
if (tile & kFlippedVerticallyFlag) | |
CC_SWAP(top,bottom); | |
if (tile & kFlippedHorizontallyFlag) | |
CC_SWAP(left,right); | |
if (tile & kFlippedDiagonallyFlag) | |
{ | |
texbase[0] = left; | |
texbase[1] = top; | |
texbase[2] = left; | |
texbase[3] = bottom; | |
texbase[4] = right; | |
texbase[5] = top; | |
texbase[6] = right; | |
texbase[7] = bottom; | |
} | |
else | |
{ | |
texbase[0] = left; | |
texbase[1] = top; | |
texbase[2] = right; | |
texbase[3] = top; | |
texbase[4] = left; | |
texbase[5] = bottom; | |
texbase[6] = right; | |
texbase[7] = bottom; | |
} | |
// ***************************** | |
idxbase[0] = vertexbase; | |
idxbase[1] = vertexbase + 1; | |
idxbase[2] = vertexbase + 2; | |
idxbase[3] = vertexbase + 3; | |
idxbase[4] = vertexbase + 2; | |
idxbase[5] = vertexbase + 1; | |
vertexCount += 6; | |
} | |
} | |
#if __IPHONE_OS_VERSION_MAX_ALLOWED | |
glUnmapBufferOES(GL_ARRAY_BUFFER); | |
glUnmapBufferOES(GL_ELEMENT_ARRAY_BUFFER); | |
#elif __MAC_OS_X_VERSION_MAX_ALLOWED | |
glUnmapBuffer(GL_ARRAY_BUFFER); | |
glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); | |
#endif | |
lastBaseTile_ = baseTile; | |
lastVertexCount_ = vertexCount; | |
texdone: | |
glPushMatrix(); | |
glTranslatef(baseTile.x * mapTileSize_.width, baseTile.y * mapTileSize_.height, 0); | |
glDisableClientState(GL_COLOR_ARRAY); | |
// JEB set layer tint and opacity | |
glColor4f(color_.r/255.0f, color_.g/255.0f, color_.b/255.0f, opacity_/255.0f); | |
glTexCoordPointer(2, GL_FLOAT, 0, NULL); | |
glDrawElements(GL_TRIANGLES, vertexCount, GL_UNSIGNED_SHORT, NULL); | |
glEnableClientState(GL_COLOR_ARRAY); | |
glPopMatrix(); | |
glBindBuffer(GL_ARRAY_BUFFER, 0); | |
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); | |
// JEB - Restore default blend | |
if( newBlend ) | |
glBlendFunc(CC_BLEND_SRC, CC_BLEND_DST); | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment