Sign in to follow this  
selve

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

Recommended Posts

selve    145
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:
[img]http://i47.tinypic.com/27yvm76.png[/img]
For example if I press by mouse "QUESTS", this appears on the center of the screen:
[img]http://i45.tinypic.com/2n9xoyb.png[/img]
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:
[img]http://i48.tinypic.com/f2u6c.png[/img]
And if I click CONTROLS, the last picture disappears and this one is on the screen:
[img]http://i48.tinypic.com/2zdog9e.png[/img]
Then it's waiting for me to press ESCAPE or another button on screen, for example BACK.
[b]Here's the part of code:[/b]
[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]

Share this post


Link to post
Share on other sites
BaneTrapper    1531
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
[CODE]
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
}
[/CODE]

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 Edited by BaneTrapper

Share this post


Link to post
Share on other sites
lauris71    841
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:

[code]
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
// ...
};
[/code]

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.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this