Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » help with keyboard menu

This thread is locked; no one can reply to it. rss feed Print
help with keyboard menu
Jefferson Almeida
Member #12,659
March 2011

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
Member #261
April 2000
avatar

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
Member #12,659
March 2011

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

Trent Gamblin
Member #261
April 2000
avatar

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
Major Reynaldo
May 2007
avatar

Jefferson Almeida
Member #12,659
March 2011

Oo" I'm confuse

Thomas Fjellstrom
Member #476
June 2000
avatar

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.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Trent Gamblin
Member #261
April 2000
avatar

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

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Jefferson Almeida
Member #12,659
March 2011

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
Major Reynaldo
May 2007
avatar

Jefferson Almeida
Member #12,659
March 2011

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

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

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
Member #12,659
March 2011

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

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Jefferson Almeida
Member #12,659
March 2011

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
Major Reynaldo
May 2007
avatar

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
Member #12,659
March 2011

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

Go to: