如何计算炸弹爆炸面积?

时间:2013-11-24 19:53:17

标签: math collision-detection computational-geometry game-physics

我正在开发一款游戏,让我们说玩家将炸弹放在x = 100,y = 100,爆炸半径为100单位的位置......我很容易找到所有的“物品”炸弹爆炸击中的游戏(只需检查它们与炸弹的距离是否低于100)。

但现在我想考虑到我在游戏中遇到的障碍,障碍物是正方形,总是64 * 64像素,总是与轴对齐(不旋转)..我想知道一个项目是否是“隐藏在一个障碍后面,知道他没有被击中......

类似的东西:

enter image description here

右边的家伙没有被击中,但是底部的家伙被击中,我在击中区域填充灰色,并且在绿色区域隐藏...

我的想法是: 1.找到场景中与炸弹的距离低于100的所有物品。 2.找到场景中与炸弹的距离低于100的所有障碍物。 3.计算从物品到炸弹中心的线条。然后检查线条是否与任何障碍物相交,如果没有......你被击中了。

最后,问题 1.有没有更好的主意? 2.有免费的开源c#兼容引擎可以帮助我吗? Box2d可以帮到我吗?

由于

2 个答案:

答案 0 :(得分:1)

这很简单,正如Jongware在评论中提到的那样,你应该使用两行可见性。

您应该计算图片中各项“侧面”的可见线。可以通过计算炸弹中心的直线来获得每条能见线的原点,并获得与该矢量垂直的方向。然后,您的两个可见点位于正常和负法线方向上距物品中心一半的半径处。这个圆近似可能并不能很好地代表所有可能的形状,但通常对于简单游戏来说是足够好的近似(并且您的项目在图中看起来是圆形的)。

使用2D向量的Java-isch伪代码:

// bombCenter and itemCenter are 2D-vectors
bombDirectionVector = bombCenter.minus(itemCenter);
normal = bombDirectionVector.getNormal()    // normal vector of length 1
viewPoint1 = itemCenter.plus(normal.times(itemRadius));
viewPoint2 = itemCenter.minus(normal.times(itemRadius));
// Check obstacle intersection with the lines from viewPoint{1,2} to bombCenter
// ...

然后,能见线将从每个项目两侧的点到达炸弹中心。因此,对于每个项目,检查两条可见性线是否与相同的障碍物或两个连接的障碍物相交。

没有免费的开源C#兼容引擎,我知道这样做,但唯一可能有点棘手的部分是障碍交叉检查。因此,如果您只是找到了一些可以帮助您进行交叉检查的内容,那么其余部分应该非常直接地实现。

我希望这会有所帮助,如果有任何不清楚的地方让我知道,我会相应地澄清答案。

答案 1 :(得分:0)

这是关于这个主题的一个很好的演示/写作: http://www.redblobgames.com/articles/visibility/

如果它是基于图块的游戏并且您知道所有对象的图块坐标,则可以使用Bresenham的线算法:http://roguebasin.roguelikedevelopment.org/index.php?title=Bresenham%27s_Line_Algorithm。这是一段摘录:

// Author: Jason Morley (Source: http://www.morleydev.co.uk/blog/2010/11/18/generic-bresenhams-line-algorithm-in-visual-basic-net/)
using System;

namespace Bresenhams
{
    /// <summary>
    /// The Bresenham algorithm collection
    /// </summary>
    public static class Algorithms
    {
        private static void Swap<T>(ref T lhs, ref T rhs) { T temp; temp = lhs; lhs = rhs; rhs = temp; }

        /// <summary>
        /// The plot function delegate
        /// </summary>
        /// <param name="x">The x co-ord being plotted</param>
        /// <param name="y">The y co-ord being plotted</param>
        /// <returns>True to continue, false to stop the algorithm</returns>
        public delegate bool PlotFunction(int x, int y);

        /// <summary>
        /// Plot the line from (x0, y0) to (x1, y10
        /// </summary>
        /// <param name="x0">The start x</param>
        /// <param name="y0">The start y</param>
        /// <param name="x1">The end x</param>
        /// <param name="y1">The end y</param>
        /// <param name="plot">The plotting function (if this returns false, the algorithm stops early)</param>
        public static void Line(int x0, int y0, int x1, int y1, PlotFunction plot)
        {
            bool steep = Math.Abs(y1 - y0) > Math.Abs(x1 - x0);
            if (steep) { Swap<int>(ref x0, ref y0); Swap<int>(ref x1, ref y1); }
            if (x0 > x1) { Swap<int>(ref x0, ref x1); Swap<int>(ref y0, ref y1); }
            int dX = (x1 - x0), dY = Math.Abs(y1 - y0), err = (dX / 2), ystep = (y0 < y1 ? 1 : -1), y = y0;

            for (int x = x0; x <= x1; ++x)
            {
                if (!(steep ? plot(y, x) : plot(x, y))) return;
                err = err - dY;
                if (err < 0) { y += ystep;  err += dX; }
            }
        }
    }
}