首页 文章

碰撞检测仅适用于具有特定瓦片xna的2面

提问于
浏览
1

这可能很简单,但它给了我很多的悲伤,我想知道你们是否能够对它有所了解 . 基本上我有一个瓦片 Map ,它以64 * 64绘制瓦片并且效果非常好,它们在game1类中以这样的2D数组绘制 .

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;
    }

播放器边界位于 player class update方法中,该方法继承自sprite类 .

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

该职位继承自 sprite class

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

任何帮助将不胜感激 .

谢谢 .

1 回答

  • 0

    让我们从上到下的OY轴,具有中心位置PX,PY,半宽PW,半高PH和方向矢量DX,DY的播放器具有坐标系 .

    平铺矩形以TX,TY,半宽TW,半高TH为中心 .

    当玩家的中心点在第一次遇到Minkowski的和矩形时(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
    

相关问题