PageRenderTime 63ms CodeModel.GetById 33ms RepoModel.GetById 1ms app.codeStats 0ms

/CH14_code/Tilemap12/Classes/TileMapScene.m

https://bitbucket.org/akuandev/cocos2dsample
Objective C | 296 lines | 204 code | 59 blank | 33 comment | 20 complexity | 2c8f0cb058c24c9f20d91eab200d4697 MD5 | raw file
  1. //
  2. // HelloWorldLayer.m
  3. // Tilemap
  4. //
  5. // Created by Steffen Itterheim on 28.08.10.
  6. // Copyright Steffen Itterheim 2010. All rights reserved.
  7. //
  8. #import "TileMapScene.h"
  9. #import "Player.h"
  10. @implementation TileMapLayer
  11. +(id) scene
  12. {
  13. CCScene *scene = [CCScene node];
  14. TileMapLayer *layer = [TileMapLayer node];
  15. [scene addChild: layer];
  16. return scene;
  17. }
  18. -(id) init
  19. {
  20. if ((self = [super init]))
  21. {
  22. GameKitHelper* gkHelper = [GameKitHelper sharedGameKitHelper];
  23. gkHelper.delegate = self;
  24. [gkHelper authenticateLocalPlayer];
  25. CCTMXTiledMap* tileMap = [CCTMXTiledMap tiledMapWithTMXFile:@"isometric-with-border.tmx"];
  26. [self addChild:tileMap z:-1 tag:TileMapNode];
  27. CCTMXLayer* layer = [tileMap layerNamed:@"Collisions"];
  28. layer.visible = NO;
  29. // Use a negative offset to set the tilemap's start position
  30. tileMap.position = CGPointMake(-500, -500);
  31. self.isTouchEnabled = YES;
  32. // define the extents of the playable area in tile coordinates
  33. const int borderSize = 10;
  34. playableAreaMin = CGPointMake(borderSize, borderSize);
  35. playableAreaMax = CGPointMake(tileMap.mapSize.width - 1 - borderSize, tileMap.mapSize.height - 1 - borderSize);
  36. CGSize screenSize = [[CCDirector sharedDirector] winSize];
  37. // Create the player and add it
  38. player = [Player player];
  39. player.position = CGPointMake(screenSize.width / 2, screenSize.height / 2);
  40. // approximately position player's texture to best match the tile center position
  41. player.anchorPoint = CGPointMake(0.3f, 0.1f);
  42. [self addChild:player];
  43. // divide the screen into 4 areas
  44. screenCenter = CGPointMake(screenSize.width / 2, screenSize.height / 2);
  45. upperLeft = CGRectMake(0, screenCenter.y, screenCenter.x, screenCenter.y);
  46. lowerLeft = CGRectMake(0, 0, screenCenter.x, screenCenter.y);
  47. upperRight = CGRectMake(screenCenter.x, screenCenter.y, screenCenter.x, screenCenter.y);
  48. lowerRight = CGRectMake(screenCenter.x, 0, screenCenter.x, screenCenter.y);
  49. // to move in any of these directions means to add/subtract 1 to/from the current tile coordinate
  50. moveOffsets[MoveDirectionNone] = CGPointZero;
  51. moveOffsets[MoveDirectionUpperLeft] = CGPointMake(-1, 0);
  52. moveOffsets[MoveDirectionLowerLeft] = CGPointMake(0, 1);
  53. moveOffsets[MoveDirectionUpperRight] = CGPointMake(0, -1);
  54. moveOffsets[MoveDirectionLowerRight] = CGPointMake(1, 0);
  55. currentMoveDirection = MoveDirectionNone;
  56. // continuously check for walking
  57. [self scheduleUpdate];
  58. }
  59. return self;
  60. }
  61. -(void) dealloc
  62. {
  63. [super dealloc];
  64. }
  65. #pragma mark GameKitHelper delegate methods
  66. -(void) onLocalPlayerAuthenticationChanged
  67. {
  68. GKLocalPlayer* localPlayer = [GKLocalPlayer localPlayer];
  69. CCLOG(@"LocalPlayer isAuthenticated changed to: %@", localPlayer.authenticated ? @"YES" : @"NO");
  70. if (localPlayer.authenticated)
  71. {
  72. GameKitHelper* gkHelper = [GameKitHelper sharedGameKitHelper];
  73. [gkHelper getLocalPlayerFriends];
  74. //[gkHelper resetAchievements];
  75. }
  76. }
  77. -(void) onFriendListReceived:(NSArray*)friends
  78. {
  79. CCLOG(@"onFriendListReceived: %@", [friends description]);
  80. GameKitHelper* gkHelper = [GameKitHelper sharedGameKitHelper];
  81. [gkHelper getPlayerInfo:friends];
  82. }
  83. -(void) onPlayerInfoReceived:(NSArray*)players
  84. {
  85. CCLOG(@"onPlayerInfoReceived: %@", [players description]);
  86. GameKitHelper* gkHelper = [GameKitHelper sharedGameKitHelper];
  87. [gkHelper submitScore:1234 category:@"Playtime"];
  88. }
  89. -(void) onScoresSubmitted:(bool)success
  90. {
  91. CCLOG(@"onScoresSubmitted: %@", success ? @"YES" : @"NO");
  92. if (success)
  93. {
  94. GameKitHelper* gkHelper = [GameKitHelper sharedGameKitHelper];
  95. [gkHelper retrieveTopTenAllTimeGlobalScores];
  96. }
  97. }
  98. -(void) onScoresReceived:(NSArray*)scores
  99. {
  100. CCLOG(@"onScoresReceived: %@", [scores description]);
  101. GameKitHelper* gkHelper = [GameKitHelper sharedGameKitHelper];
  102. [gkHelper showLeaderboard];
  103. }
  104. -(void) onLeaderboardViewDismissed
  105. {
  106. CCLOG(@"onLeaderboardViewDismissed");
  107. }
  108. #pragma mark methods from previous chapters
  109. -(CGPoint) locationFromTouch:(UITouch*)touch
  110. {
  111. CGPoint touchLocation = [touch locationInView: [touch view]];
  112. return [[CCDirector sharedDirector] convertToGL:touchLocation];
  113. }
  114. -(CGPoint) locationFromTouches:(NSSet*)touches
  115. {
  116. return [self locationFromTouch:[touches anyObject]];
  117. }
  118. -(bool) isTilePosBlocked:(CGPoint)tilePos tileMap:(CCTMXTiledMap*)tileMap
  119. {
  120. CCTMXLayer* layer = [tileMap layerNamed:@"Collisions"];
  121. NSAssert(layer != nil, @"Collisions layer not found!");
  122. bool isBlocked = NO;
  123. unsigned int tileGID = [layer tileGIDAt:tilePos];
  124. if (tileGID > 0)
  125. {
  126. NSDictionary* tileProperties = [tileMap propertiesForGID:tileGID];
  127. id blocks_movement = [tileProperties objectForKey:@"blocks_movement"];
  128. isBlocked = (blocks_movement != nil);
  129. }
  130. return isBlocked;
  131. }
  132. -(CGPoint) ensureTilePosIsWithinBounds:(CGPoint)tilePos
  133. {
  134. // make sure coordinates are within bounds of the playable area
  135. tilePos.x = MAX(playableAreaMin.x, tilePos.x);
  136. tilePos.x = MIN(playableAreaMax.x, tilePos.x);
  137. tilePos.y = MAX(playableAreaMin.y, tilePos.y);
  138. tilePos.y = MIN(playableAreaMax.y, tilePos.y);
  139. return tilePos;
  140. }
  141. -(CGPoint) floatingTilePosFromLocation:(CGPoint)location tileMap:(CCTMXTiledMap*)tileMap
  142. {
  143. // Tilemap position must be added as an offset, in case the tilemap position is not at 0,0 due to scrolling
  144. CGPoint pos = ccpSub(location, tileMap.position);
  145. float halfMapWidth = tileMap.mapSize.width * 0.5f;
  146. float mapHeight = tileMap.mapSize.height;
  147. float tileWidth = tileMap.tileSize.width / CC_CONTENT_SCALE_FACTOR();
  148. float tileHeight = tileMap.tileSize.height / CC_CONTENT_SCALE_FACTOR();
  149. CGPoint tilePosDiv = CGPointMake(pos.x / tileWidth, pos.y / tileHeight);
  150. float mapHeightDiff = mapHeight - tilePosDiv.y;
  151. // Cast to int makes sure that result is in whole numbers, tile coordinates will be used as array indices
  152. float posX = (mapHeightDiff + tilePosDiv.x - halfMapWidth);
  153. float posY = (mapHeightDiff - tilePosDiv.x + halfMapWidth);
  154. return CGPointMake(posX, posY);
  155. }
  156. -(CGPoint) tilePosFromLocation:(CGPoint)location tileMap:(CCTMXTiledMap*)tileMap
  157. {
  158. CGPoint pos = [self floatingTilePosFromLocation:location tileMap:tileMap];
  159. // make sure coordinates are within bounds of the playable area, and cast to int
  160. pos = [self ensureTilePosIsWithinBounds:CGPointMake((int)pos.x, (int)pos.y)];
  161. //CCLOG(@"touch at (%.0f, %.0f) is at tileCoord (%i, %i)", location.x, location.y, (int)pos.x, (int)pos.y);
  162. return pos;
  163. }
  164. -(void) centerTileMapOnTileCoord:(CGPoint)tilePos tileMap:(CCTMXTiledMap*)tileMap
  165. {
  166. // get the ground layer
  167. CCTMXLayer* layer = [tileMap layerNamed:@"Ground"];
  168. NSAssert(layer != nil, @"Ground layer not found!");
  169. // internally tile Y coordinates seem to be off by 1, this fixes the returned pixel coordinates
  170. tilePos.y -= 1;
  171. // get the pixel coordinates for a tile at these coordinates
  172. CGPoint scrollPosition = [layer positionAt:tilePos];
  173. // negate the position for scrolling
  174. scrollPosition = ccpMult(scrollPosition, -1);
  175. // add offset to screen center
  176. scrollPosition = ccpAdd(scrollPosition, screenCenter);
  177. CCLOG(@"tilePos: (%i, %i) moveTo: (%.0f, %.0f)", (int)tilePos.x, (int)tilePos.y, scrollPosition.x, scrollPosition.y);
  178. CCAction* move = [CCMoveTo actionWithDuration:0.2f position:scrollPosition];
  179. [tileMap stopAllActions];
  180. [tileMap runAction:move];
  181. }
  182. -(void) ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
  183. {
  184. // get the position in tile coordinates from the touch location
  185. CGPoint touchLocation = [self locationFromTouches:touches];
  186. // check on which screen quadrant the touch was and set the move direction accordingly
  187. if (CGRectContainsPoint(upperLeft, touchLocation))
  188. {
  189. currentMoveDirection = MoveDirectionUpperLeft;
  190. }
  191. else if (CGRectContainsPoint(lowerLeft, touchLocation))
  192. {
  193. currentMoveDirection = MoveDirectionLowerLeft;
  194. }
  195. else if (CGRectContainsPoint(upperRight, touchLocation))
  196. {
  197. currentMoveDirection = MoveDirectionUpperRight;
  198. }
  199. else if (CGRectContainsPoint(lowerRight, touchLocation))
  200. {
  201. currentMoveDirection = MoveDirectionLowerRight;
  202. }
  203. }
  204. -(void) ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
  205. {
  206. currentMoveDirection = MoveDirectionNone;
  207. }
  208. -(void) update:(ccTime)delta
  209. {
  210. CCNode* node = [self getChildByTag:TileMapNode];
  211. NSAssert([node isKindOfClass:[CCTMXTiledMap class]], @"not a CCTMXTiledMap");
  212. CCTMXTiledMap* tileMap = (CCTMXTiledMap*)node;
  213. // if the tilemap is currently being moved, wait until it's done moving
  214. if ([tileMap numberOfRunningActions] == 0)
  215. {
  216. if (currentMoveDirection != MoveDirectionNone)
  217. {
  218. // player is always standing on the tile which is centered on the screen
  219. CGPoint tilePos = [self tilePosFromLocation:screenCenter tileMap:tileMap];
  220. // get the tile coordinate offset for the direction we're moving to
  221. NSAssert(currentMoveDirection < MAX_MoveDirections, @"invalid move direction!");
  222. CGPoint offset = moveOffsets[currentMoveDirection];
  223. // offset the tile position and then make sure it's within bounds of the playable area
  224. tilePos = CGPointMake(tilePos.x + offset.x, tilePos.y + offset.y);
  225. tilePos = [self ensureTilePosIsWithinBounds:tilePos];
  226. if ([self isTilePosBlocked:tilePos tileMap:tileMap] == NO)
  227. {
  228. // move tilemap so that touched tiles is at center of screen
  229. [self centerTileMapOnTileCoord:tilePos tileMap:tileMap];
  230. }
  231. }
  232. }
  233. // continuously fix the player's Z position
  234. CGPoint tilePos = [self floatingTilePosFromLocation:screenCenter tileMap:tileMap];
  235. [player updateVertexZ:tilePos tileMap:tileMap];
  236. }
  237. @end