2009-10-01 1 views
0

설정 :
iPhone 용 2 차원 타일 기반 게임 (조감도) 작업 중입니다. 앱은 'blocked'속성이 true 또는 false 인 타일의 타일 -d (.tbx) 타일 맵 파일을 읽어 영웅이 타일을 통과 할 수 있는지 여부를 나타냅니다. 맵의 각 타일을 반복하고 각 타일의 차단 된 속성 (true/false)을 유지하기 위해 타일 행과 열을 나타내는 2 차원 C 배열을 만듭니다. 영웅을 이사 할 때, 배열로 영웅의 위치를 ​​확인하여 이동 한 타일이 막혔는지 아닌지 확인합니다. 막히면 영웅의 위치가 전진 한만큼 뒤집어집니다.2 차원 iPhone 게임의 타일 기반 충돌 감지 문제

PROB : 영웅이 차단 된 타일을 밟았 때
문제는, 그가 떨어져 이동할 수있다. 타일 ​​위치는 차단 된 타일이 있어야하는 위치에서 감지되지만 영웅이 붙어 있다는 의미에서 정확합니다. 영웅은 타일 단위가 아니라 픽셀 단위로 진행합니다. 그게 전부입니다. 남은 건 오직 코드를 표시하는 것입니다 : 나는 문제가 당신이 플레이어가 차단 된 타일로 이동할 수 있도록 그가 걸리면 것을 생각

//Code from GameScreen.m 





-(void)generateCollisionMap 
{ 




for(int layer=0; layer < 2; layer++) { 
      for(int yy=0; yy < _screenTilesHeight; yy++) { 

       NSLog(@"Row %i", yy); 

       for(int xx=0; xx < _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 && !doesNeedShiftWorld) { 
       heroY += _playerSpeed; 
       [self checkBlocked:1]; 
       _currentAnimation = _upAnimation; 
       _moving = YES; 
      } 

      // Down 
      if(moveDirection == 2 && !doesNeedShiftWorld) { 
       heroY -= _playerSpeed; 
       [self checkBlocked:2]; 
       _currentAnimation = _downAnimation; 
       _moving = YES; 
      } 

      // Left 
      if(moveDirection == 3 && !doesNeedShiftWorld) { 
       heroX -= _playerSpeed; 
       [self checkBlocked:3]; 
       _currentAnimation = _leftAnimation; 
       _moving = YES; 
      } 

      // Right 
      if(moveDirection == 4 && !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; 

    } 

} 

답변

4

문제는 당신이 플레이어를 옮기고 있다는 것입니다. 다음으로 이동 한 공간이 차단되어 있는지 확인하려면을 확인하십시오. 대신, 그가 이동하려고하는 위치를 파악하고 차단되었는지 확인한 다음 차단되지 않은 경우에만 이동하려고합니다. 또한 절을 추가하여 현재 공간을 제외 할 수 있습니다. 즉, 캐릭터가 격자 공간을 변경하지 않는 한 그는 항상으로 이동할 수 있습니다. 그러나 일단 격자 공간을 변경하려고하면 무언가와 충돌할지 확인해야합니다.

if(moveDirection == 1 && !doesNeedShiftWorld) { 
    heroY += _playerSpeed; 
    [self checkBlocked:1]; 
    _currentAnimation = _upAnimation; 
    _moving = YES; 
} 

그것은이 같은해야한다 :

if(moveDirection == 1 && !doesNeedShiftWorld) 
{ 
    //Figure out if the player is changing grid spaces. 
    BOOL isChangingSpaces = ((int)((heroY + _playerSpeed)/myGridSizeVariable) != (int)(heroY/myGridSizeVariable)); 

    //The player should be able to move either if he isn't 
    //changing grid spaces or if his destination space is free. 
    if (!isChangingSpaces || (spaceIsOpenAtX:heroX andY:heroY+_playerSpeed)) 
    { 
     heroY += _playerSpeed; 
     _currentAnimation = _upAnimation; 
     _moving = YES; 
    } 
} 

을 그리고 당신이 정말로 당신의 코드를 만들려고한다 훨씬 더 객체 지향

여기 아래에 코드입니다. 이 시점에서, 그것은 완전히 절차적인 것으로 보이고 모든 변수는 전역 변수이며, 이것은 좋은 방법이 아닙니다. "checkBlocked"는 "spaceIsOpenAtX : andY :"로 다시 작성해야합니다. 그러면 X 및 Y 좌표를 원하는 위치에 놓아 해당 위치가 차단되었는지 확인할 수 있기 때문입니다. 지금까지했듯이 코드가 너무 추상 적이기 때문에 (실제 if 문 검사 이외에 을 표시하지 않고 정수를 전달합니다) 단일 용도 외의 다른 상황에는 적용 할 수 없습니다 너는 그것을 주었다.

정말로 player.speed와 player.animation과 [maze spaceIsOpen] 등이 있어야합니다. C가 아니라 Objective-C를 사용하고 있습니다. C를 사용하는 경우에도 더 나은 아이디어가 될 것입니다. OO 방식으로해라.

0

(영웅의 크기는 36 픽셀로 28 개 픽셀).

플레이어를 이동하려고 시도하기 전에 플레이어가 움직이는 방향이 차단되어 있는지 확인합니다.