2013-07-16 4 views
2

다음 코드는 PC (플레이어 캐릭터)가 NPC를 통과하는 것을 막기위한 시도입니다.충돌 감지를위한 경계 상자가 겹쳐서 문제가 발생했습니다.

  • "if"문은 두 개의 사각형 (BoundingBox)이 교차하는지 확인합니다.
  • collisionBox는 겹치는 경계 상자의 영역을 정의합니다.
  • moveDir은 if 문 다음에 PC가 수행 할 벡터 변경을 정의합니다 (예 : moveDir = (2,0) PC가 오른쪽 두 픽셀로 이동하는 경우)
  • 현재 속도 (오른쪽, 왼쪽 아래,,) moveDir.X 또는 moveDir.Y는 키보드 입력에 따라 할당되는 값을 정의

코드 :

if (PC.charSprite.BoundingBox.Intersects(npc.charSprite.BoundingBox))  
{   
    Rectangle collisionBox = Rectangle.Intersect(PC.charSprite.BoundingBox, npc.charSprite.BoundingBox); 

    if (PC.moveDir.X > 0) //Moving Right 
    { 
     //Unknown Code Goes Here 
    } 
    else if (PC.moveDir.X < 0) //Moving Left 
    { 

    } 
    else if (PC.moveDir.Y > 0) //Moving Down 
    { 

    } 
    else if (PC.moveDir.Y < 0) //Moving Up 
    { 

    } 
} 

어떻게 할 PC가 NPC에 닿으면 PC가 그 방향으로 움직이지 않고 다른 세 방향 중 하나를 자유롭게 움직일 수 있도록하십시오. 내가 시도

코드 :

if (PC.moveDir.X > 0) //Moving Right 
{ 
    PC.moveDir = Vector2.Zero; 
} 
else if (PC.moveDir.X < 0) //Moving Left 
{ 
    PC.moveDir = Vector2.Zero; 
} 
else if (PC.moveDir.Y > 0) //Moving Down 
{ 
    PC.moveDir = Vector2.Zero; 
} 
else if (PC.moveDir.Y < 0) //Moving Up 
{ 
    PC.moveDir = Vector2.Zero; 
} 

^이는 모든 움직임을 방지 장소에 PC를 잠급니다.

if (PC.moveDir.X > 0) //Moving Right 
{ 
    PC.moveDir.X = 0; 
} 
else if (PC.moveDir.X < 0) //Moving Left 
{ 
    PC.moveDir.X = 0; 
} 
else if (PC.moveDir.Y > 0) //Moving Down 
{ 
    PC.moveDir.Y = 0; 
} 
else if (PC.moveDir.Y < 0) //Moving Up 
{ 
    PC.moveDir.Y = 0; 
} 

^또한 PC를 제자리에 고정시킵니다.

if (PC.moveDir.X > 0) //Moving Right 
{ 
    PC.moveDir.X = -currentspeed; 
} 
else if (PC.moveDir.X < 0) //Moving Left 
{ 
    PC.moveDir.X = currentspeed; 
} 
else if (PC.moveDir.Y > 0) //Moving Down 
{ 
    PC.moveDir.Y = -currentspeed; 
} 
else if (PC.moveDir.Y < 0) //Moving Up 
{ 
    PC.moveDir.Y = currentspeed; 
} 

^이 작업은 매우 간헐적으로 이루어집니다. moveDir을 반대 방향으로 바꾸면 NPC의 가장자리에 PC를 두지 만 오버랩을 방지 할 수 있기를 바랬습니다. 불행히도, PC가 제자리에 갇히는 시간의 절반. 두

if (PC.moveDir.X > 0) //Moving Right 
{ 
    PC.moveDir.X = -currentspeed; 
    PC.moveDir.X = 0; 
} 
else if (PC.moveDir.X < 0) //Moving Left 
{ 
    PC.moveDir.X = currentspeed; 
    PC.moveDir.X = 0; 
} 
else if (PC.moveDir.Y > 0) //Moving Down 
{ 
    PC.moveDir.Y = -currentspeed; 
    PC.moveDir.Y = 0; 
} 
else if (PC.moveDir.Y < 0) //Moving Up 
{ 
    PC.moveDir.Y = currentspeed; 
    PC.moveDir.Y = 0; 
} 

을 결합

그냥 전체 고정됩니다. PC가 NPC에 반대하고 NPC에게이 감동입니다 수직으로 바뀌면

if (PC.moveDir.X > 0) //Moving Right 
{ 
    PC.moveDir.X = -collisionBox.Width; 
} 
else if (PC.moveDir.X < 0) //Moving Left 
{ 
    PC.moveDir.X = collisionBox.Width; 
} 
else if (PC.moveDir.Y > 0) //Moving Down 
{ 
    PC.moveDir.Y = -collisionBox.Height; 
} 
else if (PC.moveDir.Y < 0) //Moving Up 
{ 
    PC.moveDir.Y = collisionBox.Height; 
} 

