Text Input in an Allegro Game
Describes how to process input using both C and C++.
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.
Related Tutorials
Balancing Game Development and Creative Direction in Indie Production
A practical look at how indie developers can balance creative direction with hands-on game development. This article co…
My Unreal Engine Development Process: From Core Idea to Playable Build
A practical overview of my Unreal Engine development process, covering how I move from a core game idea to a playable b…
Introducing LaneGraph: The Ultimate Road Network Solution for Unity
Discover the power of LaneGraph, a lightweight and flexible lane-based navigation system for Unity. LaneGraph makes it…
Retargeting Mixamo Characters with Root Motion In Unreal Engine 5.4.
I have always found Retargeting Mixamo Characters To have Root Motion is a serious lengthy Tast, Recently I stumbled up…
How To Make A SIMPLE Main Menu In Unity
In this tutorial for unity, i go over how to make a simple main menu for unity, it's an unlisted video because i do not…
Guide to Gameplay Balance
A perspective on competitive gameplay balance, from a background of "shooter" sandbox design.
Discussion
More from Chris "23yrold3yrold" Barry
Comparing Shadow Mapping Techniques with Shadow Explorer
New Incentives and a Whole New Platform From The Intel AppUp developer program
The final installment in this series on Intel's AppUp program details additional incentives and opportunities for devel…
The Game Maker
This book excerpt contains the first chapter of the book that introduces beginning game developers to the Game Maker pr…
Discussion