GAME MENU
GOORE YANNIS

Hi everybody, I have to do a menu for a space battle game and i'm a little bit lost because i don't know how to make different levels, or how to put up the menu options.

piccolo

look into game states. menus input cant seen as a state. levels can all so be seen as a state

GOORE YANNIS

do you have a tutorial or something like that because i don't understand how to do that I have to do 3 levels with a menu can you explain your thinking ?

Edgar Reynaldo

The menu is a state, and so is each level. Look into state machines.

A menu is a set of buttons. A button is a rectangle or other shape that monitors mouse clicks and gives visual feedback to the user.

GOORE YANNIS

Okay , I see do you have an example of that in C language ?

piccolo

https://www.allegro.cc/depot/Thegame/

keep in mind menus are usually constructed using object oriented programing.

Edgar Reynaldo

Read carefully, this will affect your entire coding career :

Whenever you approach a coding problem, you need to identify the basic components that you need to create. In a program, there are two and only two things you need to worry about. 1) Data - these are the raw bits that make up your program, the values your variables hold, etc...., and 2) Instructions - what to do with all that dang data...

Now, you have to approach your programming problem with the fundamental approach of turning your problem into Data, and Instructions.

Identify the basic building blocks of your program. What values do you need to store in order to represent the parameters of your problem? And secondly, what kind of logic do you need to process that data and turn it into the correct output of the program?

So, in your case, you need a game with multiple 'screens' which can be represented by states. In C you can do this with predefined constants and a variable to hold the current state. Then your logic code and your drawing code can react to the value stored in the 'state' variable and act accordingly.

Your first screen is a menu. A menu is simply an array of buttons. A button is a shape, which can be defined mathematically using variables. The most typical example is a pure rectangle, aligned with the screen axes.

A rectangle is a position, and dimensions. xy position, and width/height.

A button is an 'object' or 'widget' that monitors mouse clicks and compares the value of the mouse position at the time of the mouse click with a stored area such as a rectangle.

So what does that mean for you? How do we reduce that all to data and instructions?

First the data ;

#SelectExpand
1/// Game states 2const int STATE_QUIT = -1; 3const int STATE_MENU = 0; 4const int STATE_GAME = 1; 5 6/// sub states for each level 7const int STATE_GAME_LEVEL1 = 0; 8const int STATE_GAME_LEVEL2 = 1; 9const int STATE_GAME_LEVEL3 = 2; 10 11/// We need to store our hit area for our buttons 12typedef struct RECTANGLE { 13 int x,y,w,h; 14}; 15 16/// Initial states 17int gamestate = STATE_MENU; 18int gamelevel = STATE_GAME_LEVEL1; 19 20/// Our button 21RECTANGLE button_play = {200,100,200,50};

That about covers it for our data. Now we need to present that data to our users with some instructions. This is where the logic handling and display handling come in.

First, we need a way to test if our button is pressed :

bool button_pressed(ALLEGRO_EVENT ev , RECTANGLE* b) {
   if (ev.type != ALLEGRO_EVENT_MOUSE_BUTTON_DOWN) {return false;}
   return (ev.mouse.x >= b->x && ev.mouse.y >= b->y && ev.mouse.x < b->x + b->w && ev.mouse.y < b->y + b->h);
}

Second, we need to change our output depending on the game state :

