Jump to content
  • Advertisement
  • 08/14/04 01:44 PM
    Sign in to follow this  

    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.



      Report Article
    Sign in to follow this  


    User Feedback


    There are no comments to display.



    Create an account or sign in to comment

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

    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

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!