I have a simple script which displays one button (which is a png image) and when the user clicks it the application quits.
But i want to add multiple buttons which is where im finding my current thinking will lead to a very long if:else situation and I am wondering if that is the only way.
This is how i have my current menu set up in a main.cpp file.
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;
}
}
This is my detection function.
Below is my main function which acts as my game loop, i’ve removed non relevant code to keep it easier to follow:
//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;
}
}
The issue is should my main.cpp have all this checking going on, is going to get very long very quickly when i add more buttons so I’m wondering if I have missed a trick to simplify my efforts?
When you get right down to the basic logic/computation, I would say the answer is “no”, you haven’t missed any tricks. I’ve never found a way around checking each target one at a time – at least in terms of computation. You could make your code cleaner a lot of ways. You could have a GuiElement class that exposes a “bool IsIn( int x, int y )” method. Then your big case statement would look more like:
You could then further reduce amount code with a list or table:
But it’s still ultimately looking at each rectangle one at a time.
Couple caveats:
I don’t think there’s much real computational overhead in checking the hit boxes of each item – unless you’re doing it at some crazy high frame rate.
Sure, you could optimize the checking with some kind of spatial index (like a b-tree or quad-tree organized by the locations of the buttons on the screen), but … see #1. 😉
If instead of 10 or 15 buttons/controls you have THOUSANDS then you will likely want to do #2 because #1 will no longer be true.
********* Update ***********
Here’s a brief sample of a class that could be used for this. As far as .h vs main.cpp, the typical approach is to put the header in a “Button.h” and the implementation (code) in a “Button.cpp”, but you could just put this at the top of main.cpp to get started – it has all the logic right in the class definition.
You’ll notice I didn’t really write any new code. The “IsIn()” test is your logic verbatim, I just changed the variable names to match the class. And since you already have a single button, I’m assuming you can reuse the code that renders that button the Render() method.
And lastly, if is not something you’re familiar with, you don’t have to create a list/vector at all. The code the renders the buttons could just call “okButton.Render()”, followed by “cancelButton.Render()”.
Sample “button” class:
Then to create it/them (using the list approach):
And in your render loop: