Allegro: why can't I put allegro_init() and set_gfx_mode in a class?

Started by
9 comments, last by darenking 18 years, 10 months ago
Howdy! I am building a game engine class called Engine, and I was trying to put the Allegro and graphics initialization stuff in the constructor. I want my main() function to be as simple as possible, ideally like this: int main() { Engine engine; while(! key[KEY_ESC]) { engine.Input(); engine.Update(); engine.Output(); } } It seems that I have to put certain things in this main loop though. The program compiles but then crashes as soon as I run it if I put allegro_init(); in the Engine constructor. And of course I need END_OF_MAIN(); at the end of the main(). OK, so maybe there's no real advantage to tidying up the main() function to that extent, and I expect there is no choice of where to initiate Allegro, but I would like to be able to put: install_keyboard(); set_color_depth(DEPTH); set_gfx_mode(MODE, WIDTH, HEIGHT, 0, 0); ...inside my Engine class, either in the constructor or in an Init() method so that I can call it whenever the player wants to change the screen resolution. But when I do so, although the program compiles without error, when I run it, the graphics are displayed wrongly, with the colours wrong and a sort of stripyness to the whole thing, like pinstriped trousers. It would be good to be able to set_gfx_mode in a class method, then I can let the player change the screen resolution, if they find it runs too slowly or whatever. Any ideas?
Advertisement
There's no reason why simply putting the calls into a class would cause it to crash, so the problem lies elsewhere. Perhaps you could narrow down exactly where it crashes?
The only problems you'll have when using any Allegro stuff inside a class, is if you call Allegro functions before main() starts, or after main() ends.

This will only happen if your object has a global scope (global ctors and dtors are run before and after main respectively).

It looks from your (poorly-formatted) example, that you are probably not doing that.

Therefore, there should be no problem.

I have to agree with Kylotan in the opinion that your fault lies elsewhere.

Mark
I don't know how to do tabs in this message board (anyone?) so I've put ___ instead.

The crashing happened when I put allegro_init(); inside my Engine class, which I don't really need to do anyway. Presumably it has to go in main().

I stil have the stripy problem though. My main() now looks like this:

int main()
{
___allegro_init();
___Engine engine;
___engine.Init();

___while(! key[KEY_ESC])
___{
______engine.Input();
______engine.Update();
______engine.Output();
___}

___allegro_exit();
___return 0;

}END_OF_MAIN;

Sorry about the ___ but don't know how to do tabs here.

My engine.Init() (maybe should just move it to the class constructor) looks like this:

void Engine::Init()
{
___install_keyboard();
___set_color_depth(MONITOR_DEPTH);
___set_gfx_mode(MONITOR_MODE, MONITOR_WIDTH, MONITOR_HEIGHT, 0, 0);
}

with this in my header:
#define MONITOR_WIDTH 1280
#define MONITOR_HEIGHT 1024
#define MONITOR_DEPTH 32
#define MONITOR_MODE GFX_AUTODETECT_WINDOWED

It looks OK, doesn't it?

Here's a screen grab of how it looks, the colours are wrong and there's the stripe:
http://www.server32.net/image/game_stripe.jpg
Should look like this:
http://www.server32/image/game_correct.jpg

It works fine with set_color_depth and set_gfx_mode in main(). Problem is the same in full screen mode.

My bitmaps are 24bit. Surely MONITOR_DEPTH should be 24 not 32? But if I set that as 24 I still get the stripe effect.
Update!

It seems that I can put set_gfx_mode in a class method without problem, it's putting set_color_depth in the class that was causing everything to go stripy.

This is OK for me, it means I can allow the player to change the screen resolution, but it does seem a bit odd.

I guess there is no reason why I would want to change the colour depth anyway so it doesn't matter.

Would still be interested to know why this is, if anybody knows?

There is no reason you cannot put allegro_init() in a method. I've done and it works! You must make sure it is the first allegro function called (with the exception of the config functions and some others that may be called without prior initialisation). You should also check the return value (if the function fails you should abort or it will crash).

Keep in mind that you cannot just call set_color_depth() and set_gfx_mode() to change the resolution on the fly, while you are using some form of double buffering (or page flipping). You must first destroy all bitmaps used for the buffering, then change the resolution, and in the end recreate the buffers. I have some C code to demonstrate this, which I can post if you'd like (however, it is somewhat complex because it handles both direct and double buffering (or page flipping) modes (my game can change between them on the fly) ).

Moreover, you should never call set_color_depth() after set_gfx_mode(). If you do, then all blitting routines will do (extremely slow) internal color conversion. Consider the following example:

/* Creates a 32bit screen. When writing to screen the blitting routines will do fast 32bit -> 32bit blitting. */set_color_depth(32);set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0);/* Creates a 8bit (default) screen. When writing to screen the blitting routines will do extremely slow 32bit -> 8bit blitting. */set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0);set_color_depth(32);


Actually, I have encountered this issue myself in some fractal rendering code I made, and corrected it. I can't remember right now what the cause was, but I am 100% sure that I was doing something wrong. There is a good chance that the color conversion is to blame.

Last but not least, you should move the install_keyboard() after the set_gfx_mode(), because there is a slight chance that the former may fail in some platforms when there is no render window. Check the manual for more info (it is very informative).

EDIT: Read the faq to see how to format code in the forum.

[OpenTK: C# OpenGL 4.4, OpenGL ES 3.0 and OpenAL 1.1. Now with Linux/KMS support!]

Lots of issues here to go through.

One thing though: if you have to create a window before you install the keyboard, does that mean you have to reinstall the keyboard every time you recreate all the graphics?

Actually that's probably not really an issue if the program is structured correctly, ie I would create a window at the start, then, if the player chooses to change the screen resolution, that would be done separately. I would only install the keyboard the first time.
Just thought I'd give a few suggestions..

Have you tried doing this?

int main(){    Engine *engine;    engine = new Engine;    //...    delete engine;}


See if that works. This way you can be sure that the Engine object is not being created before main().

Other than this you could add an Initialise() function to your Engine class and move the code from your constructor to this function.
Progress is born from the opportunity to make mistakes.

My prize winning Connect 4 AI looks one move ahead, can you beat it? @nickstadb
Thanks for that, not quite sure why Engine would be created before main() though as I'm declaring it inside main().

int main()
{
Engine engine;
...etc

Seems to run fine anyway, and I've sorted out the original problem, the weird striping effect. Still not sure why but it only works if I have set_color_depth in the main() function where I init Allegro! I can set the graphics mode wherever I like though and that's the important thing as I can let the player change the mode.
Quote:One thing though: if you have to create a window before you install the keyboard, does that mean you have to reinstall the keyboard every time you recreate all the graphics?


I am not sure about this. However, under Linux and Windows (and probably MacOS), you do not need to create a window first, so for 99.9% of the time there won't be any problem.

About the intialisation: please tell me, are there any static methods in your Engine class? I'm trying to trace the problem.

EDIT: OK, after some testing I did not encounter any of the problems. Are you using the latest version (as of now 4.2.0beta3)?

[Edited by - Fiddler on June 17, 2005 5:39:56 PM]

[OpenTK: C# OpenGL 4.4, OpenGL ES 3.0 and OpenAL 1.1. Now with Linux/KMS support!]

This topic is closed to new replies.

Advertisement