2017-03-26 2 views
0

J'ai un sprite, Player. Mettre à jour la position de Player de la manière suivante:XNA/Monogame: Physique de saut de plateforme et collision Numéro

_position += (_direction * _velocity) * (float)gameTime.ElapsedGameTime.TotalSeconds;

_position, _direction et _velocity sont Vector2 s.

J'ai un simple collisionneur (BoxCollider) qui génère simplement un rectangle (BoundingBox) étant donné la position et les dimensions du collisionneur.

Dans Initialize(), je crée un nouveau List<BoxCollider> et le remplit avec des collisionneurs pour le niveau. Je passe la liste à Player pour vérifier les collisions.

La méthode de contrôle de collision:

public void CheckPlatformCollision(List<BoxCollider> colliders, GameTime gameTime) 
{ 
    var nextPosition = _position + (_direction * _velocity) * (float)gameTime.ElapsedGameTime.TotalSeconds; 
    Rectangle playerCollider = new Rectangle((int)nextPosition.X, (int)nextPosition.Y, BoundingBox.Width, BoundingBox.Height); 
    foreach(BoxCollider collider in colliders) 
    { 
     if(playerCollider.Intersects(collider.BoundingBox)) 
     { 
      nextPosition = _position; 
     } 
    } 
    Position = nextPosition; 
} 

En ce moment, tous les moyens que j'ai essayé de mettre en œuvre la gravité a échoué. Si Player est tombé de trop haut, nextPosition devient trop loin de Player et le laisse coincé dans les airs.

J'ai aussi des problèmes avec les collisions horizontales, le problème étant similaire: Player s'arrête trop tôt, laissant un espace entre. Parfois, j'ai eu Player coller sur le côté du collisionneur.

Ce que je voudrais savoir est:

Comment puis-je mettre en œuvre correctement la gravité & sauter avec _position, _direction et _velocity? Comment gérer correctement les collisions horizontalement et verticalement?

+0

Peut-être que cela vous aidera: http://gamedev.stackexchange.com/questions/104954/2d-collision-detection-xna-c – vyrp

Répondre

1

Pour gravité, ajoutez juste avant de mettre à jour _position:

_velocity += gravity * (float)gameTime.ElapsedGameTime.TotalSeconds; 

gravity est quelque chose comme new Vector2(0, 10).


Pour sauter, vous devez régler la composante verticale de la vitesse lorsque le joueur appuie sur le bouton de saut:

if (jumpPressed && jumpAvailable) 
{ 
    _velocity.Y = -10; // Numbers are example. You need to adjust this 
    jumpAvailable = false; 
} 

Et vous devez réinitialiser jumpAvailable lorsque le joueur touche le sol.


COLLIDING est une chose beaucoup plus compliquée. Mais si vous cherchez "XNA Implement collision" sur Internet, vous trouverez beaucoup de réponses.

Il existe plusieurs façons. L'un d'entre eux repousse le joueur à la frontière du boxcollider, au lieu de ne pas le laisser bouger, comme vous l'avez fait dans votre code.Le code serait:

if (IntersectsFromTop(playerCollider, collider.BoundingBox)) 
{ 
    _position.Y = collider.BoundingBox.Y - BoundingBox.Height; 
} 
else if (IntersectsFromRight(playerCollider, collider.BoundingBox)) 
{ 
    _position.X = collider.BoundingBox.X + collider.BoundingBox.Width; 
} 
// And so on... 

Les méthodes d'assistance peuvent mis en œuvre comme:

private static bool IntersectsFromTop(Rectange player, Rectangle target) 
{ 
    var intersection = Rectangle.Intersect(player, target); 
    return player.Intersects(target) && intersection.Y == target.Y && intersection.Width >= intersection.Height; 
} 

private static bool IntersectsFromRight(Rectange player, Rectangle target) 
{ 
    var intersection = Rectangle.Intersect(player, target); 
    return player.Intersects(target) && intersection.X + intersection.Width == target.X + target.Width && intersection.Width <= intersection.Height; 
} 
// And so on... 

Le rationnale derrière ce code peut être expliqué avec une image:

Top collision and left collision

Dans cette image width et height correspondent à l'intersection, en violet.