c# - Monogame - iOS 上的每像素碰撞

标签 c# ios debugging xamarin.ios monogame

首先,我想说,我使用这段代码进行逐像素碰撞检测:

    public bool CollidesWith(Sprite other)
    {
        // Default behavior uses per-pixel collision detection
        return CollidesWith(other, true);
    }

    public bool CollidesWith(Sprite other, bool calcPerPixel)
    {
        // Get dimensions of texture
        int widthOther = other.Texture.Width;
        int heightOther = other.Texture.Height;
        int widthMe = Texture.Width;
        int heightMe = Texture.Height;

        if (calcPerPixel &&                                // if we need per pixel
            ((Math.Min(widthOther, heightOther) > 10) ||  // at least avoid doing it
            (Math.Min(widthMe, heightMe) > 10)))          // for small sizes (nobody will notice :P)
        {
            return Rectangle.Intersects(other.Rectangle) // If simple intersection fails, don't even bother with per-pixel
                && PerPixelCollision(this, other);
        }

        return Rectangle.Intersects(other.Rectangle);
    }

    public bool PerPixelCollision(Sprite a, Sprite b)
    {
        // Get Color data of each Texture
        Color[] bitsA = new Color[a.Texture.Width * a.Texture.Height];
        a.Texture.GetData(bitsA);
        Color[] bitsB = new Color[b.Texture.Width * b.Texture.Height];
        b.Texture.GetData(bitsB);

        // Calculate the intersecting rectangle
        int x1 = Math.Max(a.Rectangle.X, b.Rectangle.X);
        int x2 = Math.Min(a.Rectangle.X + a.Rectangle.Width, b.Rectangle.X + b.Rectangle.Width);

        int y1 = Math.Max(a.Rectangle.Y, b.Rectangle.Y);
        int y2 = Math.Min(a.Rectangle.Y + a.Rectangle.Height, b.Rectangle.Y + b.Rectangle.Height);

        // For each single pixel in the intersecting rectangle
        for (int y = y1; y < y2; ++y)
        {
            for (int x = x1; x < x2; ++x)
            {
                // Get the color from each texture
                Color a1 = bitsA[(x - a.Rectangle.X) + (y - a.Rectangle.Y) * a.Texture.Width];
                Color b1 = bitsB[(x - b.Rectangle.X) + (y - b.Rectangle.Y) * b.Texture.Width];

                if (a1.A != 0 && b1.A != 0) // If both colors are not transparent (the alpha channel is not 0), then there is a collision
                {
                    return true;
                }
            }
        }
        // If no collision occurred by now, we're clear.
        return false;
    }

此代码在我的“Sprite”结构中。它在 Windows、OpenGL(MonoGame 跨平台桌面项目)、Android 和 Windows UWP 上运行良好。

但在 iOS 上,当我调用 Sprite.CollidesWith(...); 时,我的程序停止渲染屏幕。一切正常,但它无法渲染新帧(它渲染静态图像)。 (我添加了点击声音来测试程序是否崩溃。(点击屏幕卡住后,我可以听到声音))

问题出在这一行:

a.Texture.GetData(bitsA);

我在网上搜索了一下,发现 Texture2D.GetData<> 没有在 iOS 上实现...那么,有没有可能在 iOS 上进行像素完美的碰撞检测? (不调用 GetData<>)

对于任何错误,我很抱歉,我是这个论坛的新手。 并感谢您的帮助。

最佳答案

I searched the web and i found that Texture2D.GetData<> is not implemented on iOS...

事情是这样的。 Texture2D.GetData 不打算按照您使用它的方式使用。它实际上所做的是在纹理已发送到显卡后从GPU 中读取纹理数据。。如果可以避免,那不是您想要做的事情。

阅读 this thread on the MonoGame forums如果你不相信我。这是来自该线程的引述,很好地总结了它。

We need to put this in big letters in the documentation. Don't call GetData() every frame. Avoid it entirely if possible. GPUs are designed for data to go into them, not back the other way.

在大多数平台上,这是一个相当慢的操作。正如您所发现的,在某些平台上,这甚至是不可能的。


soo, is there any possibility to make pixel-perfect collision detection on iOS? (without calling GetData<>)

所以这里真正的问题是如何完全避免使用 GetData。正如评论中提到的,已经有一个相当合理的 workaround如果你想要快速而肮脏的东西,你可以使用。

Saving or reading files may affect game performance.

我发现有点讽刺的是,当您已经通过逐像素碰撞破坏了渲染性能时,您还担心游戏性能。

事实上,出于性能原因,大多数游戏不会进行逐像素碰撞检测。如果您使用矩形和圆形等更简单的碰撞形状,玩家几乎肯定不会注意到它。我认为值得考虑您是否确实需要它们。

虽然我不知道你在制作什么样的游戏。有些游戏确实需要逐像素碰撞,所以如果确实是这种情况,我会告诉你我的想法如何处理它。

我认为进行逐像素碰撞的最佳方法是以某种二进制格式存储纹理数据。但除此之外,理想情况下,您希望通过 MonoGame 内容管道或其他方式预处理数据,这样您就不会在运行时从慢速源读取数据。像这样的方法可以让您两全其美(在游戏启动时快速加载和快速渲染)。

工作量很大,但可能值得考虑。

关于c# - Monogame - iOS 上的每像素碰撞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42657559/

相关文章:

debugging - Common-LISP 调试(包含代码)

c# - WCF 是否进行 CRL/OCSP 证书检查?

ios - 如何为不同的设备设置线宽

ios - 如何在 viewWillAppear 中将 UIScrollView 滚动到底部,当使用自动布局时,没有视觉动画

javascript - Chrome 开发工具中未捕获的 ReferenceError

react-native - 使用 Vscode : TypeError: global. performance.now 调试具有 React Native Reanimated 的 React Native 应用程序不是函数

c# - ASP.NET 中的 Facebook channel 文件

c# - "file system simulation implementation"

C#应用程序破解

ios - PushViewController 后跟 'back' 按钮有时不会弹出 View