help with keyboard menu
Jefferson Almeida

Hi... a keyboard menu simple, but I still do not know to make that with allegro =\

#SelectExpand
1#include "header.h" 2#include <windows.h> 3#include <conio.h> 4#include <stdio.h> 5 6#define MaxNo_Menu 5 7 8HANDLE con=GetStdHandle(STD_OUTPUT_HANDLE); 9 10void movexy(int x,int y) 11{ 12 COORD Coord; 13 Coord.X=x; 14 Coord.Y=y; 15 16 SetConsoleCursorPosition(con,Coord); 17} 18 19void textattr(int color) 20{ 21 SetConsoleTextAttribute(con, color); 22} 23 24int main() 25{ 26// This piece of code hides the cursor !! 27HANDLE hConsoleOutput; 28CONSOLE_CURSOR_INFO structCursorInfo; 29hConsoleOutput = GetStdHandle( STD_OUTPUT_HANDLE ); 30GetConsoleCursorInfo( hConsoleOutput, &structCursorInfo ); 31structCursorInfo.bVisible = FALSE; 32SetConsoleCursorInfo( hConsoleOutput, &structCursorInfo ); 33 34 35 char *menu_list[MaxNo_Menu] = { "start", "quit" }; 36 int i, 37 xpos = 10, 38 ypos[MaxNo_Menu] = { 3, 6 }; 39 40 // list the menu 41 for (i=0; i< MaxNo_Menu; ++i) 42 { 43 movexy(xpos, ypos[i] ); 44 textattr(14); 45 printf("%s",menu_list[i] ); 46 } 47 48 // make menu available to choose 49 i=0; 50 while(1) 51 { 52 movexy(xpos, ypos[i]); 53 textattr(16 ); 54 printf("%s",menu_list[i] ); 55 56 switch( _getch() ) 57 { 58 case 72: if(i>0) { 59 movexy(xpos,ypos[i] ); 60 textattr(14); 61 printf("%s", menu_list[i] ); 62 --i; 63 } 64 break; 65 66 case 80: if(i< MaxNo_Menu-1 ) 67 { 68 movexy(xpos,ypos[i] ); 69 textattr(14); 70 printf("%s", menu_list[i] ); 71 ++i; 72 } 73 break; 74 75 case 13: if(i==0) { movexy (10,1); printf("Test... "); } 76 if(i==1) { movexy (10,1); printf("Play "); } 77 if(i==2) { movexy (10,1); printf("Quit"); } 78 break; 79 } 80 } 81 82 return 0; 83}

Trent Gamblin

Here are some hints, I'm not going to write it for you.

readkey will read a key press. Similar to getch.

textout_ex will draw text on the screen.

clear_to_color will clear the screen. You'll want to do that when the cursor moves, then redraw your menu.

With those three functions and some boilerplate initialization code, you can make a menu like the one you have there.

Jefferson Almeida

This would not be in allegro 4? I'm working with allegro 5

Trent Gamblin

Ok then. Things get a little more complex. You're going to have to learn about events and event queues for keyboard (or any other) input. You'll need to know how to initialize Allegro and at a minimum the font and image addons. Here's a quick example, this may not even compile but it should give you an idea of the function calls you'll need for a menu.

#SelectExpand
1#include <allegro5/allegro.h> 2#include <allegro5/allegro_image.h> 3#include <allegro5/allegro_font.h> 4 5ALLEGRO_FONT *font; 6 7const int NUM_MENU_ITEMS = 5; 8int menu_choice = 0; 9 10static void draw_menu(void) 11{ 12 al_draw_text(font, al_map_rgb(255, 255, 255), 100, 0, 0, "Some menu choice"); 13 // repeat menu items (you probably want to align them better) 14 // draw a 'cursor' (a star) 15 al_draw_text(font, al_map_rgb(0, 255, 0), 80, menu_choice*al_get_font_line_height(font), 0, "*"); 16} 17 18int main(int argc, char **argv) 19{ 20 al_init(); 21 al_init_image_addon(); 22 al_init_font_addon(); 23 al_install_keyboard(); 24 25 ALLEGRO_DISPLAY *display = al_create_display(640, 480); 26 ALLEGRO_EVENT_QUEUE *queue = al_create_event_queue(); 27 al_register_event_source(queue, al_get_keyboard_event_source()); 28 29 font = al_load_font("a4font.tga", 0, 0); 30 31 bool quit = false; 32 33 while (!quit) { 34 draw_menu(); 35 ALLEGRO_EVENT event; 36 al_wait_for_event(queue, &event); 37 if (event.type == ALLEGRO_EVENT_KEY_CHAR) { 38 if (event.keyboard.keycode == ALLEGRO_KEY_ESCAPE) 39 quit = true; 40 else if (event.keyboard.keycode == ALLEGRO_KEY_UP) 41 if (menu_choice > 0) 42 menu_choice--; 43 else if (event.keyboard.keycode == ALLEGRO_KEY_DOWN) 44 if (menu_choice < NUM_MENU_ITEMS-1) 45 menu_choice++; 46 } 47 } 48}

