Allegro 5 Issue

Hi. I've just started learning the basics of this, and made my first progarm in Allegro 5. I have been running this code with different values, and almost each time it behaves in a different way. Am I not allowed to read data from keyboard while using the Allegro ? Is it that what causes the undefined behaviour ?

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
// First Allegro Program

#include <allegro5\allegro.h>
#include <allegro5\allegro_font.h>
#include <allegro5\allegro_ttf.h>
#include <allegro5\allegro_native_dialog.h>
#include <iostream>
#include <string>

ALLEGRO_DISPLAY * display = NULL;

struct RGB { unsigned char RGB_red, RGB_green, RGB_blue; };
struct SCREEN { int W, H; };

SCREEN Screen_Max;

void Initialise_Display();
void Process_Font(std::string);
void Read_And_Process_Text(ALLEGRO_FONT *);
void Print_Text(ALLEGRO_FONT *, std::string, RGB, SCREEN);
void Destroy_Display();

int main (int argc, char **argv)
{
	std::string font_name("Times_New_Roman");
	
	Initialise_Display();
	Process_Font(font_name);
	Destroy_Display();

	return 0;
}

void Initialise_Display()
{
	if (!al_init())
	{
		al_show_native_message_box(display, "Error 101", "A problem occured.", "Display could not be initialised.", NULL, NULL);
		exit(-1);
	}

	display = al_create_display(720,480);

	if (!display)
	{
		al_show_native_message_box(display, "Error 102", "A problem occured.", "Display could not be shown.", NULL, NULL);
		exit(-1);
	}

	Screen_Max.W = al_get_display_width(display);
	Screen_Max.H = al_get_display_height(display);
}

void Process_Font(std::string font)
{
	std::string type(".ttf");
	std::string font_name = font + type;
	const char * _font_name = font_name.c_str();

	al_init_font_addon();
	al_init_ttf_addon();

	ALLEGRO_FONT * font18 = al_load_font(_font_name,18,0);
	ALLEGRO_FONT * font24 = al_load_font(_font_name,24,0);
	ALLEGRO_FONT * font32 = al_load_font(_font_name,32,0);

	char _continue;

	do
	{
		system("cls");

		short option;
		std::cout << "Which font size would you like to use?" << std::endl;
		std::cout << " 1. Times New Roman 18pt." << std::endl;
		std::cout << " 2. Times New Roman 24pt." << std::endl;
		std::cout << " 3. Times New Roman 32pt." << std::endl;
		std::cout << " Your option: ";	std::cin >> option;
	
		switch (option)
		{
			case 1:
				Read_And_Process_Text(font18);
				break;
			case 2:
				Read_And_Process_Text(font24);
				break;
			case 3:
				Read_And_Process_Text(font32);
				break;
			default:
				if (option < 1 || option > 3)
					exit(-1); // if I don't add the whole 'if', it doesn't break, allowing me to insert values such as '24' or so
				break;
		}
		
		std::cout << std::endl << "Would you like to print another text? (Y/N)" << std::endl;
		std::cin >> _continue;

	}while (toupper(_continue) == 'Y');

	al_destroy_font(font18);
	al_destroy_font(font24);
	al_destroy_font(font32);
}

void Read_And_Process_Text(ALLEGRO_FONT * _font)
{
	RGB color;
	SCREEN screen;
	std::string text;
	
	std::cout << "Give the text: "; 
	getline(std::cin, text); // Always skips reading

	std::cout << "What proportion of red/green/blue will the color of the text have? (0-255)" << std::endl;
	std::cout << " (0-255)   Red: "; std::cin >> color.RGB_red;
	std::cout << " (0-255) Green: "; std::cin >> color.RGB_green; // depending on the value of 'red', it is sometimes skipped
	std::cout << " (0-255)  Blue: "; std::cin >> color.RGB_blue; // depending on the value of 'red' and 'green', it is sometimes skipped
	std::cout << std::endl;

	std::cout << "Where exactly on the screen would you like to place the text? (x,y) coordinates: " << std::endl;
	std::cout << "x = "; std::cin >> screen.W; // sometimes skipped
	std::cout << "y = "; std::cin >> screen.H; // sometimes skipped

	try
	{
		if (screen.W < 0 || screen.H < 0 || screen.W > Screen_Max.W || screen.H > Screen_Max.H)
		{
			throw "Error. Invalid input.";
		}
	}
	catch(std::string error)
	{
		std::cout << error;
	}

	Print_Text(_font, text, color, screen);	
}

