The following code works except I want a FPS counter to display the actual working rate somewhere on the screen or gui. I'm also wondering if I could improve my gameloop in terms of the keyboard exit on escape or anything else (if possible).
I noticed a few things in here:
You are using al_wait_for_event twice in your game loop... You should only do this at one point, because your game will wait for two events each cycle if your event queue is empty at the end of the loop.
You are setting exit to true in your check for escape, but the variable doesn't do anything... You can make your game loop's start look like this: while(!exit) to make it work. You should also change your check for ALLEGRO_EVENT_DISPLAY_CLOSE to exit = true;
As for the FPS, there is a function that returns the current time in the order of milliseconds: al_get_time. You could do something like this:
double old_time = al_get_time(); while(!exit) { //game loop logic here double new_time = al_get_time(); double delta = new_time - old_time; double fps = 1/(delta*1000); old_time = new_time; }
Hope this helps ^^
You should also change your check for ALLEGRO_EVENT_DISPLAY_CLOSE to exit = true;
Do you mean I should do this
else if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) { exit = true; break; }
or this?
else if(ev.type == (exit = true)) { break; }
Also how do I display the fps once its calculated?
thanks.
Do you mean I should do this
No... more something like this:
Don't use break in your main loop. Having multiple exit points makes your code less readable.
As for drawing the FPS: http://www.allegro.cc/manual/5/al_draw_textf
I checked out the font page in the manual and made more changes below but I'm not sure if theres a quick and easy way to convert the fps variable which is double to a const char* (line 90). Any ideas?
al_draw_textf(font,text_color,x,y,FLAG,"FPS: %d",fps);
al_draw_textf(font,text_color,x,y,FLAG,"FPS: %d",fps);
That did draw the fps but now the program seems to endlessly draw text over the same location until its a yellow rectangle plus I cant seem to exit the program, ever. Pressing ESC or trying to close the window wont stop it either, I used process explorer to kill the program.
As for the text: draw it in your drawing code, not the main loop.
I think the reason why it is getting a yellow rectangle is that you are drawing it to the screen without clearing the screen. This makes it overdraw each cycle. You should clear the screen each cycle... What I suggest(because you seem to want to let the screen gradually fill with random lines) is that you should create a bitmap with the screen's dimensions and draw the lines to that one. You can then blit it to the backbuffer and then draw the FPS.
should create a bitmap with the screen's dimensions and draw the lines to that one.
Does al_flip_display() change the ALLEGRO_DISPLAY and the ALLEGRO_BITMAP buffers to which the program is drawing to?
It doesn't change the target bitmap (which is an Allegro concept), but it does swap buffers at a lower level. If you al_flip_display twice in a row you shouldn't be surprised if two different images are flipped onto the visible screen. But if you're following j-gamer's suggestion then you will have to change the target bitmap yourself. Something like this:
al_set_target_bitmap(buffer); al_draw_line(...); al_set_target_backbuffer(display); al_draw_bitmap(buffer, 0, 0, 0); al_flip_display();
Since you have two targets, the buffer, and then later the display, you have to set the target bitmap twice.
What about,
al_draw_textf(ttf_font,al_map_rgb(255,255,0),16,32,0,"FPS: %d",fps);
Would writing it to the display during every event timer update and clearing with,
al_clear_to_color(al_map_rgb(0,0,0))
work?
Yes, if you clear the backbuffer and then draw your text and line onto it then it will look normal, but you will lose any lines you have drawn so far.
In the latest code you posted you check if the event queue is empty, and if it is, then you check the event type. That's not what you want to do. Check the type of each event as you receive one and deal with it accordingly. Check all the events in the queue at once, using al_is_event_queue_empty to see if you have checked them all.
Yes, if you clear the backbuffer and then draw your text and line onto it then it will look normal, but you will lose any lines you have drawn so far.
Right, thats why I wanted to draw the lines to the buffer and never clear it and draw the text to the display and clear it (with every timer update). Am I wrong, would it work?
In the latest code you posted you check if the event queue is empty, and if it is, then you check the event type. That's not what you want to do. Check the type of each event as you receive one and deal with it accordingly. Check all the events in the queue at once, using al_is_event_queue_empty to see if you have checked them all.
Do you mean this
Right, thats why I wanted to draw the lines to the buffer and never clear it and draw the text to the display and clear it (with every timer update). Am I wrong, would it work?
Sure, that should work.
1) Draw lines to buffer
2) Clear backbuffer
3) Draw buffer to backbuffer
4) Draw text to backbuffer
5) Flip display
Do you mean this
Yes. If there are no events in the queue, why would you check them? As it was, you were only checking certain events if they were last in the queue.
Go back to what I was using in the other thread :
This way it will only redraw when you get a timer event. If you want some other behaviour, let me know.
1) Draw lines to buffer
2) Clear backbuffer
3) Draw buffer to backbuffer
4) Draw text to backbuffer
5) Flip display
Wont the lines in the buffer get deleted with every update of the backbuffer (step 2)?
No. You're clearing the backbuffer of the display, not the buffer.
I tried this and now it crashes. Am I supposed to fiddle around with what Trent said every time I redraw?
1) You forgot to initialize the font addon. Initialize it before you initialize the ttf addon. This is why it is crashing.
2) %lf is the correct printf format specifier for a double, not %d, that is for signed integers. Note : After messing with al_draw_textf for a while, it does not recognize %lf as a valid specifier, even though printf does. Use %f and cast fps to a float.
3) You're waiting for events twice, get rid of lines 102 and 103.
4) You're drawing the buffer on top of the FPS counter, so you'll never see it. Swap lines 119 and 120.
EDIT: beaten ._.
I forgot :
5) al_get_time() returns the number of seconds passed since allegro was initialized, not milliseconds. So the correct formula is
mis-read the manual
I made the changes like you said but it still crashed. I commented out the line where the text is printed and that worked except the frame rate slowed to 1 line per second.
al_init_ttf_addon may fail. It returns bool so check the return value. Your font may not be loading properly either. Make sure you are running your program from the directory that contains it or else it will be looking for your font in a different folder.
As for why you're only getting 1 line per second, I can't explain that. When I fixed your code and ran it, it worked at 120 frames per second, just like your fps is set to run at.
Your font may not be loading properly either.
I double checked it and it was in the wrong directory after all but it still doesn't work and I get 1 frame a second with no changes to the last code I posted in this thread.
When I fixed your code and ran it, it worked at 120 frames per second, just like your fps is set to run at.
It would be helpful if you could post that one. Does it have the text printing to the screen or is that the version before that change?
It would be helpful if you could post that one. Does it have the text printing to the screen or is that the version before that change?
Text output is included, and working properly. I double checked, and the following code runs at 120 fps for me (I used a different font, as I don't have your font handy) :
If the above code doesn't work properly for you, try this out for a test :
while (!quit) { al_clear_to_color(al_map_rgb(0,0,0)); double new_time = al_get_time(); float fps = 1.0f/(new_time - old_time); old_time = new_time; al_draw_textf(ttf_font , al_map_rgb(255,255,255) , 0.0 , 0.0 , "FPS : %f" , fps); al_flip_display(); if (!al_is_event_queue_empty()) {quit = true;} }
If the above code doesn't work properly for you, try this out for a test :
The above code did work but I got .5 frames per second on average.
The code after also worked after I made some changes but it just exits after printing the fps.
while (!exit) { al_clear_to_color(al_map_rgb(0,0,0)); double new_time = al_get_time(); float fps = 1.0f/(new_time - old_time); old_time = new_time; al_draw_textf(ttf_font,al_map_rgb(255,255,0), 16, 32,0,"FPS: %f",(float)fps); //al_draw_textf(ttf_font , al_map_rgb(255,255,255) , 0.0 , 0.0 , "FPS : %f" , fps); al_flip_display(); if (!al_is_event_queue_empty(event_queue)) {exit = true;} }
Okay, change the is_event_queue_empty line to this :
if (!al_is_event_queue_empty()) { ALLEGRO_EVENT ev; al_wait_for_event(&ev); if (ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) { break; } }
And see if it still runs slowly for you.
Other ideas :
1) Go back to the regular code, and check the bitmap flags of the bitmap you create and make sure it is a video bitmap :
bitmap = al_create_bitmap(screen_width , screen_height); if (!bitmap) { printf("failed to create bitmap.\n"); return 1; } if (!(al_get_bitmap_flags(bitmap) & ALLEGRO_VIDEO_BITMAP)) { printf("Not a video bitmap!\n"); }
2) Link to the debugging Allegro library and then run your program. Then post the allegro.log file it produces. The devs may be able to see something of why it's so slow in it.
1) Go back to the regular code, and check the bitmap flags of the bitmap you create and make sure it is a video bitmap :
Tried it and I didn't get any text.
Before you try that (messing with your dlls) , try this :
al_set_new_display_flags(ALLEGRO_OPENGL); display = al_create_display(screen_width , screen_height); // As before ........
If you're having trouble with Direct3D and DirectDraw, I would suggest downloading and installing the latest video drivers for your system, from your computer manufacturer if they offer them, or from ati.amd.com or from www.nvidia.com depending on what kind of graphics card you have.
Before you try that (messing with your dlls) , try this :
That fixes it! Thanks.
I prefer OpenGL anyways even when I use Irrlicht I always pick that as my driver. But now my FPS counter is changing so fast I can't even read it.
If you've changed around your DX and D3D dll's I would reinstall my graphics drivers so other programs continue to function properly.
Also, glad the OpenGL drivers work for you.