2016-12-29 57 views
1

這可能非常簡單,但它給了我很多的傷痛,我想知道你們是否能夠揭示它。基本上我有一個瓷磚地圖,它在64 * 64處繪製瓷磚,並且工作得非常好,並且它們在game1類中以這種2D數組繪製。碰撞檢測只能正常工作雙面具有特定瓷磚xna

TileMap tileMap = new TileMap(new int[,] 
    { 
     { 2,2,2,2,2,2,2,2,2,2 }, 
     { 2,2,2,2,2,2,2,2,2,2 }, 
     { 0,0,0,0,0,0,4,4,4,4 }, 
     { 0,0,0,0,0,0,1,1,4,4 }, 
     { 1,1,1,1,1,1,1,1,1,1,}, 
     { 1,1,1,1,1,1,1,1,1,1,} 
    }); 

現在出現這個問題。基本上我想確定玩家擊中了哪一方。但是,對於下面的算法,碰撞只能在底部和左側正確運行。如果玩家從頂部擊中貼磚,它將聲明它從底部擊中。如果玩家從右側擊中,它將指定左側被擊中。如果玩家從頂部或右側擊中,則會顯示已發生碰撞,但說明它發生在底部或左側。 它會輸出瓦片的頂部已被擊中,但只有當玩家完全在像這樣的瓦片

幾乎同樣的事情發生時,它會顯示右側命中(玩家移動更上面的左略高於圖像)

enter image description here

tilemap的

 int left = (int)Math.Floor((float)player.playerBounds.Left/TILE_WIDTH); 
     int top = (int)Math.Floor((float)player.playerBounds.Top/TILE_HEIGHT); 
     int right = (int)Math.Ceiling((float)player.playerBounds.Right/TILE_WIDTH) - 1; 
     int bottom = (int)Math.Ceiling((float)player.playerBounds.Bottom/TILE_HEIGHT) - 1; 

     Rectangle tileBounds = new Rectangle((int)tilePosX, (int)tilePosY, TILE_WIDTH, TILE_HEIGHT); 
     Rectangle playerBounds = player.playerBounds; 

     float WidthOfRects = 0.5f * (playerBounds.Width + tileBounds.Width); 
     float heightOfRects = 0.5f * (playerBounds.Height + tileBounds.Height); 

     int centerX = (playerBounds.Left + playerBounds.Width/2) - (tileBounds.Left + tileBounds.Width/2); 
     int centerY = (playerBounds.Top + playerBounds.Height/2) - (tileBounds.Top + tileBounds.Height/2); 

     for (int y = top; y <= bottom; ++y) 
     { 
      for (int x = left; x <= right; ++x) 
      { 

       if (mapCell[y, x].TileID == 1) 
       { 
        //minkowski sum 
        if (Math.Abs(centerX) <= WidthOfRects && Math.Abs(centerY) <= heightOfRects) 
        { 
         double wy = WidthOfRects * centerY; 
         double hx = heightOfRects * centerX; 
         if (wy > hx) 
         { 
          if (wy > -hx) 
          { 
           Console.WriteLine("bottom"); 
           //newPos.Y = tileCollision.Bottom; 
          } 
          else 
          { 
           Console.WriteLine("right"); 
           //newPos.X = tileCollision.Right; 

          } 
         } 
         if (wy > -hx) 
         { 
          Console.WriteLine("left "); 
          //newPos.X = tileCollision.Left - playerBounds.Width; 
         } 
         else 
         { 
          Console.WriteLine("top"); 
          //newPos.Y = tileCollision.Top - playerBounds.Height; 
         } 
        } 
        // player.Position = newPos; 
       } 
      } 
     } 

Map Cell

public class MapCell 
{ 

    public int TileID { get; set; } 

    public MapCell(int tileID) 
    { 
     TileID = tileID; 
    } 

玩家界限在玩家類別從精靈類繼承的更新方法。

public override void Update(GameTime gameTime) 
    { 
     playerBounds = new Rectangle((int)Position.X, (int)Position.Y, 50, 50); 
    } 

的位置從精靈類

protected Vector2 position; 
    public Vector2 Position 
    { 
     get { return position; } 
     set { position = value; } 
    } 

任何幫助將不勝感激繼承。

謝謝。

回答

0

讓我們從OY軸上下自由座標系統,中心位置PX,PY,半寬PW,半高PH和方向矢量DX,DY的玩家。

瓷磚矩形以TX,TY,半寬TW,半高TH爲中心。

玩家觸摸瓦時,它的中央點滿足閔可夫斯基的總和矩形在第一時間(t是時間參數)

CX = PX + DX * t 
CY = PX + DY * t 

if DY >= 0 then //moving down 
    t1 = (TY - TH - PH - PY)/DY //time to meet horizontal edge 
else //moving up 
    t1 = (TY + TH + PH - PY)/DY 

if DX >= 0 then //moving right 
    t2 = (TX - TW - PW - PX)/DX //time to meet vertical edge 
else //moving left 
    t2 = (TX + TW + PW - PX)/DX 

if t1 <= t2 then 
    if DY >= 0 then 
    touches top edge first 
    else 
    touches bottom edge first 
else 
    if DX >= 0 then 
    touches left edge first 
    else 
    touches right edge first 

//you can consider corner touches (t1=t2) separately