2009-10-01 11 views
0

SETUP:
Je travaille sur un (point de vue oiseau oeil) jeu à base de tuiles 2-D pour iPhone. L'application lit dans un fichier de tuiles tile-d (.tbx) des tuiles avec une propriété 'blocked' de true ou de false pour représenter si le héros peut ou non traverser la case. Je parcoure chaque mosaïque de la carte et crée un tableau C bidimensionnel représentant les lignes et les colonnes de tuiles pour contenir la propriété bloquée (vrai/faux) de chaque tuile. Quand je déplace le héros à travers le tableau, je vérifie la position du héros avec le tableau pour voir si la tuile sur laquelle il s'est déplacé est bloquée ou non. Si elle est bloquée, la position du héros est inversée d'autant qu'elle a été avancée.problèmes de détection de collision à base de tuiles dans le jeu iPhone 2-D

PROB:
problème est, quand un héros a sauté sur une tuile bloqué, il ne peut pas se déplacer hors de celui-ci. Les positions des tuiles sont correctes dans le sens où les tuiles bloquées sont détectées là où elles devraient être mais le héros est néanmoins coincé. Le héros avance 'par pixel' et non 'par carreau'. C'est à peu près tout. Seule chose à gauche est de montrer le code: (Hero est de 28 pixels par 36 pixels en taille)

//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; 

    } 

} 

Répondre

4

Votre problème est que vous déplacez le lecteur, puis en vérifiant si l'espace dans lequel il a été déplacé est bloqué. Au lieu de cela, vous voulez déterminer la position à laquelle il va vouloir aller, voir si elle est bloquée, et ensuite seulement le déplacer si ce n'est pas bloqué. En outre, vous pouvez toujours ajouter une clause pour exclure son espace actuel. c'est-à-dire que tant que votre personnage ne change pas d'espaces de grille, il peut toujours se déplacer, mais une fois qu'il est sur le point de changer d'espace, vous devriez vérifier s'il va entrer en collision avec quelque chose.

Voici votre code ci-dessous:

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

Il devrait être quelque chose comme ceci:

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; 
    } 
} 

Et vous devriez vraiment essayer de rendre votre code beaucoup plus orienté objet. À ce stade, il semble être complètement procédural et toutes vos variables sont globales, ce qui n'est certainement pas une bonne façon de procéder. "checkBlocked" devrait être réécrit comme "spaceIsOpenAtX: andY:" car alors vous pouvez mettre n'importe quelle coordonnée X et Y dans ce que vous voulez afin de voir si cette position est bloquée. Comme vous l'avez fait maintenant, votre code est trop abstrait (passant autour des entiers sans indication de ce qu'ils signifient autre que vos vérifications réelles si if) et il ne peut pas être appliqué pour n'importe quelle situation en dehors de l'usage unique tu l'as donné. Vraiment, vous devriez avoir player.speed et player.animation et [maze spaceIsOpen], etc. Vous utilisez Objective-C, pas seulement C. Et même si vous utilisiez C, ce serait une meilleure idée de faites-le de manière OO.

0

Je pense que le problème est que vous permettez au joueur de se déplacer sur le carreau bloqué et il est bloqué.

Je vérifierais pour voir si la direction dans laquelle se déplace le joueur est bloquée avant d'essayer de déplacer le joueur là-bas.

Questions connexes