2010-03-19 2 views
0

일반적인 용어와 의사 코드에서 벽이 실제로 전체 스퀘어의 한 부분 인 경우 벽을 따라 슬라이딩하는 충돌 응답을 갖는 가장 좋은 방법은 무엇입니까? 에 충돌하고 있습니까? 사용 된 충돌 테스트 방법은 점이 사각형에 있는지 확인하는 테스트입니다.포인트 스퀘어 충돌 후 슬라이딩 응답

사각형을 네 줄로 나누고 그 줄까지의 최단 거리를 계산해서 포인트를 그 거리만큼 뒤로 이동해야합니까? 그렇다면 충돌 후 가장 가까운 사각형의 가장자리를 어떻게 결정할 수 있습니까? ?

답변

2

이동 벡터를 벽에 대해 테스트하여 충돌 지점을 감지합니다. 표면에 대한 정보를 알고 있다면 (예 : 상자의 일부라고 말하면) 한 번에 여러 개의 벽을 테스트 할 수 있습니다.

해결 방법은 2D와 3D간에 약간 다를 수 있습니다. "입방체"또는 "상자"가 아닌 "사각형"이라고 말하면서 2D로 갈 것입니다.

포인트가 닿는 지점을 알았 으면 움직임 벡터의 나머지 부분을 벽 방향으로 긋고 (다른 벽에서 벽의 한 지점을 빼고 표준화 한 다음) 그 양만큼 벽 방향을 조정하십시오. 이것은 마찰이 없다고 가정하면서 벽과 평행 한 움직임의 양입니다.

편집은 다음과 같은 코드를 추가 :

상용구 :

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) 

실제 비즈니스 : 그 유용 희망

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 

.

+0

코드가 도움이 될 것입니다. 감사합니다. – mars