2010-03-19 12 views
0

En termes généraux et pseudo-code, quelle serait la meilleure façon d'avoir une réponse de collision de glisser le long d'un mur si le mur est en réalité juste une partie d'un carré entier qu'un point est en collision dans? La méthode de test de collision utilisée est un test pour voir si le point se trouve dans le carré. Dois-je diviser le carré en quatre lignes et simplement calculer la distance la plus courte à la ligne et ensuite déplacer le point à cette distance? Si oui, alors comment puis-je déterminer quel bord du carré le point est le plus proche de la collision ?Réaction de glissement après une collision par point-carré

Répondre

2

Détectez le point de collision en testant le vecteur de mouvement par rapport au mur. Si vous savez des choses sur votre surface (par exemple, comme vous le dites, cela fait partie d'une boîte), vous pourrez peut-être tester plusieurs murs à la fois.

La solution peut être légèrement différente entre 2D et 3D. Je vais aller avec 2D puisque vous parlez "carré" plutôt que "cube" ou "boîte". Une fois que vous savez où votre point touche, vous prenez le reste de votre vecteur de mouvement, le parsèment contre la direction du mur (soustrayez un point du mur à un autre puis normalisez) puis augmentez la direction du mur de cette valeur. C'est la quantité de mouvement qui serait parallèle au mur, en supposant qu'il n'y ait pas de friction.

Modifier ajouté le code suivant:

boilerplate:

import math 

class Vector2d: 
    def __init__(self, x, y): 
     self.x = x 
     self.y = y 

    def __add__(self, rhs): 
     return Vector2d(self.x + rhs.x, self.y + rhs.y) 

    def __sub__(self, rhs): 
     return Vector2d(self.x - rhs.x, self.y - rhs.y) 

    def GetScaled(self, scale): 
     return Vector2d(self.x * scale, self.y * scale) 

    def GetLength(self): 
     return math.sqrt((self.x * self.x) + (self.y * self.y)) 

    def GetNormalized(self): 
     return self.GetScaled(1.0/self.GetLength()) 

def DotProduct(v0, v1): 
    return (v0.x * v1.x) + (v0.y * v1.y) 

La véritable entreprise:

class Wall2d: 
    def init(self, point0, point1): 
     """point0, point1 are Vector2ds""" 
     self.p0 = point0 
     self.p1 = point1 

     # these three steps could be combined to optimize, but 
     # for demonstration are left explicit 
     self.dir = self.p1 - self.p0 
     self.length = self.dir.GetLength() 
     self.dir = self.dir.GetNormalized() 

     # computing the normal in 3D would require three points 
     # on the face and a cross product 
     self.normal = Vector2d(self.length.y, -self.length.x) 

    def LineSegmentCollides(self, pointStart, pointEnd): 
     startDot = DotProduct(pointStart - self.p0, self.normal) 
     endDot = DotProduct(pointEnd - self.p0, self.normal) 
     if startDot * endDot < 0: 
      # the only way a collision can occur is if the start 
      # and end are on opposite sides of the wall, so their 
      # dot product results will have opposite signs, so 
      # the result of the multiplication is negative 
      moveVector = pointEnd - pointStart 

      # scale the movement vector by the ratio of the move 
      # vector on the "start" side versus the total length 
      # of the movement in the axis of the normal 
      collisionDelta = moveVector.GetScaled(startDot/
                (startDot + endDot)) 
      collisionPoint = pointStart + collisionDelta 

      collisionDot = DotProduct(collisionPoint - self.p0, self.dir) 
      if (collisionDot > 0) && (collisionDot < self.length): 
       # we've hit the wall between p0 and p1 (other 
       # values of collisionDot mean we missed on one 
       # end or the other) 

       # now, collision response is up to you. In this 
       # case, we'll just zero out the movement in the 
       # direction of the wall after the collision 
       # (sorry about the poor naming) 
       # note that we don't actually care about the actual 
       # point of collision here. 
       collisionPushBack = moveVector.GetScaled(
             endDot/(startDot + endDot)) 
       endPoint = pointEnd + collisionPushBack 

       return True 
     return False 

J'espère que ce qui est utile.

+0

Ce code serait utile, merci. – mars