我有一个简单的脚本,显示一个按钮(这是一个png图像),当用户点击它时,应用程序退出。
但我想添加多个按钮,即我发现我当前的想法会导致一个非常长的if:else情况,我想知道这是否是唯一的方法。
这就是我在main.cpp文件中设置当前菜单的方法。
bool handle_mouse_leftClick(int x, int y, SDL_Surface *button) {
if( ( ( mouseX > x ) && ( mouseX < x + button->w ) ) && ( ( mouseY > y ) && ( mouseY < y + button->h ) ) ) {
return true;
} else {
return false;
}
}
这是我的检测功能。
以下是我的主要功能,它充当我的游戏循环,我删除了非相关代码以便更容易理解:
//menu button
SDL_Surface *button;
button = IMG_Load("button.png");
while(!quit){
//handle events
while( SDL_PollEvent( &event ) ){
switch(event.type){
case SDL_QUIT: quit = true; break;
case SDL_MOUSEBUTTONDOWN:
if (event.button.button == SDL_BUTTON_LEFT) {
if(handle_mouse_leftClick(btnx,btny,button)){
quit = true;
}
}
break;
}
}
问题是我的main.cpp是否会进行所有这些检查,当我添加更多按钮时会很快变得很长,所以我想知道我是否错过了一个简化我的工作的技巧?
答案 0 :(得分:2)
当你接近基本的逻辑/计算时,我会说答案是“不”,你没有错过任何技巧。我从来没有找到一种方法一次检查每个目标 - 至少在计算方面。您可以通过很多方式使代码更清洁。你可以有一个暴露“bool IsIn(int x,int y)”方法的GuiElement类。那么你的大案例陈述看起来更像是:
bool handle_mouse_leftClick(int x, int y, SDL_Surface *button)
{
if (Button1.IsIn( mouseX, mouseY )
{
// do this
}
else if (Button2.IsIn( mouseX, mouseY ))
{
// do that
}
else
{
return false;
}
}
然后,您可以使用列表或表格进一步减少金额代码:
int handle_mouse_leftClick(int x, int y, SDL_Surface *button)
{
for (unsigned int i = 0; i < buttonList.size(); i++
{
if (buttonList[i].IsIn( mouseX, mouseY ))
{
return i; // return index of button pressed
}
return -1; // nothing pressed
}
}
但它仍然最终一次只看一个矩形。
夫妻警告:
我不认为检查每个项目的命中框有很多真正的计算开销 - 除非你是以一些疯狂的高帧速率进行的。
当然,您可以使用某种空间索引(例如按屏幕上按钮位置组织的b树或四叉树)来优化检查,但是......请参阅#1。 ; - )
如果不是10或15个按钮/控件而是 THOUSANDS ,那么你可能会想要做#2,因为#1将不再是真的。
的 强> 的 ** * ** * ** * 的更新 * ** * ** * ****
这是一个可以用于此的类的简短示例。至于.h vs main.cpp,典型的方法是将标题放在“Button.h”中,将实现(代码)放在“Button.cpp”中,但你可以把它放在main的顶部.cpp开始 - 它在类定义中具有所有逻辑。
你会注意到我没有写任何新代码。 “IsIn()”测试是你的逻辑逐字逐句,我只是更改了变量名以匹配类。因为你已经只有一个按钮,我假设你可以重复使用Render()方法呈现该按钮的代码。
最后,如果不是你熟悉的东西,你根本不需要创建列表/向量。呈现按钮的代码可以调用“okButton.Render()”,然后调用“cancelButton.Render()”。
示例“按钮”类:
class Button
{
private:
int m_x, m_y; // coordinates of upper left corner of control
int m_width, m_height; // size of control
public:
Button(int x, int y, int width, int height, const char* caption)
{
m_x = x;
m_y = y;
m_width = width;
m_height = height;
// also store caption in variable of same type you're using now for button text
}
bool IsIn( int mouseX, int mouseY )
{
if (((mouseX > m_x) && (mouseX < m_x + m_width))
&& ((mouseY > m_y) && (mouseY < m_y + m_height ) ) ) {
return true;
} else {
return false;
}
}
void Render()
{
// use the same code you use now to render the button in OpenGL/SDL
}
};
然后创建它/它们(使用列表方法):
Button okButton( 10, 10, 100, 50, "OK" );
buttonList.push_back( okButton );
Button cancelButton( 150, 10, 100, 50, "Cancel" );
buttonList.push_back( cancelButton );
在你的渲染循环中:
void Update()
{
for (unsigned int i = 0; i < buttonList.size(); i++
{
buttonList[i].Render();
}
}