Edgar Reynaldo

Do ALLEGRO_KEY_UP and ALLEGRO_KEY_DOWN even register an ALLEGRO_EVENT_KEY_CHAR? Don't you want to use the ALLEGRO_EVENT_KEY_DOWN event type instead?

Jefferson Almeida

Oo" I'm confuse

Thomas Fjellstrom

Do ALLEGRO_KEY_UP and ALLEGRO_KEY_DOWN even register an ALLEGRO_EVENT_KEY_CHAR? Don't you want to use the ALLEGRO_EVENT_KEY_DOWN event type instead?

For text input you want ALLEGRO_EVENT_KEY_CHAR. But they should have some kind of character, but nothing that is printable.

Trent Gamblin

Using ALLEGRO_EVENT_KEY_CHAR would allow for repeats, and yes it does work with the arrow keys.

Edgar Reynaldo

Okay then. I just figured that you wouldn't get an ALLEGRO_EVENT_KEY_CHAR for a key that didn't have a printable character. Guess I was wrong. It works better this way though I guess.

Jefferson Almeida

I'm doing wrong trying to put the menu this way?

#SelectExpand
1 2#include "header.h" 3 4 5const float FPS = 60; 6const int SCREEN_W = 800; 7const int SCREEN_H = 600; 8 9enum GameState { 10 PRESSKEY = 0, 11 SHOWSTART = 1 12}; 13 14GameState state = PRESSKEY; 15 16enum MYKEYS { 17KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_ENTER 18}; 19 20const int NUM_MENU_ITEMS = 5; 21int menu_choice = 0; 22 23class Flasher { 24 private : 25 ALLEGRO_BITMAP *bmp; 26 float x,y; 27 double time_visible; 28 double time; 29 bool visible; 30 public : 31 Flasher(ALLEGRO_BITMAP *bitmap, float xpos, float ypos, float flash_time) : 32 bmp(bitmap), 33 x(xpos), 34 y(ypos), 35 time_visible(0.3), 36 time(0.3), 37 visible(true) 38{} 39void Update(double tsec) { 40 time += tsec; 41 while(time > time_visible) { 42 time -= time_visible; 43 visible = !visible; 44 } 45 } 46 void Draw() { 47 if (visible) { 48 al_draw_bitmap(bmp, x, y, 0); 49 } 50 } 51 }; 52 53 54int main() 55{ 56 ALLEGRO_BITMAP *bmp = NULL; 57 ALLEGRO_DISPLAY *display = NULL; 58 ALLEGRO_FONT *font = NULL; 59 ALLEGRO_EVENT_QUEUE *event_queue = NULL; 60 ALLEGRO_EVENT ev; 61 ALLEGRO_TIMER *timer = NULL; 62 ALLEGRO_BITMAP *remakelogo, *pushstart2, *start, *quit, *seta = NULL; 63 bool doexit = false; 64 bool key[4] = { false, false, false, false }; 65 66 if(!al_init()) { 67 fprintf(stderr, "Failed to initialize Allegro!\n"); 68 return -1; 69 } 70 if(!al_init_primitives_addon()) { 71 fprintf(stderr, "Failed to initialize Addon primitives!\n"); 72 return -1; 73 } 74 al_init_font_addon(); 75 al_init_ttf_addon(); 76 if(!al_init_image_addon()) { 77 fprintf(stderr, "Failed to initialize Image addon!\n"); 78 return -1; 79 } 80 if(!al_install_mouse()) { 81 fprintf(stderr, "Failed to initialize Mouse!\n"); 82 return -1; 83 } 84 if(!al_install_keyboard()) { 85 fprintf(stderr, "Failed to initialize Keyboard!\n"); 86 return -1; 87 } 88 timer = al_create_timer(1.0 / FPS); 89 if(!timer) { 90 fprintf(stderr, "Failed to created timer!\n"); 91 return -1; 92 } 93 //font = al_load_font("a4_font.tga", 15, 0); 94 font = al_load_ttf_font("DejaVuSans.ttf", 15, 0); 95 if(!font) { 96 fprintf(stderr, "Failed to load font!\n"); 97 return -1; 98 } 99 display = al_create_display(SCREEN_W, SCREEN_H); 100 if(!display) { 101 fprintf(stderr, "Failed to initialize Display!\n"); 102 return -1; 103 } 104 105 al_set_target_bitmap(al_get_backbuffer(display)); 106 107 event_queue = al_create_event_queue(); 108 if(!event_queue) { 109 fprintf(stderr, "Failed to create event_queue!\n"); 110 return -1; 111 } 112 remakelogo = al_load_bitmap("images/remakelogo.png"); 113 start = al_load_bitmap("images/start.bmp"); 114 quit = al_load_bitmap("images/quit.bmp"); 115 seta = al_load_bitmap("images/seta.png"); 116 bmp = al_load_bitmap("images/pushstart.png"); 117 if (!(bmp && remakelogo && start && quit && seta)) { 118 fprintf(stderr, "Failed to load images!\n"); 119 return -1; 120 } 121 al_draw_bitmap(remakelogo, 150, 150, 0); 122 al_draw_bitmap(bmp, 250, 320, 0); 123 124 125 al_register_event_source(event_queue, al_get_display_event_source(display)); 126 127 al_register_event_source(event_queue, al_get_timer_event_source(timer)); 128 129 al_register_event_source(event_queue, al_get_keyboard_event_source()); 130 131 al_flip_display(); 132 133 al_start_timer(timer); 134 135 136Flasher myflasher(bmp, 250, 320, 0.5);// Make sure to pass a valid flash_time! 137 138bool redraw = true; 139while (!doexit) { 140 if (redraw) { 141 al_clear_to_color(al_map_rgb(0,0,0)); 142 al_draw_bitmap(remakelogo, 150, 150, 0); 143 switch (state) { 144 case PRESSKEY : 145 myflasher.Draw(); 146 break; 147 case SHOWSTART : 148 149 al_draw_text(font, al_map_rgb(255, 255, 255), 250, 360, 0, "Start"); 150 al_draw_text(font, al_map_rgb(255, 255, 255), 250, 380, 0, "Options"); 151 al_draw_text(font, al_map_rgb(255, 255, 255), 250, 400, 0, "Quit"); 152 al_draw_text(font, al_map_rgb(0, 255, 0), 240, 360+menu_choice*al_get_font_line_height(font), 0, "*"); 153 if (ev.type == ALLEGRO_EVENT_KEY_CHAR) 154 if (ev.keyboard.keycode == ALLEGRO_KEY_ESCAPE) 155 doexit = false; 156 if (ev.keyboard.keycode == ALLEGRO_KEY_UP) 157 if (menu_choice > 0) 158 menu_choice--; 159 else if (ev.keyboard.keycode == ALLEGRO_KEY_DOWN) 160 if (menu_choice < NUM_MENU_ITEMS-1) 161 menu_choice++; 162 break; 163 } 164 165 al_flip_display(); 166 redraw = false; 167 } 168 while (1) { 169 ALLEGRO_EVENT ev; 170 al_wait_for_event(event_queue , &ev); 171 switch (state) { 172 case PRESSKEY : 173 if (ev.type == ALLEGRO_EVENT_TIMER) { 174 myflasher.Update(1.0/FPS); 175 } else if (ev.type == ALLEGRO_EVENT_KEY_DOWN) { 176 if (ev.keyboard.keycode == ALLEGRO_KEY_ENTER) { 177 state = SHOWSTART; 178 } 179 } 180 break; 181 case SHOWSTART : 182 break; 183 } 184 if (ev.type == ALLEGRO_EVENT_TIMER) { 185 redraw = true; 186 } else if (ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) { 187 doexit = true; 188 break; 189 } 190 if (al_is_event_queue_empty(event_queue)) {break;} 191 } 192} 193 return 0; 194} 195 196 197 198//END_OF_MAIN()

