# What's the most efficient way to deal with in-game messages in Allegro 5?

I have a little 2D game made with Allegro, and I want to introduce strings during gameplay. For example, I've just made it so a key is needed to open a door, so I'd need some tutorial text to appear when the player collides with the door that tells them they need the key first.
This is just a learning experience for me, really - the key is pretty visible but I would like to learn how to handle this sort of messages especially for tutorial purposes in a bigger, better game.

Right now, during gameplay, I have running game_loop() (which handles player movement, collisions etc) and game_render(), which obviously runs after it. To introduce these messages, what I have successfully done so far is to add a global std::vector<const char*> to which I push_back messages whenever appropriate.

My message_renderer() then goes like so:

static double t = 0, c = 0;

if (!messages.empty())
{

for (unsigned int i = 0; i < messages.size(); i++)
{

al_draw_text(font18, al_map_rgb_f(255, 255, 255), wWidth / 2, wHeight - 50, ALLEGRO_ALIGN_CENTRE, messages[i]);
if (t < 2)
{
t += get_dt();
c += get_dt();
if (c > 1)
c = 1;
}
else
{
t = 0;
c = 0;
messages.pop_back();
}

}
}


I then call this message_renderer() in my game_render() after I've drawn everything else, to ensure that the message appears on top.

Now, again, this does work - the message displays for 2 seconds at render time once it's added to the vector. However, this solution doesn't really seem particularly neat to me, since as far as I know there are standardised ways of dealing with these sort of events - I just don't know what they are!

So my question is - is my current method efficient enough? Can it be improved, in Allegro (or generally, in logic!) and if so, how?

EDIT: I've modified the code since posting the question, so it should now behave like expected - showing a message for 3 seconds. It does so, but when I have two strings in the vector at the same time they overlap - I thought the timer would work as "pause" between each iteration but I guess not... If someone could point me in the right direction for that too, it'd be much appreciated :)

• Why not use std::string instead of const char* ? You have the benefits of the standard C++ class, and you can retrieve the pointer needed by Allegro with std::string::c_str(). Aug 2 '14 at 21:48
• Thanks for your reply! So as you say, I would have the text as std::strings (in my "text file"), then I'd add them to a vector of strings, and retrieve them with c_str()? Wouldn't that clash with Allegro's draw text function which needs a const char (as far as I'm aware)? Aug 3 '14 at 9:20
• That's perfectly fine, C++ is able to construct std::strings from const char* and the c_str() function is here to get access to the underlying null-terminated character string, for cases like yours. Aug 3 '14 at 10:08
• Fantastic, thanks very much - I'll give that a go :) Aug 3 '14 at 10:10

You can use std::ostringstreams to push anything (even non-char variables) into a stream and convert it to a string:

std::ostringstream ss;
ss << "Some text: " << some_variable;
//...
al_draw_text(font28, al_map_rgb_f(255, 255, 255), wWidth / 2, (wHeight / 2) - 28, ALLEGRO_ALIGN_CENTRE, ss.str().c_str());
ss.str(""); //Clear stream contents.

• Thanks for your reply! Can I ask - did you suggest this because it's better or easier to use strings than chars? Aug 2 '14 at 19:48
• @Nicholas std::strings are indeed easier to use, and much more powerful. But Casey's answer is about string streams, which are a different thing. Check out the documentation and don't forget to add ss.clear() to cleanly reset your stream (see stackoverflow.com/a/2848109/1119972). Aug 2 '14 at 21:53
• I suggested using std::ostringstreams because if you ever wanted to output a number into a string it is a lot less of a hassle than trying to do it using a std::string. Aug 2 '14 at 23:34
• Thank you both! I didn't know of the actual relationship between char and string in C++... I think it's starting to make sense now. I'll try ostringstream - cheers! Aug 3 '14 at 10:12

al_draw_text contains arguments where you specify the position to start writing your string. Normally that means the first character will be at the specified position and the rest of the characters continue to the right (although this - the text alignment - can be changed via the flags argument).
• If you want to control the positioning yourself, specify a different position to draw the second string. If you want to make sure the text doesn't overlap, or for the layout to adapt to different fonts and sizes, you can use the drawn size of the first string by using al_get_text_dimensions or the related functions.