【问题标题】:C# - Per Pixel Collision DetectionC# - 每像素碰撞检测
【发布时间】:2018-01-13 04:04:16
【问题描述】:

这是我正在制作 2D 迷宫游戏(XNA 4.0)的情况。我发现进行碰撞检测的最佳方法是使用逐像素检测。在互联网上搜索时,我发现人们解释或显示两个碰撞的代码(即鼠标和播放器、播放器和播放器、两个形状)。我想要做的是让这种碰撞检测玩家是否与墙壁碰撞(背景是黑色但迷宫墙壁是白色的)。有人可以解释如何做到这一点,或者用代码给出某种起点。非常感谢。

附:指向网站的链接或与我的问题相关的任何内容也会有所帮助

【问题讨论】:

  • 真的需要像素完美碰撞吗?这确实是检查碰撞的资源昂贵的方法。使用矩形-多边形-圆碰撞。
  • 这是什么游戏?你怎么走动?那样走动很重要吗?
  • @Steven 这是一个 2D 迷宫游戏(整个迷宫本身就是一个图像)。我使用两个浮点变量 xSpeed、ySpeed 移动,然后使用代码 walkRec.X += xSpeed 行。用户只能在四个方向(左、右、上、下)移动,没有对角线移动。我会说这非常重要。
  • @DavorMlinaric 是的,因为我的 PNG 图像是迷宫,所以我使用的迷宫是生成的,然后我继续使用 piskel 更改颜色以适合我的主题(墙壁是白色的,背景是透明的,游戏画面设置为黑色)。因此,由于玩家总是会与图像发生碰撞,因此不可能进行您所说的碰撞
  • @TaricDF (理论上,不确定是否有内置的 GetPixelColor 纹理函数)而不是检查整个迷宫和对象中每个像素的像素碰撞,您可以检查颜色是否在上方,下方,左侧,对象的右侧是“白色”...如果对象上方 1-2 个像素是白色的,那么就是一堵墙。

标签: c# xna collision-detection


【解决方案1】:

进行这种 CPU 密集型操作的最佳方法是先检查碰撞箱碰撞,然后再检查每像素碰撞。

大部分代码都可以在这个有用的video 中找到。

static bool IntersectsPixel(Rectangle hitbox1, Texture2D texture1, Rectangle hitbox2, Texture2D texture2)
{
    Color[] colorData1 = new Color[texture1.Width * texture1.Height];
    texture1.GetData(colorData1);
    Color[] colorData2 = new Color[texture2.Width * texture2.Height];
    texture2.GetData(colorData2);

    int top = Math.Max(hitbox1.Top, hitbox2.Top);
    int bottom = Math.Min(hitbox1.Bottom, hitbox2.Bottom);
    int right = Math.Max(hitbox1.Right, hitbox2.Right);
    int left = Math.Min(hitbox1.Left, hitbox2.Left);

    for(y = top; y< bottom; y++)
    {
        for(x = left; x < right; x++)
        {
            Color color1 = colorData1[(x - hitbox1.Left) + (y - hitbox1.Top) * hitbox1.Width]
            Color color2 = colorData2[(x - hitbox2.Left) + (y - hitbox2.Top) * hitbox2.Width]

            if (color1.A != 0 && color2.A != 0)
                return true;
        }
    }
        return false;
}

你可以这样调用这个方法:

if (IntersectsPixel(player.hitbox, player.texture, obstacle.hitbox, obstacle.texture))
{
    // Action that happens upon collision goes here
}

希望能帮到你,
- GHC

【讨论】:

    【解决方案2】:

    创建一个代表精灵的布尔矩阵和一个代表迷宫的布尔矩阵(代表精灵的矩阵需要与迷宫具有相同的尺寸)。

    然后你可以做一些简单的事情,比如遍历所有 x-y 坐标并检查它们是否都是真的

    // as an optimization, store a bounding box to minimize the 
    // coordinates  of what you need to check
    for(int i = 0; i < width, i++) {
        for(int j = 0; j < height, j++) {
            if(sprite[i][j] && maze[i][j]) {
                 collision = true
                 //you  might want to store the coordinates
            }
        }
    }
    

    如果你想变得非常花哨,你可以将你的迷宫矩阵展平并使用位操作

    【讨论】:

    • 我会使用vector2来存储玩家移动时的x,y点
    • 你可以。存储 x,y 坐标的方式没有什么神奇之处。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-24
    • 1970-01-01
    • 2011-08-20
    • 2016-09-08
    相关资源
    最近更新 更多