Edgar Reynaldo

I'm doing wrong trying to put the menu this way?

Somewhat, yes.

Take the ALLEGRO_EVENT_KEY_CHAR check out of your drawing code, and put it in your event loop.

Jefferson Almeida

Just ALLEGRO_EVENT_KEY_CHAR or all included if (ev.keyboard.keycode == ALLEGRO_KEY_ESCAPE).... etc?

Edgar Reynaldo

All code that deals with events should be inside your event loop. And you're missing some brackets there too. You should only check event.keyboard.keycode if you have received an ALLEGRO_EVENT_KEY_DOWN, ALLEGRO_EVENT_KEY_UP, or an ALLEGRO_EVENT_KEY_CHAR type event.

Jefferson Almeida

I don't know if are right but I added after "while (1)" but did not work! I'm revising!

Edgar Reynaldo

Post your latest code.

Jefferson Almeida

here

#SelectExpand
1 2#include "header.h" 3 4 5const float FPS = 60; 6const int SCREEN_W = 800; 7const int SCREEN_H = 600; 8 9enum GameState { 10 PRESSKEY = 0, 11 SHOWSTART = 1 12}; 13 14GameState state = PRESSKEY; 15 16enum MYKEYS { 17KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_ENTER 18}; 19 20const int NUM_MENU_ITEMS = 5; 21int menu_choice = 0; 22 23class Flasher { 24 private : 25 ALLEGRO_BITMAP *bmp; 26 float x,y; 27 double time_visible; 28 double time; 29 bool visible; 30 public : 31 Flasher(ALLEGRO_BITMAP *bitmap, float xpos, float ypos, float flash_time) : 32 bmp(bitmap), 33 x(xpos), 34 y(ypos), 35 time_visible(0.3), 36 time(0.3), 37 visible(true) 38{} 39void Update(double tsec) { 40 time += tsec; 41 while(time > time_visible) { 42 time -= time_visible; 43 visible = !visible; 44 } 45 } 46 void Draw() { 47 if (visible) { 48 al_draw_bitmap(bmp, x, y, 0); 49 } 50 } 51 }; 52 53 54int main() 55{ 56 ALLEGRO_BITMAP *bmp = NULL; 57 ALLEGRO_DISPLAY *display = NULL; 58 ALLEGRO_FONT *font = NULL; 59 ALLEGRO_EVENT_QUEUE *event_queue = NULL; 60 ALLEGRO_EVENT ev; 61 ALLEGRO_TIMER *timer = NULL; 62 ALLEGRO_BITMAP *remakelogo, *pushstart2, *start, *quit, *seta = NULL; 63 bool doexit = false; 64 bool key[4] = { false, false, false, false }; 65 66 if(!al_init()) { 67 fprintf(stderr, "Failed to initialize Allegro!\n"); 68 return -1; 69 } 70 if(!al_init_primitives_addon()) { 71 fprintf(stderr, "Failed to initialize Addon primitives!\n"); 72 return -1; 73 } 74 al_init_font_addon(); 75 al_init_ttf_addon(); 76 if(!al_init_image_addon()) { 77 fprintf(stderr, "Failed to initialize Image addon!\n"); 78 return -1; 79 } 80 if(!al_install_mouse()) { 81 fprintf(stderr, "Failed to initialize Mouse!\n"); 82 return -1; 83 } 84 if(!al_install_keyboard()) { 85 fprintf(stderr, "Failed to initialize Keyboard!\n"); 86 return -1; 87 } 88 timer = al_create_timer(1.0 / FPS); 89 if(!timer) { 90 fprintf(stderr, "Failed to created timer!\n"); 91 return -1; 92 } 93 //font = al_load_font("a4_font.tga", 15, 0); 94 font = al_load_ttf_font("DejaVuSans.ttf", 15, 0); 95 if(!font) { 96 fprintf(stderr, "Failed to load font!\n"); 97 return -1; 98 } 99 display = al_create_display(SCREEN_W, SCREEN_H); 100 if(!display) { 101 fprintf(stderr, "Failed to initialize Display!\n"); 102 return -1; 103 } 104 105 al_set_target_bitmap(al_get_backbuffer(display)); 106 107 event_queue = al_create_event_queue(); 108 if(!event_queue) { 109 fprintf(stderr, "Failed to create event_queue!\n"); 110 return -1; 111 } 112 remakelogo = al_load_bitmap("images/remakelogo.png"); 113 start = al_load_bitmap("images/start.bmp"); 114 quit = al_load_bitmap("images/quit.bmp"); 115 seta = al_load_bitmap("images/seta.png"); 116 bmp = al_load_bitmap("images/pushstart.png"); 117 if (!(bmp && remakelogo && start && quit && seta)) { 118 fprintf(stderr, "Failed to load images!\n"); 119 return -1; 120 } 121 al_draw_bitmap(remakelogo, 150, 150, 0); 122 al_draw_bitmap(bmp, 250, 320, 0); 123 124 125 al_register_event_source(event_queue, al_get_display_event_source(display)); 126 127 al_register_event_source(event_queue, al_get_timer_event_source(timer)); 128 129 al_register_event_source(event_queue, al_get_keyboard_event_source()); 130 131 al_flip_display(); 132 133 al_start_timer(timer); 134 135 136Flasher myflasher(bmp, 250, 320, 0.5);// Make sure to pass a valid flash_time! 137 138bool redraw = true; 139while (!doexit) { 140 if (redraw) { 141 al_clear_to_color(al_map_rgb(0,0,0)); 142 al_draw_bitmap(remakelogo, 150, 150, 0); 143 switch (state) { 144 case PRESSKEY : 145 myflasher.Draw(); 146 break; 147 case SHOWSTART : 148 149 al_draw_text(font, al_map_rgb(255, 255, 255), 250, 360, 0, "Start"); 150 al_draw_text(font, al_map_rgb(255, 255, 255), 250, 380, 0, "Options"); 151 al_draw_text(font, al_map_rgb(255, 255, 255), 250, 400, 0, "Quit"); 152 al_draw_text(font, al_map_rgb(0, 255, 0), 240, 360+menu_choice*al_get_font_line_height(font), 0, "*"); 153 break; 154 } 155 al_flip_display(); 156 redraw = false; 157 } 158 while (1) { 159 ALLEGRO_EVENT ev; 160 al_wait_for_event(event_queue , &ev); 161 switch (state) { 162 case PRESSKEY : 163 if (ev.type == ALLEGRO_EVENT_TIMER) { 164 myflasher.Update(1.0/FPS); 165 } else if (ev.type == ALLEGRO_EVENT_KEY_DOWN) { 166 if (ev.keyboard.keycode == ALLEGRO_KEY_ENTER) { 167 state = SHOWSTART; 168 } 169 } 170 break; 171 case SHOWSTART : 172 if (ev.type == ALLEGRO_EVENT_KEY_CHAR) 173 if (ev.keyboard.keycode == ALLEGRO_KEY_ESCAPE) 174 doexit = false; 175 break; 176 if (ev.keyboard.keycode == ALLEGRO_KEY_UP) 177 if (menu_choice > 0) 178 menu_choice--; 179 else if (ev.keyboard.keycode == ALLEGRO_KEY_DOWN) 180 if (menu_choice < NUM_MENU_ITEMS-1) 181 menu_choice++; 182 break; 183 } 184 if (ev.type == ALLEGRO_EVENT_TIMER) { 185 redraw = true; 186 } else if (ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) { 187 doexit = true; 188 break; 189 } 190 if (al_is_event_queue_empty(event_queue)) {break;} 191 } 192} 193 return 0; 194} 195 196 197 198//END_OF_MAIN()

