我最近开始使用SFML开发2D塔防游戏,并且我打算在鼠标悬停在某些物体(菜单项,敌人等)上时插入几个视觉噱头和其他功能。为此,我必须不断检查鼠标是否悬停在这样的物体上,其中许多物体可能会移动并具有不同的大小和形状。有没有人知道一种快速有效的方法来实现这个目标?
解决这个问题的强力方法是简单地检查游戏世界中的每个对象是否鼠标位置与其边界矩形相交。我的游戏相当简单,所以通常在这里优化它会有点过分,但我还打算在其他地方实现更复杂的组件,我希望确保程序尽可能少浪费图形资源。
除此之外,我还阅读了许多可能有用的解决方案,例如跟踪网格/四叉树中的对象,只检查鼠标所在的区域。还有一个通过光线投射的解决方案,但据我所知,SFML本身没有内置。因为我认为我不是唯一一个必须解决这个问题的人,我希望有一些我错过了这个解决方案。有什么想法吗?
提前感谢您的帮助!
答案 0 :(得分:0)
我现在也正在编写TD游戏,我本月也开始使用SFML。这也是我最后一天的问题,并提出了这个想法。我不知道这是否是标准的方法,但这比我第一次尝试测试整个游戏对象要好。并希望能找到更好的解决方案lol
我的游戏窗口有3个区域,即:
地图 - 地图,敌人所在地以及建造塔楼的地方
SHOP - 你买塔的地方
信息 - 如果您点击敌人或塔楼等,信息将显示在此区域
然后我写了一个边界类,它定义了一个区域的边界。
示例:强>
Boundary shopBoundary;
Boundary mapBoundary;
Boundary infoBoundary;
我还可以添加另一个边界如果我想添加另一个区域(也许我可以点击特殊增益塔的区域?)然后我会这样做
Boundary buffsBoundary;
所以我就是这样做的伎俩
我创建了一个定义鼠标位置的枚举
enum AREAS { NONE, SHOP, MAP, INFO }
Areas mLoc = NONE;
我创建了一个结构,用于存储一个AREAS,用于命名该区域,以及该区域边界的边界对象。
struct _Boundary
{
Areas area;
Boundary boundary;
bool isMouseInside(const sf::Vector2i v) const
{
return boundary.isMouseInside(v);
}
}
std::vector<_Boundary> boundaries; // now put all your boundary to a container
现在每次鼠标移动,我只需要检查鼠标在哪里只使用3次迭代(对于地图,商店和信息)
if ( mouse moved )
{
for ( int a = 0; a < boundaries.size(); a++ )
{
if ( boundaries[a].isMouseInside(mousePos) )
{
mLoc = boundaries[a].area;
break;
}
}
}
通过该循环,我将能够通过检查mLoc
来跟踪鼠标的去向,通过在点击发生时必须知道位置,它将缩小您需要检查的游戏对象,(如果鼠标位置在商店区域,然后点击发生时,只检查该区域上的游戏对象)
if ( mouse button pressed )
{
if ( click mouse left )
{
if ( mLoc == SHOP )
{
// the click has been occured in shop
// check the game objects relative to shop
}
else if ( mLoc == MAP )
{
// the click has been occured in map
// check the game objects relative to map
}
else if ( mLoc == INFO )
{
// the click has been occured in information
// check game objects relative to that area
}
}
}