는 ^이 거의 작품은 완벽하지만, PC는 한쪽으로 이동합니다. 다시 약 절반의 시간. CSJ에 의해 코멘트에서 영감을

시도 :

if (PC.charSprite.BoundingBox.Intersects(npc.charSprite.BoundingBox)) 
{ 
    Rectangle collisionBox = Rectangle.Intersect(PC.charSprite.BoundingBox, npc.charSprite.BoundingBox); 
    if (PC.moveDir.X > 0) //Moving Right 
    { 
     PC.charSprite.Position = new Vector2(npc.charSprite.BoundingBox.Left - 34, PC.charSprite.Position.Y); 
    } 
    else if (PC.moveDir.X < 0) //Moving Left 
    { 
     PC.charSprite.Position = new Vector2(npc.charSprite.BoundingBox.Right + 2, PC.charSprite.Position.Y); 
    } 
    else if (PC.moveDir.Y > 0) //Moving Down 
    { 
     PC.charSprite.Position = new Vector2(PC.charSprite.Position.X, npc.charSprite.BoundingBox.Top - 34); 
    } 
    else if (PC.moveDir.Y < 0) //Moving Up 
    { 
     PC.charSprite.Position = new Vector2(PC.charSprite.Position.X, npc.charSprite.BoundingBox.Bottom + 2) 
    } 
} 

내가 다시 물어 다음 PC는 NPC를 접촉 할 때, PC가 그 방향으로 이동을 중지하지만 중 하나를 자유롭게 이동할 수 있도록 어떻게 그것을해야합니까 다른 세 방향?

다른 일반적인 Rectangle과 교차하는 Rectangle을 다른 방향으로 이동하는 것을 방해하지 않고 교차하는 Rectangle쪽으로 이동할 수있는 방법을 만드는 방법은 무엇입니까? 나는 이런 상황에서 수행 한 어떤

답변

0

머리를 두 드리고 술을 마시고 마침내 해결책을 찾았습니다. 나는 다른 사람들이 유사한 문제들로 그들을 돕기 위해 그것을 사용할 수 있도록 그것을 수업에 넣었습니다.

class Collision 
{ 
    #region Declarations 
    private Rectangle rectangle1; 
    private Rectangle rectangle2; 
    private Rectangle collisionZone; 
    #endregion 

    #region Constructors 
    public Collision(Rectangle R1, Rectangle R2) 
    { 
     rectangle1 = R1; 
     rectangle2 = R2; 
     if(AreColliding()) 
     { 
      collisionZone = Rectangle.Intersect(rectangle1, rectangle2); 
     } 
     else 
     { 
      collisionZone = Rectangle.Empty; 
     } 
    } 
    #endregion 

    #region Properties 
    /// <summary> 
    /// Returns the x-axis value of the top-left corner of R1 
    /// </summary> 
    public int TopLeftR1X 
    { 
     get { return rectangle1.X; } 
    } 

    /// <summary> 
    /// Returns the y-axis value of the top-left corner of R1 
    /// </summary> 
    public int TopLeftR1Y 
    { 
     get { return rectangle1.Y; } 
    } 

    /// <summary> 
    /// Returns the x-axis value of the top-right corner of R1 
    /// </summary> 
    public int TopRightR1X 
    { 
     get { return rectangle1.X + rectangle1.Width; } 
    } 

    /// <summary> 
    /// Returns the y-axis value of the top-right corner of R1 
    /// </summary> 
    public int TopRightR1Y 
    { 
     get { return rectangle1.Y; } 
    } 

    /// <summary> 
    /// Returns the x-axis value of the bottom-left corner of R1 
    /// </summary> 
    public int BottomLeftR1X 
    { 
     get { return rectangle1.X; } 
    } 

    /// <summary> 
    /// Returns the y-axis value of the bottom-left corner of R1 
    /// </summary> 
    public int BottomLeftR1Y 
    { 
     get { return rectangle1.Y + rectangle1.Height; } 
    } 

    /// <summary> 
    /// Returns the x-axis value of the bottom-right corner of R1 
    /// </summary> 
    public int BottomRightR1X 
    { 
     get { return rectangle1.X + rectangle1.Width; } 
    } 

    /// <summary> 
    /// Returns the y-axis value of the bottom-right corner of R1 
    /// </summary> 
    public int BottomRightR1Y 
    { 
     get { return rectangle1.Y + rectangle1.Height; } 
    } 

    /// <summary> 
    /// Returns the x-axis value of the top-left corner of R2 
    /// </summary> 
    public int TopLeftR2X 
    { 
     get { return rectangle2.X; } 
    } 

    /// <summary> 
    /// Returns the y-axis value of the top-left corner of R2 
    /// </summary> 
    public int TopLeftR2Y 
    { 
     get { return rectangle2.Y; } 
    } 

    /// <summary> 
    /// Returns the x-axis value of the top-right corner of R2 
    /// </summary> 
    public int TopRightR2X 
    { 
     get { return rectangle2.X + rectangle2.Width; } 
    } 

