2012-12-29 47 views
1

我正在嘗試將基本(現在)碰撞檢測實現到我的平臺遊戲中。我有每個16 x 16大小的瓷磚。該字符的大小爲32 x 32像素,並具有自己的邊界框。現在,在我的Tile類中,我有一個bool isSolid。我陣列中的每個瓷磚也都有相應邊界框的矩形。玩家與棋子之間的碰撞檢測

我檢查,看看是否有球員和瓷磚之間的交點做:

if (player.GetBoundingBox().Intersects(map.tiles[(int)player.position.Y/16, 
(int)player.position.X/16].bounds) && map.tiles[(int)player.position.Y/16, 
(int)player.position.X/16].isSolid) 
{ 
... 
} 

現在,我的問題是,這是極不準確,因爲我四捨五入的位置。我現在累了,因爲現在和我的生活,我無法弄清楚如何正確地做到這一點。解決這個問題的最好方法是什麼?

+0

player.position.X,player.position.Y - 玩家左上角的座標? – SergeyS

回答

1

那麼這可能不完全是「基本」,它工作得非常好,並且沒有任何問題,因爲它計算X軸和Y軸座標,這個碰撞結構將在以後幫助你。 (我從舊的Platformer入門套件代碼切換到這個,這是非常糟糕的)

假設你已經有重力方法,讓我們開始吧。

這應該是你的下降和速度邏輯後,它會看到哪些軸需要檢查。

  float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds; //If you havent already, get the elapsed time 
      if (velocity.X != 0f) 
      { 
       Position += velocity.X * Vector2.UnitX * elapsed; 
       HandleCollisions(CollisionDirection.Horizontal); 
      } 
      if (velocity.Y != 0f) 
      { 
       Position += velocity.Y * Vector2.UnitY * elapsed; 
       HandleCollisions(CollisionDirection.Vertical); 
      } 

現在爲非常重要的HandleCollisons方法

 private void HandleCollisions(CollisionDirection direction) 
     { 
      // Get the player's bounding rectangle and find neighboring tiles. 
      Rectangle bounds = player.GetBoundingBox(); 
      int leftTile = (int)Math.Floor((float)bounds.Left/Tile.Width); 
      int rightTile = (int)Math.Ceiling(((float)bounds.Right/Tile.Width)) - 1; 
      int topTile = (int)Math.Floor((float)bounds.Top/Tile.Height); 
      int bottomTile = (int)Math.Ceiling(((float)bounds.Bottom/Tile.Height)) - 1; 

      // Reset flag to search for ground collision. 
      isOnGround = false; 

      // For each potentially colliding tile, 
      for (int y = topTile; y <= bottomTile; ++y) 
      { 
       for (int x = leftTile; x <= rightTile; ++x) 
       { 
        Rectangle tileBounds = Level.GetBounds(x, y); 
        // If this tile is collidable, 
        bool IsSolid = map.tiles[x,y].IsSolid; 
        Vector2 depth; 
        if (isSolid && TileIntersectsPlayer(BoundingRectangle, tileBounds, direction, out depth)) 
        { 

          if ((collision == ItemCollision.Platform && movement.Y > 0)) 
           continue; 
          isOnGround = true; 
          if (isSolid || isOnGround) 
          { 
           if (direction == CollisionDirection.Horizontal) 
           { 
            position.X += depth.X; 
           } 
           else 
           { 

            isOnGround = true; 
            position.Y += depth.Y; 
           } 
          } 


        } 
       } 
      } 
      // Save the new bounds bottom. 
      previousBottom = bounds.Bottom; 

     } 
     public static bool TileIntersectsPlayer(Rectangle player, Rectangle block, CollisionDirection direction, out Vector2 depth) 
     { 
      depth = direction == CollisionDirection.Vertical ? new Vector2(0, player.GetVerticalIntersectionDepth(block)) : new Vector2(player.GetHorizontalIntersectionDepth(block), 0); 
      return depth.Y != 0 || depth.X != 0; 
     } 

那它的!它會檢測碰撞,但是我們需要讓它找出碰撞後玩家將會有多大的備份。您將需要這兩種擴展方法。

public static float GetHorizontalIntersectionDepth(this Rectangle rectA, Rectangle rectB) 
     { 
      // Calculate half sizes. 
      float halfWidthA = rectA.Width/2.0f; 
      float halfWidthB = rectB.Width/2.0f; 

      // Calculate centers. 
      float centerA = rectA.Left + halfWidthA; 
      float centerB = rectB.Left + halfWidthB; 

      // Calculate current and minimum-non-intersecting distances between centers. 
      float distanceX = centerA - centerB; 
      float minDistanceX = halfWidthA + halfWidthB; 

      // If we are not intersecting at all, return (0, 0). 
      if (Math.Abs(distanceX) >= minDistanceX) 
       return 0f; 

      // Calculate and return intersection depths. 
      return distanceX > 0 ? minDistanceX - distanceX : -minDistanceX - distanceX; 
     } 

     public static float GetVerticalIntersectionDepth(this Rectangle rectA, Rectangle rectB) 
     { 
      // Calculate half sizes. 
      float halfHeightA = rectA.Height/2.0f; 
      float halfHeightB = rectB.Height/2.0f; 

      // Calculate centers. 
      float centerA = rectA.Top + halfHeightA; 
      float centerB = rectB.Top + halfHeightB; 

      // Calculate current and minimum-non-intersecting distances between centers. 
      float distanceY = centerA - centerB; 
      float minDistanceY = halfHeightA + halfHeightB; 

      // If we are not intersecting at all, return (0, 0). 
      if (Math.Abs(distanceY) >= minDistanceY) 
       return 0f; 

      // Calculate and return intersection depths. 
      return distanceY > 0 ? minDistanceY - distanceY : -minDistanceY - distanceY; 
     } 

請注意,您可能需要修改這一點,因爲玩家的位置是BOTTOM左邊。還需要一個碰撞枚舉,用於垂直和水平。請告訴我,如果有什麼東西似乎缺少在這。