【问题标题】:How to calculate the blast area of a bomb?如何计算炸弹的爆炸面积?
【发布时间】:2013-11-24 19:53:17
【问题描述】:

我正在开发一款游戏,假设玩家 a 在位置 x=100,y=100 放置了一颗炸弹,爆炸半径为 100 个单位……我很容易找到其中的所有“物品”被炸弹击中的游戏(只需要检查他们与炸弹的距离是否低于100)。

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

类似这样的:

右边的家伙没有被击中,但底部的家伙被击中了,我将命中区域填充为灰色,将隐藏区域填充为绿色......

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

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

谢谢

【问题讨论】:

  • 轰炸机式不需要复杂的计算。
  • 你的方法很好。这只是您正在处理的项目和障碍数量的问题。如果数字很大(一个或两个),最好使用空间分区来查找日志时间范围内的项目和/或障碍。
  • 思考“视角因素” - 阅读有关辐射传热的任何文本。我猜你不会接受它,但如果这是一个辐射传热问题,你会这样做。
  • 如果你已经有一些可见性代码,你可以检查炸弹是否对每个人都是可见的。 (如果你只测试“头部”的中心,底部的家伙可能会通过向右移动几个像素来躲避爆炸;你可能需要在那里有两条可见线。)

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


【解决方案1】:

这很简单,正如 Jongware 在 cmets 中提到的,您应该使用两条可见性线。

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

使用 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# 兼容引擎可以做到这一点,但唯一可能有点棘手的部分是障碍物交叉检查。因此,如果您只是找到一些可以帮助您进行交叉点检查的东西,那么其余的应该非常直接地实施。

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

【讨论】:

    【解决方案2】:

    这是一个关于该主题的精彩演示/文章: 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; }
                }
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多