2016-10-26 1 views
0

J'ai donc essayé d'obtenir la détection de collision et de travail réponse dans mon projet de jeu en utilisant le théorème de séparation Axe. J'ai réussi à détecter la collision, mais pour la vie de moi, je n'arrive pas à comprendre comment y répondre. J'essaie de trouver le vecteur de traduction minimale, mais je ne suis pas sûr de savoir comment en faire un vecteur réel afin que je puisse calculer comment répondre à la collision. J'ai lu un tutoriel après le tutoriel, et j'ai regardé beaucoup de questions précédemment posées ici, mais je n'arrive pas à comprendre comment l'implémenter. J'ai du mal à comprendre comment trouver et utiliser le MTV, donc si quelqu'un pouvait vraiment m'aider à comprendre, et peut-être me donner un exemple pour que je puisse le comprendre en implémentation plutôt qu'en théorie, ce serait beaucoup apprécié, et je m'excuse pour tout inconvénient. Mon code ne détecte avec succès la collision, et voici en bas:Trouver le MTV (Minimal vecteur de translation) en utilisant le théorème de séparation Axe

//NOTE: This is within the HitPolygon class, so "this" is referencing itself as a polygon 
public Projection project(Vector2D axis){ 

    float min = axis.dot(this.getVertices().get(0)); 
    float max = min; 
    Vector2D vecMax = new Vector2D(0, 0), vecMin = new Vector2D(0, 0); 

    for(int i = 1; i < this.getVertices().size(); i++){ 
     float p = axis.dot(this.getVertices().get(i)); 
     if(p < min){ 
      min = p; 
      vecMin = this.getVertices().get(i); 
     } 
     if(p > max){ 
      max = p; 
      vecMax = this.getVertices().get(i); 
     } 
    } 

    Projection result = new Projection(min, max, vecMin, vecMax, axis); 

    return result; 

} 

public boolean contains(Projection p1, Projection p2){ 
    return(p1.min >= p2.min && p1.min <= p2.max) || (p1.max >= p2.min && p1.max <= p2.max); 
} 

public boolean overlap(Projection a, Projection b){ 
    if(contains(a, b)) return true; 
    if(contains(b, a)) return true; 

    return false; 
} 

public boolean collide(HitPolygon b){ 

    ArrayList<Vector2D> axes1 = this.getAxes(0); 
    ArrayList<Vector2D> axes2 = b.getAxes(0); 

    for(int i = 0; i < axes1.size(); i++){ 
     Vector2D axis = axes1.get(i); 
     Projection p1 = this.project(axis), p2 = b.project(axis); 

     if(!overlap(p1, p2)) return false; 
     else{ 
      float start = p1.min > p2.min ? p1.min : p2.min; 
      float end = p1.max < p2.max ? p1.max : p2.max; 
      float translation = end - start; 
      //translation might be the MTV, more or less, but it's not a vector and I don't know how to turn it into one. 
     } 
    } 

    for(int i = 0; i < axes2.size(); i++){ 
     Vector2D axis = axes2.get(i); 
     Projection p1 = this.project(axis), p2 = b.project(axis); 
     if(!overlap(p2, p1)) return false; 
     else{ 

     } 
    } 
    System.out.println("collide"); 
    return true; 
} 

Et voici la classe simple de projection:

class Projection{ 
    public Vector2D minVec, maxVec; 
    public float min, max; 
    public Vector2D axis = new Vector2D(0, 0); 
    public Projection(float min, float max, Vector2D minVec, Vector2D maxVec, Vector2D axis){ 
     this.min = min; 
     this.max = max; 
     this.minVec = minVec; 
     this.maxVec = maxVec; 
     this.axis = axis; 
    } 

    public float minDot(){ 
     return axis.dot(minVec); 
    } 

    public float maxDot(){ 
     return axis.dot(maxVec); 
    } 
} 

Si un code supplémentaire est nécessaire, je serais heureux de le fournir. Pardonnez mon manque de compréhension pour trouver et utiliser le MTV, mais toute aide est vraiment appréciée. Je vous remercie!

Répondre

1

En fait, c'est très simple. Vous devez connaître les angles des axes utilisés et la profondeur de collision des deux objets (la profondeur correspond à la longueur de la zone de la collision projetée).

Convertir toutes les données à un vecteur avec la technique suivante:

var vecX = Math.cos(axisAngle) * deepness; 
var vecY = Math.sin(axisAngle) * deepness; 

Ensuite, additionnez les vecteurs:

var sumX = vec1X + vec2X + ...; 
var sumY = vec1Y + vec2Y + ...; 

Afted ce que vous obtenez un vecteur de somme, qui est le vecteur de déplacement vous besoin d'utiliser (à cause de la magie)

enter image description here

+0

This answer al répond le plus complètement à ma question! Le seul problème que j'ai à ce stade est que je ne suis pas sûr de la façon de trouver la profondeur. Vous m'avez dit que c'était la longueur de la zone de la collision projetée. Je suppose que c'est basé sur l'axe (c'est probablement implicite), mais je ne suis pas sûr de savoir comment obtenir la longueur réelle en unités, ou en pixels, parce que la seule chose que je peux obtenir ressemble à la profondeur variable, qui se trouve dans les milliers. Cette question a-t-elle un sens? Néanmoins, merci pour votre réponse, cela m'a fourni encore des informations très utiles. – Gyo

+0

@Gyo J'ajoute une image –

+0

L'image m'aide certainement à la comprendre conceptuellement, mais je ne sais toujours pas comment obtenir correctement la profondeur. Je pense que j'ai besoin d'obtenir la distance x et y entre les deux points sur l'axe (Voici l'image que j'ai faite pour expliquer: [image] (http://prntscr.com/czbqgf)) Et je pense que la distance x et y ensemble serait le mtv pour cet axe. Est-ce correct? C'est la seule façon dont je peux penser à cela pour obtenir la profondeur dans les unités appropriées. Je m'excuse si j'ai l'impression que je ne comprends pas, j'essaie quand même. @ Bálint – Gyo