RPG Textbox

I'm making an RPG game, and I've made a function that draws the textbox to the screen. It's almost functional, but there are a few bugs that I can't figure out...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
//ORLY_rpg
struct txtbox_properties{
	txtbox_properties();
	~txtbox_properties();
	int x;
	int y;
	int x1;
	int y1;
	int x2;
	int y2;
	int margin;
	int contkey;
	int textpos;
	int text_speed;
	int border_size;
	TTF_Font* font;
	SDL_Surface* buffer;
	SDL_Surface* text_buffer;
	sprite* contspr;
	sound* click;
	color border_color;
	color fill_color;
	color text_color;}textbox;

txtbox_properties::txtbox_properties(){
	x1=0;
	margin=3;
	contkey=SDLK_SPACE;
	textpos=0;
	text_speed=35;
	border_size=2;
	x=5;
	char buffer[256];
	sprintf(buffer,"%s\\Fonts\\Arial.ttf",getenv("SystemRoot"));
	font=TTF_OpenFont(buffer,13);
	contspr=NULL;
	click=NULL;
	border_color.r=255;
	border_color.g=181;
	border_color.b=0;
	fill_color.r=25;
	fill_color.g=33;
	fill_color.b=66;
	text_color=c_white;}
txtbox_properties::~txtbox_properties(){
	SDL_FreeSurface(textbox.buffer);
	TTF_CloseFont(font);}

int findchr(char* str,char find,int start){
	int size=strlen(str);
	for(;start<size;++start){
		if(str[start]==find){
			return start;}}
	return -1;}

void show_textbox(char* message){
	int a,b,w,num=0,prev=0,size=TTF_FontHeight(textbox.font);
	char buffer[256];
	//char dbuf[256];
	//char letter[2];
	//letter[1]=0;
	SDL_PixelFormat* fmt=game.screen->format;
	//fix variables
	if(MAX(textbox.x1,textbox.x2)==textbox.x2){
		a=textbox.x1;
		textbox.x1=textbox.x2;
		textbox.x2=a;}
	if(MAX(textbox.y1,textbox.y2)==textbox.y2){
		a=textbox.y2;
		textbox.y2=textbox.y1;
		textbox.y1=a;}
	textbox.text_buffer=SDL_CreateRGBSurface(SDL_SWSURFACE,textbox.x2-textbox.x1,textbox.y2-textbox.y1,fmt->BitsPerPixel,fmt->Rmask,fmt->Gmask,fmt->Bmask,fmt->Amask);
	SDL_SetColorKey(textbox.text_buffer,SDL_SRCCOLORKEY,SDL_MapRGB(fmt,255,0,255));
	SDL_FillRect(textbox.text_buffer,NULL,SDL_MapRGB(fmt,255,0,255));
	//draw the text
	SDL_Rect point;
	point.x=textbox.x;
	point.y=textbox.y;
	SDL_Color std_color;
	std_color.r=textbox.text_color.r;
	std_color.g=textbox.text_color.g;
	std_color.b=textbox.text_color.b;
	for(a=0;message[a]!=0;++a,++num){
		refresh();
		update();
		//draw the actual box
		draw_rectangle(textbox.x1,textbox.y1,textbox.x2,textbox.y2,textbox.fill_color,true,game.screen);
		//sprintf(buffer,"x1: %i\ny1: %i\nx2: %i\ny2: %i",textbox.x1,textbox.y1,textbox.x2,textbox.y2);
		//MessageBox(0,buffer,"DEBUG",MB_OK);
		for(b=0;b<textbox.border_size;++b){
			draw_rectangle(textbox.x1+b,textbox.y1+b,textbox.x2-b,textbox.y2-b,textbox.border_color,false,game.screen);}
		switch(message[a]){
			case '\n':
				textbox.x=textbox.x1+textbox.border_size+textbox.margin;
				textbox.y+=size;
				prev=a;
				continue;
			case '|':
				if(message[a+1]=='|' && message[a-1]!='\\'){
					//delay for a moment if we encounter '||' (pause)
					if(key[textbox.contkey]){
						SDL_Delay(textbox.text_speed*5);}//TODO: Redo the delay so that only the textbox pauses
					else{
						SDL_Delay(textbox.text_speed*10);}
					++a;}
				continue;
			case '\\':
				if(message[a+1]=='\\'){
					++a;}
				break;
			case ' '://this handles checking if the text should move to the next line - the bug occurs here
				//check to make sure the text won't go out of bounds if we continue
				b=MIN(findchr(message,'\n',a),findchr(message,' ',a));
				memcpy(buffer,message+prev,b-prev);
				buffer[b-prev]=0;
				TTF_SizeText(textbox.font,buffer,&w,NULL);
				if(w>=textbox.x2-textbox.x1-textbox.border_size*4-textbox.margin*4-2){
					sprintf(buffer,"b: %i\nprev: %i\nBox width: %i\nwidth: %i\nlen: %i",b,prev,textbox.x2-textbox.x1-textbox.border_size*4-textbox.margin*4-2,w,strlen(buffer));
					MessageBox(0,buffer,"DEBUG",MB_OK);
					textbox.x=textbox.x1+textbox.border_size+textbox.margin;
					textbox.y+=size;
					num=0;
					prev+=b;
					++a;}
				break;}
		buffer[0]=message[a];
		buffer[1]=0;
		textbox.buffer=TTF_RenderText_Solid(textbox.font,buffer,std_color);
		point.x=textbox.x-textbox.x1;
		point.y=textbox.y-textbox.y1;
		SDL_BlitSurface(textbox.buffer,NULL,textbox.text_buffer,&point);
		point.x=textbox.x1+textbox.border_size+textbox.margin;
		point.y=textbox.y1+textbox.border_size+textbox.margin;
		SDL_BlitSurface(textbox.text_buffer,NULL,game.screen,&point);
		SDL_Flip(game.screen);
		TTF_SizeText(textbox.font,buffer,&w,NULL);
		SDL_FreeSurface(textbox.buffer);
		textbox.x+=w;
		if(textbox.click!=NULL){
			textbox.click->play();}
		if(key[textbox.contkey]){
			SDL_Delay(textbox.text_speed/2);}
		else{
			SDL_Delay(textbox.text_speed);}}
	while(!key[textbox.contkey]){
		key=SDL_GetKeyState(NULL);}
	//cleanup
	textbox.x=textbox.x1+textbox.border_size+textbox.margin;
	textbox.y=textbox.y1+textbox.border_size+textbox.margin;
	SDL_FreeSurface(textbox.text_buffer);}

