title: Tile-based Collision Detection problems in 2-D iPhone game
body: <p><strong>SETUP:</strong><br>
  I'm working on a 2-D tile-based game (bird's eye view) for iPhone. The app reads in a tile-d (.tbx) tilemap file of tiles with a 'blocked' property of either true or false to represent whether or not the hero can move through the tile. I iterate over each tile in the map and create a 2-dimensional C array representing tile rows and cols to hold the blocked property (true/false) of each tile. When I move the hero across the board, I check the hero's position with the array to see if the tile he moved on is blocked or not. If blocked, the hero's position is reversed by as much as it was advanced. </p>
  
  <p><strong>PROB:</strong><br>
  Problem is, when a hero has stepped on a blocked tile, he cannot move off of it. Tile positions are correct in the sense that blocked tiles are detected where they should be but hero is stuck nonetheless. Hero advances 'by pixel' and not ' by tile'. That's about all. Only thing left is to show code: (Hero is 28 pixels by 36 pixels in size)</p>
  
  <pre><code>//Code from GameScreen.m
  
  
  
  
  
  -(void)generateCollisionMap
  {
  
  
  
  
  for(int layer=0; layer &lt; 2; layer++) {
              for(int yy=0; yy &lt; _screenTilesHeight; yy++) {
  
                  NSLog(@"Row %i", yy);
  
                  for(int xx=0; xx &lt; _screenTilesWide; xx++) {
                      int _globalTileID = [[[tileMap layers] objectAtIndex:layer] getGlobalTileIDAtX:xx y:yy];
                      NSString *_value = [tileMap getTilePropertyForGlobalTileID:_globalTileID key:@"blocked" defaultValue:@"false"];
                      if([_value isEqualToString:@"true"]) {
  
                          _blocked[xx][yy] = YES;
                          NSLog(@"Cell %i = YES", xx);
  
                      }else{
  
                          if(_blocked[xx][yy] == YES){
                          NSLog(@"Leaving Cell %i as = YES", xx);
                              //Leave As Is
  
                          }else{
  
                           _blocked[xx][yy] = NO;
                          NSLog(@"Cell %i = NO", xx);
  
                          }
  
                      }
                  }
              }
              }
  }
  
  
  
  
  
  //Code from Hero.m
  
  
  -(void)moveHero
  {
  
              // Up
  
              if(moveDirection == 1 &amp;&amp; !doesNeedShiftWorld) {
                  heroY += _playerSpeed;
                  [self checkBlocked:1];
                  _currentAnimation = _upAnimation;
                  _moving = YES;
              }
  
              // Down
              if(moveDirection == 2 &amp;&amp; !doesNeedShiftWorld) {
                  heroY -= _playerSpeed;
                  [self checkBlocked:2];
                  _currentAnimation = _downAnimation;
                  _moving = YES;
              }
  
              // Left
              if(moveDirection == 3 &amp;&amp; !doesNeedShiftWorld) {
                  heroX -= _playerSpeed;
                  [self checkBlocked:3];
                  _currentAnimation = _leftAnimation;
                  _moving = YES;
              }
  
              // Right
              if(moveDirection == 4 &amp;&amp; !doesNeedShiftWorld) {
                  heroX += _playerSpeed;
                  [self checkBlocked:4];
                 _currentAnimation = _rightAnimation;
                  _moving = YES;
              }
  
  
  
  }   
  
  
  
  //  ... 
  
  
  - (void) checkBlocked:(int)checkDirection
  {
  
      float xx = (heroX+160.0f+_tileWidth) / _tileWidth;
      float yy = 11-((heroY+300.0f+_tileHeight) / _tileHeight); 
  
  
      switch (checkDirection) {
  
          case 1:
  
              yy -= 1;
  
              if([_scene isBlocked:xx y:yy] ||
                 [_scene isBlocked:(heroX+160.0f) y:yy]) {
                  NSLog(@"Scene Blocked at %i, %i!", (int)xx, (int)yy);
                  heroY -= _playerSpeed;
  
              }else{
  
                  NSLog(@"Clear at %i, %i!", (int)xx, (int)yy);
  
              }
  
              break;
  
          case 2:
  
  
              if([_scene isBlocked:xx y:yy] ||
                 [_scene isBlocked:xx y:(heroY+300.0f)] ||
                 [_scene isBlocked:(heroX+160.0f) y:(heroY+300.0f)]) {
                  NSLog(@"Scene Blocked at %i, %i!", (int)xx, (int)yy);
                  heroY += _playerSpeed;
  
              }else{
  
                  NSLog(@"Clear at %i, %i!", (int)xx, (int)yy);
  
              }
  
  
              break;
  
          case 3:
  
              xx += 1;
  
              if([_scene isBlocked:xx y:yy] ||
                 [_scene isBlocked:(heroX+160.0f) y:yy] || 
                 [_scene isBlocked:(heroX+160.0f) y:(heroY+300.0f)]) {
                  NSLog(@"Scene Blocked at %i, %i!", (int)xx, (int)yy);
                  heroX += _playerSpeed;
  
              }else{
  
                  NSLog(@"Clear at %i, %i!", (int)xx, (int)yy);
  
              }
  
  
              break;
  
          case 4:
  
  
              if([_scene isBlocked:xx y:yy] || 
                 [_scene isBlocked:xx y:(heroY+300.0f)]) {
                  NSLog(@"Scene Blocked at %i, %i!", (int)xx, (int)yy);
                  heroX -= _playerSpeed;
  
              }else{
  
                  NSLog(@"Clear at %i, %i!", (int)xx, (int)yy);
  
              }
  
  
              break;
  
      }
  
  }
  </code></pre>