#SelectExpand
1 2while (state != STATE_QUIT) { 3 if (redraw) { 4 Redraw(); 5 redraw = false; 6 } 7 do { 8 ALLEGRO_EVENT ev; 9 al_wait_for_event(queue , &ev); 10 switch (gamestate) { 11 case STATE_MENU : 12 if (button_pressed(ev , &button_play)) { 13 gamestate = STATE_GAME; 14 } 15 break; 16 case STATE_GAME : 17 /// etc... 18 break; 19 } 20 } while (!al_is_event_queue_empty(queue)); 21 22}

GOORE YANNIS

thank you verry much all of you can i send u what i have done for the moment ?

Edgar Reynaldo

You can post a zip file of your source code just attach it to the Post.

GOORE YANNIS

it's in french i come from france but there is a problem my menu don't want to appear i don't know why everything seems okay , but when i try to run it i have a black screen and i have to shutdown my Macbook.

Edgar Reynaldo

It looks like you're missing fonts

Doctor Cop

Edgar, your explanation was splendid, the way you stored the coordinates and Height, width of the rectangle later to be used to make up for x1, y1/ x2, y2 was something I never thought before, it just makes it so much easy to create buttons!

Edgar Reynaldo

Well, I've been writing a GUI for 10 years now, if there's one thing I can do, it's buttons... :o

;)

Neil Roy

In my own game, I just created a series of images for each button. Each button has three states, a normal one you see all the time, one when t he mouse is hovering over it, and one when it is actually clicked.

I then created a struct (I code in C) to hold my button data, the image, the current state etc. I check the mouse position and compare it to each button's position then update that button's state if needed. The draw routine then draws the approriate graphic based on the state. If you click the button, I then jump to the appropriate function to play the game, switch to an options menu etc.

It's fairly simple to implement to be honest.

Doctor Cop

NiteHackr, that's the only way I see it. Do you have any other way to do it?
I would like to know.

Neil Roy

There are libraries that provide functionality for buttons and the like, but I never liked the look of them and preferred to roll my own.

In my Deluxe Pacman 2 game I wrote my own button functions for creating a button etc... (see dp2_gui.c/.h in my source). For creating a button I have the following function which takes a pointer to the new button struct, whether it is a simple toggle switch (used in my level editor mostly), it takes the filename for the file with the three images which will make up the different button states as well as the position of it on screen.

#SelectExpand
1// new_button: 2// Creates a new button, loading in the file indicated. 3// The graphics provided MUST contain three images, lined up vertically. 4// The top image is the normal button that is displayed when it isn't being used. 5// The second image down is the button to display when the mouse is over it (but not clicked) 6// The third image is the button to display when the mouse is clicked on it. 7// This function assumes a new uninitialized BUTTON variable sent to it. 8bool new_button(BUTTON *b, bool is_switch, const char *file, int x, int y) 9{ 10 b->x = x; 11 b->y = y; 12 b->state = 0; 13 b->old_state = 0; 14 b->is_switch = is_switch; 15 b->bmp = NULL; 16 b->bmp = al_load_bitmap(file); 17 if(!b->bmp) return false; 18 b->w = al_get_bitmap_width(b->bmp); 19 b->h = al_get_bitmap_height(b->bmp) / 3; 20 b->up = NULL; 21 b->up = al_create_sub_bitmap(b->bmp, 0, 0, b->w, b->h); 22 b->over = NULL; 23 b->over = al_create_sub_bitmap(b->bmp, 0, b->h, b->w, b->h); 24 b->down = NULL; 25 b->down = al_create_sub_bitmap(b->bmp, 0, b->h * 2, b->w, b->h); 26 27 return true; 28}

Then there's the function to check if the mouse is over the button, fairly simple and straight forward...

#SelectExpand
1// check_button: 2// Checks to see if the mouse is over or is clicking on a button 3// Returns true if an area was clicked in. 4bool check_button(BUTTON *b, ALLEGRO_MOUSE_STATE *mouse) 5{ 6 bool is_over = true; 7 // Convert mouse position to proper position on scaled screen. 8 int mouse_x = (mouse->x - offset_x) / scale_x; 9 int mouse_y = (mouse->y - offset_y) / scale_y; 10 11 // Calculate the right side. 12 int ex = b->x + b->w - 1; 13 14 // Calculate the bottom side. 15 int ey = b->y + b->h - 1; 16 17 // save the last state 18 b->old_state = b->state; 19 20 // set new state to up 21 if(b->is_switch && b->state == 2) b->state = b->old_state; 22 else b->state = 0; 23 24 // If the mouse is outside of the area in question, return false. 25 if(mouse_x < b->x || mouse_y < b->y || mouse_x > ex || mouse_y > ey) is_over = false; 26 27 if(is_over) { 28 if(!b->is_switch) b->state = 1; // mouse is over 29 else if(b->is_switch && b->state == 0) b->state = 1; 30 if(mouse->buttons & 1) { 31 if(b->is_switch && b->state == 2) b->state = 0; 32 else b->state = 2; // left button down? 33 } 34 } 35 // if the state hasn't changed, return false 36 if(b->state == b->old_state && !is_over) return false; 37 38 // the state has changed, return true 39 return true; 40}

And I have a function for drawing them and destroying them. I could have probably went further in this and added more to it all, but this was all I really needed and it looked and operated good enough for me in game.

My button graphics are all organized the same way, the top one is normal, then a red one for mouse over and the bottom one for left clicked.

{"name":"612007","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/5\/3\/5338bd184b07884d1243644476908c9c.png","w":256,"h":159,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/5\/3\/5338bd184b07884d1243644476908c9c"}612007

There really is nothing to it and honest, I recommend doing it yourself so you have full control over what happens and you can customize it to your needs.

You could, for example, have your code draw t he buttons yourself, select a font and have it so your functions can have any text you wish on them rather than premade graphics like my own. That would be pretty simple to do... and something I thought about doing, given the common look to all my buttons.

I just happen to enjoy doing it myself.

Doctor Cop

I agree with you, however the reason I make my own GUI is that what I need is a modern look in GUI and all the GUI systems which I came across were not that much dynamic. I am trying to make GUI similar to what Web Designers are making, I want it to be up to the mark.

like you said that I could make some changes to your code and display the desirable font I need but I don't need just the font, I need to make it so that I may not need even any image and I will change it so that when I am not passing an image it will display a rectangle and that's when i think polymorphism really shines, OOPs.

I want to be able to do it in C too, but that would be very heavy lifting.

jmasterx

and all the GUI systems which I came across were not that much dynamic

Honestly, I spent several years on Agui to build and stabilize it, it is fully skinnable and very flexible. It is tried and tested in a commercial game selling over 1.5 million copies.

There are also a bunch of high quality alternatives like EAGLE; also fully skinnable.

Even if some how these libraries are not 'dynamic' enough for you, there is no good reason not to fork and modify one to your needs.

Gui threads have become the new Monday thread. It's silly.

If you need something for tools use QT.

If you need a complex render engine, fork chromium.

But writing a new gui because the ones out there that took years to develop are missing a little something you need is silly IMO.

Don't make a gui api in C just for the fun of it. Not all things lend well to OOP, but GUIs really lend well to OOP!

GOORE YANNIS

Thanks all of you, i will try what you taught me , but i have a another problem if i want to do checkpoints like in videogames, how allegro can help me to do that ?

Rodolfo Lam

You have to understand that the main focus of Allegro is the rendering of your program state, whatever that program is. Usually the programs are games.

Depending on your type of game, your "checkpoint" system could be something as simple as a single file containing your score and current level progress. It can also involve having a fully fledged database, holding entries for inventory items, skill tree development, past interactions with NPCs, and the like.

That is (at least partially, read below) outside the scope for Allegro, you need to bring your own code for that or find something you can use for the task at hand. Using C or C++ you could look into File I/O facilities to get the basics. If you feel like it (and have a good grasp of the basics), you can then venture into something such as JSON, XML, Protocol Buffers, and many other serialization libraries that can be adapted to store whatever program state you want to save.

ALLEGRO BASED OPTION:

Allegro 5 has support for reading and writting simple configuration files in the Windows *.INI format. IT is usually used to load whatever default configuration and flags you want without hardcoding it into the executable. You can look more into this here. Good luck!

Doctor Cop

Jmasterx: I'm using the help of WidgetZ library. Of course making a complete new GUI library won't be possible without spending months of time on it but what I'm doing is that I'm trying to learn how to make one.

This whole Messing with GUI systems thing for me is to learn how to make software. Making a complete GUI system will teach me how states work and how should I plan my software. If you suggest me otherwise then I'll be happy to hear your views.

Here's what I'm trying to achieve in buttons for now.

{"name":"612009","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/d\/1\/d17f1819a3c817ff5601ba47be1318a4.jpg","w":1080,"h":1080,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/d\/1\/d17f1819a3c817ff5601ba47be1318a4"}612009

Neil Roy

I have used Allegro in the past to actually draw the buttons from scratch, I just didn't bother in my own game at the time. I kind of wish I had from the get go, but hindsight and all that.

It wouldn't be difficult, you take the size you wish, a style etc... you could pick a colour to shade from-to, top to bottom I would make a primary style say, if you wanted it to be blue, go from light blue at the top, to dark at the bottom, perhaps with a rounded corner rectangle (like an oval almost) near the top to give it a shine, like a glass look. You could easily change the colour for mouse over to red, same shading, then left clicked could be red shaded, only dark on top to light red on button to give the depressed look. Ad a custom font to the mix... it wouldn't be difficult to make it very flexible.

I agree, that such a system would definitely benefit from C++ classes, but I can't see any reason why it can't be done just about as nicely in C with a little effort. Personally I love the challenge of doing it in C, but that's just me. ;)

Allegro has some very nice graphic commands for drawing primitives with which would do the trick nicely and look very good and not so plain and hum drum.

There was a nice example of Allegro code used to draw a Pong style paddle someone posted, I forget who. But this reminds me a lot of the button style I like. Take this code, add in some truetype font style to it and make it more flexible for whatever you wish... and it would be pretty kewl. :)

Of course, I am always thinking in terms of Allegro 5 + games.

void draw_paddle(float x, float y)
{
  // fill
  al_draw_filled_rounded_rectangle(x, y,
    x+paddle_width, y+paddle_height, 6, 6, al_color_html("729fcf"));
  // outline
  al_draw_rounded_rectangle(x, y,
    x+paddle_width, y+paddle_height, 6, 6, al_color_html("b5edff"), 1.0);
  // shine
  al_draw_filled_rounded_rectangle(x, y,
    x+paddle_width/2, y+paddle_height-10, 6, 6, al_color_html("8abbef"));
}

jmasterx

I can tell you that Agui supports all of those button states out of the box.

Here you will find a subclass of the Agui button that supports all those states
https://github.com/jmasterx/StemwaterSpades/blob/master/Spades%20Game/Game/UI/Button.cpp

Agui draws buttons as ninepatch images so the size can be dynamic

This codebase has everything you need to have a fully skinned dynamic responsive css-worthy client-ready user experience

https://github.com/jmasterx/StemwaterSpades/tree/master/Spades%20Game/Game/UI

Doctor Cop

Thanks, Jmasterx and Neil for the direction, I'll be on it ones my exams are completed. And yes now I admit that there is no reason for me to not look at some other GUI libs made in Allegro5 and just to be clear I was using Eagle 5 for my previous project, I just decided to make one of my own because I had problems understanding States and I thought it would be cool and experience rich if I try to make my own GUI system and it did teach me alot about states that I didn't knew before.

Edgar Reynaldo

Doctor Cop, could I get some feedback on Eagle? It supports spring and toggle buttons as well as hover, focus, and disabled if you customize it. Ninepatch support is mostly done. Have you tried building eagle with cmake yet? Or just the code blocks projects?

If you have any feature requests I would probably do them for you.

Doctor Cop

Edgar, What I have used till now is just buttons and labels. I made a calculator with it. I did't do much in it. Yes I used code blocks project, truth to be told It was a college project and I was a beginner, I couldn't compile any other GUI library back then and in search of something I could use I came to liballegro.org and I found your library. Because your Library was available with code blocks project I used it.

I thought of using it more but didn't get the chance to. In future when I make some other mini projects then I will use it. I have also used the code from WidgetZ library because it's minimal, it isn't as large as yours and I found it easy to follow.

GOORE YANNIS

If i want to reset my timer at each level how is that possible i look at stopped_timer and start_timer but he doesn't really work .

Doctor Cop

Its al_stop_timer() by the way.

Can you show me your code?
I can not tell you anything just by that information.

Edgar Reynaldo
GOORE YANNIS

This is my code, and I have a big problem with the al_destroy because i init all objects in the main and i don't know where to destroy them because i have 3 levels and if the player quit in a level i have to destroy the memory of the previous levels so i'm a little bit embarassed if you can help me please I started allegro recently so i have a lot of things i have to improve .

Neil Roy

Have a separate init function to init the data for each level, you could pass it pointers to the data that level needs and then, when a player quits the level, you should call a function you could create to destroy the data which needs it.

Then, once destroyed, you call your level init function to load in the new data for the new level. If you're programming in C++, this should be fairly simple to do. In C I would store the level data in a struct which contains pointers, then pass that struct to the function to destroy it later on.

You could have separate init functions for initializing things like your display, audio etc... data that has nothing to do with any specific level. I wouldn't do it all in main though. The benefit is that if you need to re-initialize anything, you can call such functions from anywhere else. For example, in my Deluxe Pacman 2 game (link to source in my signature), I have a general init function for graphics and audio used throughout the game. I have a shutdown() function which destroys all data when the game is shutdown. But I also have a separate display_init() specifically for setting up your screen. I separated it because in the game's options you can change certain display properties which requires a reset of the display and this can be done by calling that which only effects the display itself.

It's not terribly difficult, try and plan it out so you can, if needed, call some of these functions from anywhere. I have a game struct which contains certain data, like t he display and other things which need to be destroyed when the game ends. I use that in shutdown() which can then be called from anywhere, like if there is an error that would crash the game, it can still be called and cleanly exit.

Edgar Reynaldo
LEVEL* level = CreateLevelOne();
DestroyLevel(&level);
level = CreateLevelTwo();
DestroyLevel(&level);
/// etc...

Your code has some problems. In main.c you #include "MENU.c" that is a no-no, and causes a redefinition error in affichermenu because the function was defined twice, once in main.c and once in MENU.c.

Second, you are mixing pointers with integers. A pointer is not an integer. A pointer is an address. If you want to change the integer pointed to by an int*, you dereference it first, like so :

/// ex...

int state = STATE_GAME;
int* pstate = &state;

ChangeState(pstate);

void ChangeState(int* p) {
   *p = STATE_QUIT;
}

Third, you are missing break statements at the end of several cases.

Fourth, sometimes you incorrectly use = instead of == (warning, suggest use of parentheses around truth statement is the warning given).

Always compile your code with all warnings enabled. -Wall -Wextra -Wshadow

Fix the warnings first, and then try to run your code. If it crashes, run it through a debugger like gdb.

GOORE YANNIS

Okay thanks you i will fix them.
I try to understand game state but i failed so in my menu function there is the address of the variable p which corresponds to the variable niveau(level in english)in the main and when i want to switch my levels i switch the variable niveau(level)so i have 6 game loops 3 for the solo game and 3 for the 2 players mode.

The only problem with this that's i can't comeback to the menu i don't know how to do do it .

Edgar Reynaldo

Levels are a state, and so are screens like the menu. Include the menu screen as a state in your game. If you need to save an old state to return to, like the level, then do so.

Basically you make a decision in your logic and in your drawing on what to draw based on the state.

To change states, set up a tree. Level one can go to level two, level two can go to three. The menu can go to single player or 2P. Then each game has a level.

Represent it like this :

Menu
   Single Player
      Level 1
         Level 2
            Level 3
   Co-op
      Level 1
         Level 2
            Level 3

And each level has a link to the menu, which can then return to the current level if cancelled or another level on loading a game, etc...

Thread #617816. Printed from Allegro.cc