Cocos2d notes(6) Tiled Map
六月 15th, 2011
Cocos2D
1 2 3 4 5 6 7 8 9 | CCTMXTiledMap* tileMap = [CCTMXTiledMap tiledMapWithTMXFile:@"orthogonal.tmx"]; [self addChild:tileMap z:-1 tag:TileMapNode]; // Use a negative offset to set the tilemap's start position //tileMap.position = CGPointMake(-160, -120); // hide the event layer, we only need this information for code, not to display it CCTMXLayer* eventLayer = [tileMap layerNamed:@"GameEventLayer"]; eventLayer.visible = NO; |
判断区域–1
获得map上的坐标
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | -(CGPoint) locationFromTouch:(UITouch*)touch { CGPoint touchLocation = [touch locationInView: [touch view]]; return [[CCDirector sharedDirector] convertToGL:touchLocation]; } -(CGPoint) locationFromTouches:(NSSet*)touches { return [self locationFromTouch:[touches anyObject]]; } -(CGPoint) tilePosFromLocation:(CGPoint)location tileMap:(CCTMXTiledMap*)tileMap { // Tilemap position must be subtracted, in case the tilemap position is not at 0,0 due to scrolling CGPoint pos = ccpSub(location, tileMap.position); // Cast to int makes sure that result is in whole numbers, tile coordinates will be used as array indices pos.x = (int)(pos.x / tileMap.tileSize.width); pos.y = (int)((tileMap.mapSize.height * tileMap.tileSize.height - pos.y) / tileMap.tileSize.height); CCLOG(@"touch at (%.0f, %.0f) is at tileCoord (%i, %i)", location.x, location.y, (int)pos.x, (int)pos.y); NSAssert(pos.x >= 0 && pos.y >= 0 && pos.x < tileMap.mapSize.width && pos.y < tileMap.mapSize.height, @"%@: coordinates (%i, %i) out of bounds!", NSStringFromSelector(_cmd), (int)pos.x, (int)pos.y); return pos; } -(void) ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { CCNode* node = [self getChildByTag:TileMapNode]; NSAssert([node isKindOfClass:[CCTMXTiledMap class]], @"not a CCTMXTiledMap"); CCTMXTiledMap* tileMap = (CCTMXTiledMap*)node; // get the position in tile coordinates from the touch location CGPoint touchLocation = [self locationFromTouches:touches]; CGPoint tilePos = [self tilePosFromLocation:touchLocation tileMap:tileMap]; // Check if the touch was on water (eg. tiles with isWater property drawn in GameEventLayer) bool isTouchOnWater = NO; CCTMXLayer* eventLayer = [tileMap layerNamed:@"GameEventLayer"]; int tileGID = [eventLayer tileGIDAt:tilePos]; if (tileGID != 0) { NSDictionary* properties = [tileMap propertiesForGID:tileGID]; if (properties) { CCLOG(@"NSDictionary 'properties' contains:\n%@", properties); NSString* isWaterProperty = [properties valueForKey:@"isWater"]; isTouchOnWater = ([isWaterProperty boolValue] == YES); } } // decide what to do depending on where the touch was ... if (isTouchOnWater) { [[SimpleAudioEngine sharedEngine] playEffect:@"alien-sfx.caf"]; } else { // get the winter layer and toggle its visibility CCTMXLayer* winterLayer = [tileMap layerNamed:@"WinterLayer"]; winterLayer.visible = !winterLayer.visible; // remove the touched tile //[winterLayer removeTileAt:tilePos]; // adds a given tile //tileGID = [winterLayer tileGIDAt:CGPointMake(0, 19)]; //[winterLayer setTileGID:tileGID at:tilePos]; } } |
判断区域–2
1 2 3 4 5 6 7 8 9 10 | -(CGRect) getRectFromObjectProperties:(NSDictionary*)dict tileMap:(CCTMXTiledMap*)tileMap { float x, y, width, height; x = [[dict valueForKey:@"x"] floatValue] + tileMap.position.x; y = [[dict valueForKey:@"y"] floatValue] + tileMap.position.y; width = [[dict valueForKey:@"width"] floatValue]; height = [[dict valueForKey:@"height"] floatValue]; return CGRectMake(x, y, width, height); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | // Check if the touch was within one of the rectangle objects CCTMXObjectGroup* objectLayer = [tileMap objectGroupNamed:@"ObjectLayer"]; NSAssert([objectLayer isKindOfClass:[CCTMXObjectGroup class]], @"ObjectLayer not found or not a CCTMXObjectGroup"); bool isTouchInRectangle = NO; int numObjects = [objectLayer.objects count]; for (int i = 0; i < numObjects; i++) { NSDictionary* properties = [objectLayer.objects objectAtIndex:i]; CGRect rect = [self getRectFromObjectProperties:properties tileMap:tileMap]; if (CGRectContainsPoint(rect, touchLocation)) { isTouchInRectangle = YES; break; } } // decide what to do depending on where the touch was ... if (isTouchOnWater) { [[SimpleAudioEngine sharedEngine] playEffect:@"alien-sfx.caf"]; } else if (isTouchInRectangle) { CCParticleSystem* system = [CCQuadParticleSystem particleWithFile:@"fx-explosion.plist"]; system.autoRemoveOnFinish = YES; system.position = touchLocation; [self addChild:system z:1]; } else { // get the winter layer and toggle its visibility CCTMXLayer* winterLayer = [tileMap layerNamed:@"WinterLayer"]; winterLayer.visible = !winterLayer.visible; // remove the touched tile //[winterLayer removeTileAt:tilePos]; // adds a given tile //tileGID = [winterLayer tileGIDAt:CGPointMake(0, 19)]; //[winterLayer setTileGID:tileGID at:tilePos]; } |
移动视点到点击位置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | // move tilemap so that touched tiles is at center of screen [self centerTileMapOnTileCoord:tilePos tileMap:tileMap]; -(void) centerTileMapOnTileCoord:(CGPoint)tilePos tileMap:(CCTMXTiledMap*)tileMap { // center tilemap on the given tile pos CGSize screenSize = [[CCDirector sharedDirector] winSize]; CGPoint screenCenter = CGPointMake(screenSize.width * 0.5f, screenSize.height * 0.5f); // tile coordinates are counted from upper left corner, this maps coordinates to lower left corner tilePos.y = (tileMap.mapSize.height - 1) - tilePos.y; // point is now at lower left corner of the screen CGPoint scrollPosition = CGPointMake(-(tilePos.x * tileMap.tileSize.width), -(tilePos.y * tileMap.tileSize.height)); // offset point to center of screen and center of tile scrollPosition.x += screenCenter.x - tileMap.tileSize.width * 0.5f; scrollPosition.y += screenCenter.y - tileMap.tileSize.height * 0.5f; // make sure tilemap scrolling stops at the tilemap borders scrollPosition.x = MIN(scrollPosition.x, 0); scrollPosition.x = MAX(scrollPosition.x, -screenSize.width); scrollPosition.y = MIN(scrollPosition.y, 0); scrollPosition.y = MAX(scrollPosition.y, -screenSize.height); CCLOG(@"tilePos: (%i, %i) moveTo: (%.0f, %.0f)", (int)tilePos.x, (int)tilePos.y, scrollPosition.x, scrollPosition.y); CCAction* move = [CCMoveTo actionWithDuration:0.2f position:scrollPosition]; [tileMap stopAllActions]; [tileMap runAction:move]; } |
45度角地图
不能使用CC_DIRECTOR_INIT();
创建部分重写
1 2 3 4 5 6 7 8 9 10 11 | window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; if ([CCDirector setDirectorType:kCCDirectorTypeDisplayLink] == NO) [CCDirector setDirectorType:kCCDirectorTypeNSTimer]; CCDirector *director = [CCDirector sharedDirector]; [director setAnimationInterval:1.0/60]; EAGLView *glView = [EAGLView viewWithFrame:[window bounds] pixelFormat:kEAGLColorFormatRGB565 depthFormat:GL_DEPTH_COMPONENT24_OES preserveBackbuffer:NO]; [director setProjection:kCCDirectorProjection2D]; |
45度角地图获取点击位置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | -(CGPoint) tilePosFromLocation:(CGPoint)location tileMap:(CCTMXTiledMap*)tileMap { // Tilemap position must be subtracted, in case the tilemap position is not at 0,0 due to scrolling CGPoint pos = ccpSub(location, tileMap.position); float halfMapWidth = tileMap.mapSize.width * 0.5f; float mapHeight = tileMap.mapSize.height; float tileWidth = tileMap.tileSize.width; float tileHeight = tileMap.tileSize.height; CGPoint tilePosDiv = CGPointMake(pos.x / tileWidth, pos.y / tileHeight); float inverseTileY = mapHeight - tilePosDiv.y; // Cast to int makes sure that result is in whole numbers, tile coordinates will be used as array indices float posX = (int)(inverseTileY + tilePosDiv.x - halfMapWidth); float posY = (int)(inverseTileY - tilePosDiv.x + halfMapWidth); // make sure coordinates are within isomap bounds posX = MAX(0, posX); posX = MIN(tileMap.mapSize.width - 1, posX); posY = MAX(0, posY); posY = MIN(tileMap.mapSize.height - 1, posY); pos = CGPointMake(posX, posY); CCLOG(@"touch at (%.0f, %.0f) is at tileCoord (%i, %i)", location.x, location.y, (int)pos.x, (int)pos.y); //CCLOG(@"\tinverseY: %.2f -- tilePosDiv: (%.2f, %.2f) -- halfMapWidth: %.0f\n", inverseTileY, tilePosDiv.x, tilePosDiv.y, halfMapWidth); return pos; } |
滚动地图
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | -(void) centerTileMapOnTileCoord:(CGPoint)tilePos tileMap:(CCTMXTiledMap*)tileMap { // center tilemap on the given tile pos CGSize screenSize = [[CCDirector sharedDirector] winSize]; CGPoint screenCenter = CGPointMake(screenSize.width * 0.5f, screenSize.height * 0.5f); // get the ground layer CCTMXLayer* layer = [tileMap layerNamed:@"Ground"]; NSAssert(layer != nil, @"Ground layer not found!"); // internally tile Y coordinates are off by 1, this fixes the returned pixel coordinates tilePos.y -= 1; // get the pixel coordinates for a tile at these coordinates CGPoint scrollPosition = [layer positionAt:tilePos]; // negate the position for scrolling scrollPosition = ccpMult(scrollPosition, -1); // add offset to screen center scrollPosition = ccpAdd(scrollPosition, screenCenter); CCLOG(@"tilePos: (%i, %i) moveTo: (%.0f, %.0f)", (int)tilePos.x, (int)tilePos.y, scrollPosition.x, scrollPosition.y); CCAction* move = [CCMoveTo actionWithDuration:0.2f position:scrollPosition]; [tileMap stopAllActions]; [tileMap runAction:move]; } |
给地图添加一个宽度10的边框后修正的位置
1 2 3 4 5 6 7 8 9 | const int borderSize = 10; playableAreaMin = CGPointMake(borderSize, borderSize); playableAreaMax = CGPointMake(tileMap.mapSize.width - 1 - borderSize, tileMap.mapSize.height - 1 - borderSize); // make sure coordinates are within bounds of the playable area posX = MAX(playableAreaMin.x, posX); posX = MIN(playableAreaMax.x, posX); posY = MAX(playableAreaMin.y, posY); posY = MIN(playableAreaMax.y, posY); |
添加player
1 2 3 4 5 6 7 | #import <Foundation/Foundation.h> #import "cocos2d.h" @interface Player : CCSprite { } +(id) player; @end |
1 2 3 4 5 6 | // Create the player and add it player = [Player player]; player.position = CGPointMake(screenSize.width / 2, screenSize.height / 2); // approximately position player's texture to best match the tile center position player.anchorPoint = CGPointMake(0.3f, 0.1f); [self addChild:player]; |
player和遮挡的关系
1 2 3 4 5 6 | -(void) updateVertexZ:(CGPoint)tilePos tileMap:(CCTMXTiledMap*)tileMap { float lowestZ = -(tileMap.mapSize.width + tileMap.mapSize.height); float currentZ = tilePos.x + tilePos.y; self.vertexZ = lowestZ + currentZ - 1; } |