    /// <summary> 
    /// Returns the y-axis value of the top-right corner of R2 
    /// </summary> 
    public int TopRightR2Y 
    { 
     get { return rectangle2.Y; } 
    } 

    /// <summary> 
    /// Returns the x-axis value of the bottom-left corner of R2 
    /// </summary> 
    public int BottomLeftR2X 
    { 
     get { return rectangle2.X; } 
    } 

    /// <summary> 
    /// Returns the y-axis value of the bottom-left corner of R2 
    /// </summary> 
    public int BottomLeftR2Y 
    { 
     get { return rectangle2.Y + rectangle2.Height; } 
    } 

    /// <summary> 
    /// Returns the x-axis value of the bottom-right corner of R2 
    /// </summary> 
    public int BottomRightR2X 
    { 
     get { return rectangle2.X + rectangle2.Width; } 
    } 

    /// <summary> 
    /// Returns the y-axis value of the bottom-right corner of R2 
    /// </summary> 
    public int BottomRightR2Y 
    { 
     get { return rectangle2.Y + rectangle2.Height; } 
    } 

    /// <summary> 
    /// Returns the rectangle formed by how much the rectangles overlap. 
    /// </summary> 
    public Rectangle Overlap 
    { 
     get { return collisionZone; } 
    } 

    #endregion 

    #region Methods 

    public bool AreColliding() 
    { 
     if (rectangle1.Intersects(rectangle2)) 
     { 
      return true; 
     } 
     else 
     { 
      return false; 
     } 

    } 

    public Vector2 StopOnCollision(Vector2 position, Vector2 moveDir, int currentspeed) 
    { 
     if (Overlap.Width < Overlap.Height) 
     { 
      if (position.X < rectangle2.Left) 
      { 
       if (moveDir.X > 0) //Moving Right 
       { 
        moveDir = Vector2.Zero; 
       } 
       else 
       { 
        moveDir.X = -currentspeed; 
        moveDir.Y = 0; 
       } 
      } 
      //else if ((position.X + 33) > rectangle2.Right) 
      else if (position.X < rectangle2.Right) 
      { 
       if (moveDir.X < 0) //Moving Left 
       { 
        moveDir = Vector2.Zero; 
       } 
       else 
       { 
        moveDir.X = currentspeed; 
        moveDir.Y = 0; 
       } 
      } 
     } 
     else 
     { 
      if (Overlap.Y == rectangle2.Top) 

      { 
       if (moveDir.Y > 0) //Moving Down 
       { 
        moveDir = Vector2.Zero; 
       } 
       else 
       { 
        moveDir.Y = -currentspeed; 
        moveDir.X = 0; 
       } 
      } 

      else 
      { 
       if (moveDir.Y < 0) //Moving Up 
       { 
        moveDir = Vector2.Zero; 
       } 
       else 
       { 
        moveDir.Y = currentspeed; 
        moveDir.X = 0; 
       } 
      } 
     } 

     return moveDir; 
    } 

    #endregion 
} 

이 다소 간단합니다 - 당신은 당신이 확인하고있는 두 개의 충돌 상자 (직사각형)으로 클래스를 인스턴스화합니다. - 실제로 충돌하고 있는지 확인할 수 있습니다. - StopOnCollision을 사용하려면 움직이는 위치 (참조의 x, y 좌표), 이동을 변경하거나 방해하는 데 사용할 벡터 및 객체가 이동하는 속도 (픽셀 당 프레임)

나는 이것이 다른 사람들을 도왔을 때 도움이되기를 바랍니다.

1

은 다음과 같습니다

  • 일반적으로 변위를 수행합니다 (즉,캐릭터의 모션 벡터를 자신의 위치에 추가하십시오.
  • 충돌 할 수있는 모든 장애물을 확인하십시오. 충돌이있을 경우 장애물에서 문자를 "텔레포트"즉 한 픽셀 씩 이동시킵니다. 더 이상 충돌이 없을 때까지이 작업을 계속하십시오.

아마도 가장 빠른 실행 솔루션이 아니 겠지만 작업이 완료됩니다. 충돌 할 수있는 역동적 인 것들이 많이있을 때 잘 작동합니다.

+0

나는 설명했던대로 생각했습니다. 그것은 다소 효과적 이었지만, PC가 방금 충돌 한 NPC에서 멀어지면 NPC의 반대쪽으로 PC가 텔레포트됩니다. – Zach

+0

자신이 움직이고있는 반대 방향으로 캐릭터를 텔레포트하지 마십시오 (이것은 텔레포트의 바람직하지 않은 행동을 유발할 수 있습니다). 대신 장애물에서 캐릭터를 텔레포트하십시오. 변위를 적용하기 전에 장애물 위/아래에서 시작했는지 여부와 그가 장애물의 왼쪽/오른쪽에서 시작했는지 여부에 대한 부울 변수를 기록 할 수 있습니다. 그 방향으로 텔레포트하십시오. – CSJ

+0

나는 반대 방향으로 텔레포트하지 않았다. 나는 당신이 게시 한 후 간신히 사용하고 있던 코드를 편집했다. – Zach

관련 문제