[SDL/C++] Making menu/options in game - Problem

Started by
2 comments, last by selve 11 years, 5 months ago
Hello,
I'm writing a RPG game, which will be actually the horror RPG. I've done the animation for player and all that based stuff, but now I wanted to do buttons on the left corner of the screen:
27yvm76.png
For example if I press by mouse "QUESTS", this appears on the center of the screen:
2n9xoyb.png
And then it's waiting for me to press for example ESCAPE to turn the picture off.
If I click options, I would like to have for example such buttons on screen like: CONTROLS, BACKGROUND MUSIC, FULLSCREEN or BACK:
f2u6c.png
And if I click CONTROLS, the last picture disappears and this one is on the screen:
2zdog9e.png
Then it's waiting for me to press ESCAPE or another button on screen, for example BACK.
Here's the part of code:
[source lang="cpp"]if(event.type == SDL_MOUSEMOTION )
{
mouseX = event.motion.x;
mouseY = event.motion.y;
}
if(event.type == SDL_MOUSEBUTTONDOWN )
{
//Buttons
if(event.button.button == SDL_BUTTON_LEFT
&&
( mouseX >= buttonquestslocation.x &&
mouseX <= buttonquestslocation.x + buttonquestslocation.w ) &&
( mouseY >= buttonquestslocation.y &&
mouseY <= buttonquestslocation.y + buttonquestslocation.h ) )
{
Mix_PlayChannel(-1, paper, 0);
SDL_BlitSurface(levelonemap, NULL, screen, &paperlocation);
SDL_Flip(screen);
//Here's the place where I want the screen to wait until the player will press the button. I didn't know how to do that so i put a Delay.
SDL_Delay(3000);
}
if(event.button.button == SDL_BUTTON_LEFT
&&
( mouseX >= buttonoptionslocation.x &&
mouseX <= buttonoptionslocation.x + buttonoptionslocation.w ) &&
( mouseY >= buttonoptionslocation.y &&
mouseY <= buttonoptionslocation.y + buttonoptionslocation.h ) )
{
SDL_BlitSurface(options, NULL, screen, &optionslocation);
SDL_BlitSurface(buttoncontrols, NULL, screen, &buttoncontrolslocation);
SDL_Flip(screen);
Mix_PlayChannel(-1, paper, 0);
//Now player must choose between: CONTROLS, BACKGROUND MUSIC, FULLSCREEN or BACK
}
if(event.button.button == SDL_BUTTON_LEFT
&&
( mouseX >= buttonexitlocation.x &&
mouseX <= buttonexitlocation.x + buttonexitlocation.w ) &&
( mouseY >= buttonexitlocation.y &&
mouseY <= buttonexitlocation.y + buttonexitlocation.h ) )
{
SDL_Quit();
return 0;
}
}[/source]
Advertisement
A tip, don't handle collision detection in the event handle....
As game gets bigger its gonna get so messy you will never figure what code are you looking for... thrust me on this one, i did it the hard way.
Have int MouseX, MouseY; and at start of each loop call event handle ( which will update MouseX, MouseY)
then in your code have function ( CheckCollisionWithMenu(int MouseX, int MouseY) )
in that function check collision for all menu objects.

Then have bools for each menu, so you can draw them properly.
Example

if( IsQuests == true )
{
//Draw quests related stuff
}
else if( IsOptions == true )
{
//Draw options related stuff
}
else if( IsExit == true )
{
//Call function to shutdown sdl and exit app
}


A tip: it may be annoing for user to press escape all the time if he want to go back from the "Quest menu" or "Control's menu" make a "Back" button
I suggest you to write at least minimal widget library (or better yet - use existing). It is not very hard, but makes extending your UI later much easier. Something along the lines:


class Widget {
public:
int x, y, width, height;
// Mouse events
virtual bool onMouseMove (int x, int y);
virtual bool onMouseButtonDown (int button, int x, int y);
virtual bool onMouseButtonUp (int button, int x, int y);
virtual bool onMouseClick (int button, int x, int y);
// Render method
virtual void render (SDL_Surface surface);
// Constructors etc...
Widget (int x, int y, int width, int height);
};

class Container : public Widget {
public:
std::vector<Widget *> children;

// Example
virtual bool onMouseButtonDown (int button, int x, int y);
// Other method implementations

// Constructors, destructor...
};

// Exmple method implementation of container class
// Other methods have similar logic
bool
Container::onMouseButtonDown (int button, int x, int y) {
for (child = children.begin(); child != children.end(); ++child) {
if ((x >= child->x) && (x < child->x + child->width) && (y >= child->y) && (y < child->y + child->height)) {
if (child->onMouseButtonDown (button, x, y)) return true;
}
}
return false;
}

class MenuButton : public Widget {
// Image/surface etc. data
// State
// ...
};


Basically you send processed events to topmost object of your widget hierarchy. Depending on mouse location they will be rerouted to proper widget object.
I higlighted only the absolute bare-bones of such system. But it can be extended to handle things like automatic reformatting of widgets when screen resolution changes etc. The important point is to abstract your event handling code (i.e. showing menu image) away from main loop into extensible, self-contained class.
Lauris Kaplinski

First technology demo of my game Shinya is out: http://lauris.kaplinski.com/shinya
Khayyam 3D - a freeware poser and scene builder application: http://khayyam.kaplinski.com/
Thank You very much guys ;)

This topic is closed to new replies.

Advertisement