Jump to content
  • Advertisement
Sign in to follow this  
Necrosis

Making a chat window with ClanLib's font engine.

This topic is 4822 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm making a simple multiplayer tetris type game, and I have one final obsticle with the client to overcome. ClanLib lets you make a rectangle, and draw a string into it that word wraps and clips it so if it's too long the end gets clipped off. So I have a big string that holds the most recent text that was displayed, similar to a chat client or any mmorpg with this simple line:
// text window is a CL_Rect covering the area where text history appears
// Chat_Window_Text is the string holding all the history text
FONT.draw(text_window, Chat_Window_Text);

Now there are 17 lines total visible in the space of my rect, and any given line of chat such as something typed in by the user will never be longer than 3 lines in this program. So what I did was make 17 strings, and when a new line is entered, it copies line 2 into line 1 etc until 17 which gets the new line entered put in. Then all 17 lines are copied into the Chat_Window_Text. Now this alone wouldnt work, if any line word wraps into two or three it would clip off that many lines from the end effectively hiding the newest text. So I made a function that first gets the width of the lines, and increases a variable by 1 for every extra lines the engine would word wrap, so if one of the 17 lines would wordwrap into 2, Chat_Window_Text would get string's 2 through 17 to it. This works IF the string with 2 lines is visible, however multiple line strings that are no longer visible but still in one of the 17 strings will cause the whole thing to display one line too high so the lowest line is nothing. I know this is happening because I need to display the second line of a string even if the first line is invisible, which it is not doing with this system. And multiple lines of 3's that are moved off the visible area can raise the lowest line by quite a bit till those multiple lines get pushed out of the buffer entirely and everything relowers itself. Now, I need to approach this differently. I could probably measure each line individually, and clip everything into seperate lines based on their width in the font's pixel length, but then I wont get the word wrapping feature unless I manually do it, which would be a bit of work. Is there an easier way? Can, for example, I tell the FONT.draw to clip everything in reverse, so it draws everything at the end and clips the beginning stuff? This would solve alot and prevent me from having to come up with my own system. I've been trying, but I cant find any example source code, and the api overview didnt quite help since I didnt understand something.
CL_TextStyler::draw

Draws text onto a graphics context.

int draw(int x, int y, const std::string& str, CL_GraphicContext* context = 0);

int draw(CL_Rect dest, const std::string& str, CL_GraphicContext* context = 0);

int draw(int x, int y, std::string::const_iterator start, std::string::const_iterator end, CL_GraphicContext* context = 0);

int draw(CL_Rect dest, std::string::const_iterator start, std::string::const_iterator end, CL_GraphicContext* context = 0);

start - String position to begin rendering at, inclusive.
end - String position to end rendering at, exclusive.
I have NOT been able to figure out how to use std::string::const_iterator start, I'm under the assumption this might be useable to start drawing the entire string from a later point instead of Chat_Window_Text[0], which would then be a matter of measuring the string's length maybe and pass the value to draw at so the last letter in the string is still visible. I couldnt find any examples or any googling to figure out how to use this, I've tried things like:
FONT.draw(text_window,Chat_Window_Text[0],Chat_Window_Text[1000]);
//error C2664: 'int CL_TextStyler::draw(int,int,const std::string &,CL_GraphicContext *) const' : cannot convert parameter 2 from 'char' to 'int'

FONT.draw(text_window,0,Chat_Window_Text);
//compiles but gets runtime error

FONT.draw(text_window,Chat_Window_Text,Chat_Window_Text);
// did this for the hell of it, compiles but displays no text

Please, someone must be familiar with ClanLib fonts to tell me how this works? I noticed the ClanLib questions have a habit of not getting answered on the forums here, but there are no official CL forums or even decent tutorials or examples so I'm hoping some are familiar with this here. Or is there an even better way to have a chat window "reverse clip". Hopefully I explained my problem sufficiently, I appreciate any help.

Share this post


Link to post
Share on other sites
Advertisement
Sorry, probably won't help much - it's too late now, last night I've had 4 hours of sleep, and today won't be much better :-/ Also, your explanation is rather... long :-) and probably I've misunderstood you.


Quote:

Can, for example, I tell the FONT.draw to clip everything in reverse, so it draws everything at the end and clips the beginning stuff? This would solve alot and prevent me from having to come up with my own system. I've been trying, but I cant find any example source code, and the api overview didnt quite help since I didnt understand something.


So, you want to render your text backwards? AFAIK it should work like this:



std :: string foo;
FONT.draw(text_window, foo.rbegin(), foo.rend());

// not sth like that: FONT.draw(text_window, foo.end(), foo.begin() );




It simply swaps begin and end iterators to their reverse versions; read more: http://www.cppreference.com/cppstring/


Quote:

I'm making a simple multiplayer tetris type game


Multiplayer tetris? Man, now that's hardcore ;-) Good luck with it.

Share this post


Link to post
Share on other sites
Thanks for the response, I tend to type too much. I should have mentioned I was doing strings the bad way using char string_name[200]; instead of using std::string which would explain why that part wouldnt work. I did a quick test:


std::string STR_TEST;
STR_TEST = "Just testing, blah blah blah";

FONT.draw(text_window,STR_TEST.begin(),STR_TEST.end());
// works and draws string from start to finish word wrapped and everything
// not quite what I need since I get the same result just passing the str anyways

FONT.draw(text_window,STR_TEST.rbegin(),STR_TEST.rend());
//error C2664: 'int CL_TextStyler::draw(int,int,const std::string &,CL_GraphicContext *) const' :
//cannot convert parameter 2 from 'std::basic_string<_Elem,_Traits,_Ax>::reverse_iterator' to 'int'
// with
// [
// _Elem=char,
// _Traits=std::char_traits<char>,
// _Ax=std::allocator<char>
// ]
// No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called




My conclusion is, the clanlib function isnt designed to draw in the string backwards from bottom to up, and clip the top chat box style, since even if the rbegin and rend worked, it sounds like it would simply print it backwards and clip at the bottom anyways.

I think I will have to manually do this myself, by taking every "line" of text, checking how many pixels in length it is through a clanlib function using the my font, and stick '\n' characters into the right place to seperate one "line" into multiple lines in the master string. Then I can count the total '\n' chars, and if there are over 17 lines, go from the top of the string and remove one line plus the '\n' for every '\n' I have over 17, which will then print just the last 17 lines the player can see, and since every pre-wordwrapped line is broken into multiple lines, it will be able to display just the last parts of a string should they be at the top of the window instead of bringing all the text up leaving a blank line at the bottom or more.

Word wrapping this shouldnt be difficult, once I find out the string is one character too long to fit into the clipped text area, back track to the last space ' ' character and replace it with '\n' and instead of clipping a word into two it'll simply be part of the next line. Gonna be interesting to get it working with a string like "aaaaaaaaaaaaaaaaaaaaaaa" that has no spaces :)

I've been meaning to learn the std library stuff, I just never get around to it! The idea behind a multiplayer tetris is that it's simple enough to develop while learning the new libraries which are ClanLib and RakNet(for the networking part) which will serve as a reference for my future projects like "how the hell did I get a chat window to display correctly with this". I have to admit, I love using these glyphs for fonts, I can make outlined fonts like older games have like Ultima Online or Lineage which makes text readable regardless of what is behind it. More games need to start using this again! Downside is text ends up thicker, ah well :)

If there is a better way to do this, I'm all open for suggestions. I'll work on this tomarrowish since it's 3am already.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • 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!