• 08/14/04 01:44 PM
    Sign in to follow this  
    Followers 0

    Text Input in an Allegro Game

    General and Gameplay Programming

    Myopic Rhino

    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 
    
    #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 
    #include 
    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.

    0


    Sign in to follow this  
    Followers 0


    User Feedback

    Create an account or sign in to leave a review

    You need to be a member in order to leave a review

    Create an account

    Sign up for a new account in our community. It's easy!


    Register a new account

    Sign in

    Already have an account? Sign in here.


    Sign In Now

    There are no reviews to display.