void Print_Text(ALLEGRO_FONT * _font, std::string _text, RGB _color, SCREEN _screen)
{
	const char * __text = _text.c_str();
	al_draw_text(_font, al_map_rgb(_color.RGB_red, _color.RGB_green, _color.RGB_blue), _screen.W, _screen.H, 0, __text);
	al_flip_display(); // instead of showing the text (which it doesn't read in the read function), it turns the whole display to black
}

void Destroy_Display()
{
	al_destroy_display(display);
}


EDIT: Added the comments.

Thanks in advance,
~ Raul ~
Last edited on
1
2
3
4
default:
if (option < 1 || option > 3)
exit(-1); // if I don't add the whole 'if', it doesn't break, allowing me to insert values such as '24' or so
break;


The "default:" label is entered when the value is neither of the other specified "case:" labels. So, since you have specified cases for '1', '2' and '3', any other case will enter the default label. However, you shouldn't "break;" for the default case, just:
1
2
default:
exit(-1);


See http://www.cplusplus.com/doc/tutorial/control/ for the use of switch.

Also:

 
std::cout << " (0-255)   Red: "; std::cin >> color.RGB_red;


You are defining RGB_red (green and blue) as an unsigned char. The unsigned char can store integral values representing RGB, although by using std::cin like you do here, you are still attempting to read a single character. This means that if the input is of a single character, like "2" , it will work, but if the user input is more than a single character, like "15" or "120", the cin will get only the first character (so if you check your debugger, you'll see that an input of "15" only assigns "1" to RGB_red ).


The other input characters that you have typed will not be cleared however, and this will affect your subsequent uses of cin (for green and blue). That's why they appear to be skipped, while in fact they get the characters that were not received by the previous cin call. E.g:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
using namespace std;

int main()
{
	char c1;
	char c2;

	cin >> c1;

	cin >> c2;

	cout << c1 << endl;

	cout << c2 << endl;


	cin >> c1;

	return 0;
}


Check this out in your debugger with a value of "12" for c1 and see what happens. c1 will get '1' and c2 will get '2' without even prompting you to type something in. If you type "123", you won't even have a chance to see the output before the program closes.

Note the difference:
1
2
3
4
5
6
7

char c1;

c1 = 65;

cout << c1;


This outputs 'A'. Assignment of the integer was successful, but cout outputs 65 as a character, which corresponds to the ASCII code for 'A'. Now, if I did:

 
cout << (int)c1;


This would cast c1 as an integer, and it would outpout 65 for me.



unsigned char can store small integral values while using a small amount of memory space, and it is the input for al_map_rgb(), although you'll have to design your program so that user input gets properly handled, because currently your program only handles a single-digit integral value per color channel, and anything else typed in breaks your program.
Last edited on
Thanks. I forgot about that. Firstly I used the char type and (int) conversion, but I modified it, and yes, that's the problem. But still, do you have any idea why it skips over the text reading?

1
2
3
4
5
// code
std::string text;
std::cout << "Give the text: "; 
getline(std::cin, text); // Always skips reading
//code 
Not sure, have you tried checking the variables in the debugger? Just add a breakpoint in line 109 and step over each line, while keeping an eye on std::string text until you reach getline().
Yep, did that. When it gets to getline, it doesn't allow me to input anything, and it skips it. Though, if I use the following code, it works, but sure, for one word, as the std::cin stops reading when reaching a white space. (None of std::get or std::getline will work for me :| and I have no idea why that...)
1
2
3
4
char _text[255];
std::cout << "Give the text: ";
std::cin >> _text;
std::string text(_text);

If anyone thinks he/she might know the reason why, or how to make this work, please let me know.

Thanks in advance,
~ Raul ~
Yep, did that. When it gets to getline, it doesn't allow me to input anything, and it skips it.
I see. If you observe std::string text in the debugger, it is quite likely that it gets some value assigned after reaching getline() -- even if you don't get a chance to type in anything (that new value of std::string text would be an indication as to what the problem is).

A similar behavior occurs in the sample program I posted with the char c1 and char c2, using std::cin(), when you input more than one digit for c1. (Even though cin() doesn't allow me to type anything for c2 in that case, the assignment of a new value for c2 is traceable in the debugger).
Last edited on
I'm going to check that, but a little later. I have some other things to do now.

Thanks for all the replies.
Topic archived. No new replies allowed.