Edgar Reynaldo

Change

         case SHOWSTART :
         if (ev.type == ALLEGRO_EVENT_KEY_CHAR)
           if (ev.keyboard.keycode == ALLEGRO_KEY_ESCAPE)
           doexit = false;
           break;
            if (ev.keyboard.keycode == ALLEGRO_KEY_UP)
                if (menu_choice > 0)
                    menu_choice--;
            else if (ev.keyboard.keycode == ALLEGRO_KEY_DOWN)
                if (menu_choice < NUM_MENU_ITEMS-1)
                    menu_choice++;
            break;

to

#SelectExpand
1 case SHOWSTART : 2 if (ev.type == ALLEGRO_EVENT_KEY_CHAR) { 3 if (ev.keyboard.keycode == ALLEGRO_KEY_ESCAPE) { 4 doexit = true; 5 } 6 else if (ev.keyboard.keycode == ALLEGRO_KEY_UP) { 7 if (menu_choice > 0) { 8 menu_choice--; 9 } 10 } 11 else if (ev.keyboard.keycode == ALLEGRO_KEY_DOWN) { 12 if (menu_choice < NUM_MENU_ITEMS-1) { 13 menu_choice++; 14 } 15 } 16 } 17 break;

Your code doesn't work because it breaks out of the switch statement every time you check the 'case SHOWSTART'.

I told you to add brackets.

Also, you should set doexit to true when the escape key is pressed, not false.

You should really use consistent indentation in your code. It's much nicer to read that way.

Jefferson Almeida

work! Thank you for the explanation and help! :)

Thread #607347. Printed from Allegro.cc