...

show_textbox("This is a test that is testing my RPG text function,|| which makes it easy to display what the characters are saying. What they say is a major part of any RPG game, as the player will need to know what's going on. If they don't, they won't be able to properly play the game! Thus it is of utter importance that nearly any RPG game contain a textbox function.");



What it does is it draws the text, letter by letter at a certain speed, and once it gets to the far right end of the textbox, a word goes off the side and it wraps around to the next line. After 2 lines and a word on the third, it crashes.

If you need a working example, I can make one.
Don't answer all at once!


I fixed the bug where it crashes - memcpy was trying to access elements beyond message.

Now I just need to fix the bug where it runs off the edge... any suggestions?
PiMaster wrote:
Don't answer all at once!

I'm not familiar with SDL, but I imagine it would help a lot if you used whitespace to properly format your code and make it easier to read.
When asking about code

Don't ask others to debug your broken code without giving a hint what sort of problem they should be searching for. Posting a few hundred lines of code, saying "it doesn't work", will get you ignored. Posting a dozen lines of code, saying "after line 7 I was expecting to see <x>, but <y> occurred instead" is much more likely to get you a response.

You're really asking for a lot, here. This looks a random piece of code from a larger program.
1. Someone who doesn't know this code uses both SDL and SDL_ttf won't even manage to compile this.
2. The bug might not have even been here. Memory bugs have the unique property that they can make a program crash at any distance from where the bug actually is. Debugging them is like finding a needle in a 6x6x6 km haystack.

By the way, SDL_ttf is... rather broken. If you want to use it for now, fine, but I'd switch to using Freetype directly right away.
I imagine it would help a lot if you used whitespace to properly format your code and make it easier to read.


Sorry, I use unconventional formatting. Large amounts of whitespace make it difficult for me to read...

Well, I made a working example, complete with pre-compiled exe, source, a code blocks project, and all of SDL/SDL_ttf (including dlls, libraries, and headers). You can download the .zip here:

http://www.mediafire.com/file/kzng0xmy2qn/Example.zip

I ran the code through a formatter and did a bunch of find/replace's to add whitespace.


By now, the only bug I really need fixed is the text running off the sides. I'm fairly certain the bug is on lines 272 - 287 in example_functions.h, mostly because those lines handle wrapping the text.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
if (message[a] == ' ')
        {
            //check to make sure the text won't go out of bounds if we continue
            b = MIN(findchr(message, '\n', a+1), findchr(message, ' ', a+1));
            strcopy(buffer, message+prev, b-prev);
            buffer[b-prev] = 0;
            TTF_SizeText(textbox.font, buffer, &w, NULL);
            if (w >= textbox.x2-textbox.x1-textbox.border_size*4-textbox.margin*4-2)
            {
                textbox.x = textbox.x1+textbox.border_size+textbox.margin;
                textbox.y += size;
                num = 0;
                prev += b;
                ++a;
            }
        }


Note: findchr(str, chr, start) - finds a character in a string starting at position start
Note: strcopy(dest, src, num) - copies num characters from src to dest, making sure it isn't accessing elements outside of either array

By the way, helios, what do you mean by FreeType?

Thanks in advance!
Last edited on
http://freetype.sourceforge.net/index2.html
It's the library SDL_ttf uses internally
Eh, any answers?
Topic archived. No new replies allowed.