Text Input in an Allegro Game
A common request in the Allegro forums is for a way to process player text input. cin doesn't work. The Allegro GUI does, but is simplistic and limiting (*cough* and ugly *cough*). Back when I wrote an article on the standard C++ string class, I wrote a small C++ program that stored player input in a std::string. Since then, I made a simpler C version that uses a char array. The code is very short and simple to use, so modifying it for your purposes (to word wrap, for example, if you want that) is dirt easy. I get asked for it often, so I'm just submitting it for ease of finding. Both the C and C++ version just take the input and print it onscreen. The C++ version lets you move the caret around, processes the Insert key to toggle replacing and inserting, and lets you both delete and backspace. None of that's really necessary; It's only there because the string class makes it so easy. The functionality can be added to the C version easily enough, I know. But I'm a lazy spoilt C++ coder, so all effort to that end is left as an exercise to the reader. Here is the C version. // edittext.c #include <allegro.h> #define BUFFERSIZE 128 #define WHITE makecol(255, 255, 255) int main() { BITMAP* buffer = NULL; char edittext[BUFFERSIZE]; int caret = 0; /* typical Allegro initialization */ allegro_init(); install_keyboard(); set_gfx_mode(GFX_AUTODETECT, 320, 240, 0, 0); buffer = create_bitmap(320, 240); do { if(keypressed()) { int newkey = readkey(); char ASCII = newkey & 0xff; char scancode = newkey >> 8; /* a character key was pressed; add it to the string */ if(ASCII >= 32 && ASCII <= 126) { if(caret < BUFFERSIZE - 1) { edittext[caret] = ASCII; caret++; edittext[caret] = '\0'; } } else if(scancode == KEY_BACKSPACE) { if (caret > 0) caret--; edittext[caret] = '\0'; } } /* all drawing goes here */ clear(buffer); textout(buffer, font, edittext, 0, 10, WHITE); vline(buffer, caret * 8, 8, 18, WHITE); blit(buffer, screen, 0, 0, 0, 0, 320, 240); } while(!key[KEY_ESC]); destroy_bitmap(buffer); return 0; } END_OF_MAIN() The C++ version, as stated, is slightly more robust. This is essentially the code from my original article. C++: // edittext.cpp #include <allegro.h> #include <string> using namespace std; #define WHITE makecol(255, 255, 255) int main() { // typical Allegro initialization allegro_init(); install_keyboard(); set_gfx_mode(GFX_AUTODETECT, 320, 240, 0, 0); // all variables are here BITMAP* buffer = create_bitmap(320, 240); // initialize the double buffer string edittext; // an empty string for editting string::iterator iter = edittext.begin(); // string iterator int caret = 0; // tracks the text caret bool insert = true; // true if text should be inserted // the game loop do { while(keypressed()) { int newkey = readkey(); char ASCII = newkey & 0xff; char scancode = newkey >> 8; // a character key was pressed; add it to the string if(ASCII >= 32 && ASCII <= 126) { // add the new char, inserting or replacing as need be if(insert || iter == edittext.end()) iter = edittext.insert(iter, ASCII); else edittext.replace(caret, 1, 1, ASCII); // increment both the caret and the iterator caret++; iter++; } // some other, "special" key was pressed; handle it here else switch(scancode) { case KEY_DEL: if(iter != edittext.end()) iter = edittext.erase(iter); break; case KEY_BACKSPACE: if(iter != edittext.begin()) { caret--; iter--; iter = edittext.erase(iter); } break; case KEY_RIGHT: if(iter != edittext.end()) caret++, iter++; break; case KEY_LEFT: if(iter != edittext.begin()) caret--, iter--; break; case KEY_INSERT: insert = !insert; break; default: break; } } // clear screen clear(buffer); // output the string to the screen textout(buffer, font, edittext.c_str(), 0, 10, WHITE); // output some stats using Allegro's printf functions textprintf(buffer, font, 0, 20, WHITE, "length: %d", edittext.length()); textprintf(buffer, font, 0, 30, WHITE, "capacity: %d", edittext.capacity()); textprintf(buffer, font, 0, 40, WHITE, "empty?: %d", edittext.empty()); if(insert) textout(buffer, font, "Inserting", 0, 50, WHITE); else textout(buffer, font, "Replacing", 0, 50, WHITE); // draw the caret vline(buffer, caret * 8, 8, 18, WHITE); // blit to screen blit(buffer, screen, 0, 0, 0, 0, 320, 240); }while(!key[KEY_ESC]); // end of game loop // clean up destroy_bitmap(buffer); set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); return 0; } END_OF_MAIN() I hope that was helpful to you. Comments, questions, feedback, etc. can be posted in the forums or sent to crbarry@mts.net. Discuss this article in the forums
See Also: © 1999-2011 Gamedev.net. All rights reserved. Terms of Use Privacy Policy
|