Making a menu with SDL

Started by
5 comments, last by Charonte 15 years, 2 months ago
I have recently created my own version of Asteroids using C++ and visual studio along with SDL. However, I wanted to create a menu with 3 buttons (start, instructions, and exit) I was just wondering where I would start. I'm fairly new to programming, so any advice would be greatly appreciated. Also, would I need to make the menu in it's own .cpp? or how would i arrange it? Thanks! -mreit
Advertisement
The nicest way I have seen to cope with menus and other things that aren't part of the actual game experience, is to treat each 'screen' separately and run them from separate functions, and put them on a stack.

You start your programme by pushing the Exit function on to the stack, and then your Menu function:

Top----->Menu_Function
Bottom--|Exit_Function

Now you start your main loop, which basically calls the function on top of the stack, in this case Menu_Function. This can contain anything you want. I would recommend downloading the SDL TrueType font library, so you can just put text on the screen. From there, it's pretty easy, if you've already made your actual game, to make a three-option menu.

So, assuming your menu has these options: Game; Instructions; Exit, you do one of three things:

1. Push Game Loop on to the stack:

-->Game_Loop_Function
--|Menu_Function
--|Exit_Function

2. Push Instructions on to the stack:

-->Instructions_Function
--|Menu_Function
--|Exit_Function

3. Pop the menu off the stack

-->Exit_Function

So essentially, on each game tick, you run the function that's on top of the stack. I'm no veteran, but to me, that was extremely satisfying. It certainly works for space invaders.

To extend to conclusion here, when the player has finished with the instructions, you pop Instructions_Function off the stack and similarly, with Game_Loop_Function, when the game is finished.

The Standard Template Library has a stack template:

http://www.sgi.com/tech/stl/stack.html

Thanks! I think I'm starting to get this... But, maybe you could post an example of the code so i can see what you mean in context with he code.

Either way, thanks for the help!
Sorry it took so long to get back to you. Here's a link to the site I got that stuff about the menu and game states off:

http://www.aaroncox.net/tutorials/arcade/index.html

It's just the introductory tutorial you want, I think.

All the best!
Using a GUI-library with SDL support, e.g. guichan might ease your life in the long run :-)
-----PARPG - open source isometric 2d old school RPG still looking for interested contributors
thanks again, this is a great help
A GUI library is still probably best, but as a reply to walkingbeard:

Instead of a stack, you could use a linked list. That way you get the desired ordering in a nice little encapsulation.

Here's a basic example

MenuItem.h (next public for clarity):
class MenuItem{    protected:        int x;        int y;        int width;        int height;    public:        MenuItem(int x, int y, int width, int height);        ~MenuItem();        bool checkBounds(int posX, int posY);        MenuItem* next;};MenuItem::MenuItem(int x, int y, int width, int height){	this->x = x;	this->y = y;	this->width = width;	this->height = height;	this->next = 0;}MenuItem::~MenuItem(){	if (next !=0)	{		delete next;	}}bool MenuItem::checkBounds(int posX, int posY){	if ( posX >= x && posX <= x+width)	{		if ( posY >= y && posY <= y+height)		{		        return true;		}	}	return false;}


Initialising the list:
MenuItem start(0,0, 20,20); //Your "start" buttonstart.next = new MenuItem(0,25, 20,20); //Your "instructions" buttonstart.next->next = new MenuItem(0,50, 20,20); //Your "exit" button


Lastly, when the desired mouse button is pressed, do something like:
//Check the 'start' button:if (start.checkBounds(mouse_x, mouse_y)){    //Break out of the menu loop and begin your game.    //Could also have the game exit back to here.}else if(start.next->checkBounds(mouse_x, mouse_y)){    //Jump to another loop that renders another screen with instructions}else if(start.next->next->checkBounds(mouse_x, mouse_y)){    //Exit. (duh)}


What you do then is create an image that has maybe a title, and text for each button in the same position as you specified when creating each element in the list. That's the first thing you display on screen.

This way you can remove menu items, if you think you need to, and create fancy hover effects (by drawing a different image over the correct position when checkBounds() returns true).

Benefits of doing things this way over the function/function pointer thing walkingbeard mentioned is you no longer have to have global/static variables in order to be able to achieve the same thing.

Note that this is a really, really basic and probably really, really poor example. In the real world, you'd have SDL_Image (or whatever your surface is, I don't use SDL!) inside the MenuItem, along with perhaps a text identifier for clarity, along with a public render() function that draws to the specified point and is called each frame.

You'd also want to loop through larger menus, but I dont think you're worried about that!

That was a long-winded post, but have fun however you do it!

This topic is closed to new replies.

Advertisement