我正在开发一款游戏,让我们说玩家将炸弹放在x = 100,y = 100,爆炸半径为100单位的位置......我很容易找到所有的“物品”炸弹爆炸击中的游戏(只需检查它们与炸弹的距离是否低于100)。
但现在我想考虑到我在游戏中遇到的障碍,障碍物是正方形,总是64 * 64像素,总是与轴对齐(不旋转)..我想知道一个项目是否是“隐藏在一个障碍后面,知道他没有被击中......
类似的东西:
右边的家伙没有被击中,但是底部的家伙被击中,我在击中区域填充灰色,并且在绿色区域隐藏...
我的想法是: 1.找到场景中与炸弹的距离低于100的所有物品。 2.找到场景中与炸弹的距离低于100的所有障碍物。 3.计算从物品到炸弹中心的线条。然后检查线条是否与任何障碍物相交,如果没有......你被击中了。
最后,问题 1.有没有更好的主意? 2.有免费的开源c#兼容引擎可以帮助我吗? Box2d可以帮到我吗?由于
答案 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; }
}
}
}
}