2010-04-02 9 views
4

J'essaie de créer un bon moyen de gérer toutes les collisions possibles entre deux objets. Typiquement, l'un bouge et frappe l'autre, et devrait ensuite «rebondir». Ce que j'ai fait jusqu'ici (je crée un jeu typique où vous avez une planche et faites rebondir une balle sur des briques) est de vérifier si les rectangles se croisent et s'ils le font, inverser la vélocité-Y.Traitement des vecteurs de vitesse pendant la collision le plus proprement possible

Ceci est une solution vraiment laide et temporaire qui ne fonctionnera pas sur le long terme et puisque ce type de traitement est très commun dans les jeux, je voudrais vraiment trouver une excellente façon de le faire pour de futurs projets. . Tous les liens ou informations utiles sont appréciés.

Voici à quoi ressemble ma fonction de gestion des collisions en ce moment.

protected void collision() 
    { 
     #region Boundaries 
     if (bal.position.X + bal.velocity.X >= viewportRect.Width || 
      bal.position.X + bal.velocity.X <= 0) 
     { 
      bal.velocity.X *= -1; 
     } 
     if (bal.position.Y + bal.velocity.Y <= 0) 
     { 
      bal.velocity.Y *= -1; 
     } 
     #endregion 
     bal.rect = new Rectangle((int)bal.position.X+(int)bal.velocity.X-bal.sprite.Width/2, (int)bal.position.Y-bal.sprite.Height/2+(int)bal.velocity.Y, bal.sprite.Width, bal.sprite.Height); 
     player.rect = new Rectangle((int)player.position.X-player.sprite.Width/2, (int)player.position.Y-player.sprite.Height/2, player.sprite.Width, player.sprite.Height); 

     if (bal.rect.Intersects(player.rect)) 
     { 
      bal.position.Y = player.position.Y - player.sprite.Height/2 - bal.sprite.Height/2; 
      if (player.position.X != player.prevPos.X) 
      { 
       bal.velocity.X -= (player.prevPos.X - player.position.X)/2; 
      } 

      bal.velocity.Y *= -1; 
     } 
     foreach (Brick b in brickArray.list) 
     { 
      b.rect.X = Convert.ToInt32(b.position.X-b.sprite.Width/2); 
      b.rect.Y = Convert.ToInt32(b.position.Y-b.sprite.Height/2); 
      if (bal.rect.Intersects(b.rect)) 
      { 
       b.recieveHit(); 
       bal.velocity.Y *= -1; 
      } 
     } 
     brickArray.removeDead(); 
    } 
+0

Pour en tirer quelque chose, je pense que vous devez énoncer plus précisément le comportement que vous voulez. Dire «c'est vraiment moche et temporaire» ne le coupe pas. –

+1

On entend par Bal une Balle qui devrait rebondir avec précision sur n'importe quelle surface frappée dans l'angle droit, sans "téléporter" à travers elle lorsque la vitesse est trop élevée etc. – bjrnt

Répondre

1

Voici quelques suggestions qui pourraient vous aider.

Tout d'abord, tous vos objets tels que Player, Bal (pas sûr de ce qui est) et Brick ont une interface assez similaire - ils ont tous sprite (définir la taille de l'objet), rect (zone de délimitation de l'objet), position (position actuelle), velocity (vitesse du courant). Cela suggère que vous pourriez créer une classe de base commune pour encapsuler cette fonctionnalité.

Notez également que vous recalculez toujours rect en fonction des codes position et sprite actuels. Cela suggère que rect devrait être une propriété qui cache le recalcul (qui est toujours le même!)

Donc, vous pouvez commencer par définir une classe de base commune comme ceci (je vais suivre le style de codage standard .NET et utiliser propriétés et CamelCase noms):

class GameObject { 
    Point Position { get; set; } 
    Vector Velocity { get; set; } 
    Sprite Sprite { get; set; } 
    Rectangle Rect { 
    get { 
     // Ecnapsulated calculation of the bounding rectangle 
     return new Rectangle 
     ((int)Position.X + (int)Velocity.X - Sprite.Width/2, 
      (int)Position.Y + (int)Velocity.Y - Sprite.Height/2, 
      Sprite.Width, Sprite.Height); 
    } 
}  

Si vous utilisez maintenant ce type en tant que classe de base pour tous vos objets de jeu, vous devriez être en mesure d'écrire ceci:

protected void Collision() {  
    #region Boundaries   
    if (bal.Position.X + bal.Velocity.X >= viewportRect.Width ||   
     bal.Position.X + bal.Velocity.X <= 0)   
     bal.Velocity.X *= -1;   
    if (bal.Position.Y + bal.Velocity.Y <= 0)   
     bal.Velocity.Y *= -1;   
    #endregion 

    if (bal.Rect.Intersects(player.Rect)) {  
     bal.Position.Y = player.Position.Y - player.Sprite.Height/2 
         - bal.Sprite.Height/2;  
     if (player.Position.X != player.PrevPos.X)  
      bal.Velocity.X -= (player.PrevPos.X - player.Position.X)/2;  
     bal.Velocity.Y *= -1;  
    }  
    foreach (Brick b in brickArray.list) {  
     if (bal.Rect.Intersects(b.Rect)) {  
      b.RecieveHit();  
      bal.Velocity.Y *= -1;  
     }  
    }  
    brickArray.RemoveDead();  
}  

Il sonne aussi comme un bon idée de diviser la fonction entre en deux - un qui vérifie bal et player et l'autre qui vérifie les briques.