Hello folks, after giving up on this for a while I'm trying to get my game going again. However, I still have the problem of enormous processor usage and I read I have to place a convenient sleep function in the loop, but since I have never done that, I'm not sure about the structure of my loop and where and how to place the Sleep() or al_rest(). It would be nice if you could help me out with that!
Here is the code:
I though the logical thing to do was to place the sleep function in an else or else if at the end of the main if, however that did nothing to the processor usage.
Thanks for your time.
There shouldn't be enormous processor usage at all because you're calling al_flip_display(). So, there can only be one of two explanations:
1: You're not vsyncing. With a 2D application there's no excuse not to and this alone should dramatically cut down CPU usage. Before creating your display object, use al_set_new_display_option() to set ALLEGRO_VSYNC to 1. The default setting of 0 means to let the video drivers decide, and by default, video drivers tend to be set to NOT vsync.
2: Some video cards have optimizations in place to spread GPU rendering across CPU core usage in order to maximize performance. As you might expect though, this increases CPU usage, sometimes substantially. I don't know if ATI/AMD cards have an option related to this, but with an nVidia card, try disabling its "Threaded Optimization" setting.
As for calling al_rest() or Sleep(), keep in mind that ANY value higher than 0 could potentially give up as much as 50 ms of processing time, which would cut down CPU usage for sure but could also kill your game's performance. On the flip side, a value of 0 only gives up processing time to other threads of equal priority. This means if no such threads exist, no time is given up. It's meant as a method of playing nice with multitasking so you would put al_rest(0.0) or Sleep(0) typically at the end of your game loop. Mine is right after al_flip_display().
Very interesting explanations Kris, particularly for me point number 2.
I didn't know anything about the "threads of equal priority" bit before this.
Just to ask a question off topic: What's the best internet browser to use for this forum. I'm using explorer9 on Vista and explorer10 on Windows7, and I don't seem to be getting this big download button for attachments appearing anywhere. Cheers
Kill IE with fire.
Use Firefox / SeaMonkey / Chrome
Cheers Edgar
Hey Kris, thanks for your answer! I didn't have vsynch enabled, however enabling
it didn't fix the problem. It still has a very high processor usage.
{"name":"7lbnvfd7.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/5\/3\/53f68312e053ddcc40cd064f525724a7.png","w":810,"h":190,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/5\/3\/53f68312e053ddcc40cd064f525724a7"}
As you can see it is much higher than anything else.
I haven't seen the option in ATI and didn't find anything useful by googling, however I will test it later on a PC with an Nvidia card.
Hi Xenowar,
In situations like this, I've always found starting with a simple example that doesn't have the problem, and then gradually adding/replacing sections of code until it eventually becomes the program that does have the problem, helps me.
Just out of interest what CPU usage does this small test program show:
On my 4 year old Vista laptop it shows a varying CPU usage of between 0 to 2 percent. If I change the FPS to 1000 it uses an average of about 50 percent, and an extremely non-linear CPU usage for FPS in-between these values.
I’m off to work now. Cheers
Edit: If this test program uses too much CPU, then I guess it's something along the lines of what Kris has suggested.
Hmm, it has a CPU usage of 0. I guess I will add my code bit by bit and see how that
will change. Hopefully what will show what's at the core of it.
One difference I can see between GaryT's code and your code Xenowar is that you're calling al_clear_to_color(). I'm not sure how much that would affect things though. Clearing the screen does burn some power, but it's odd it would account for 8% of your CPU's maximum capacity. Plus, in my own project, I have to call al_clear_to_color() every frame because of the special effects I'm performing, yet my program uses extremely little CPU power.
Still, 8% is not that bad when you really think about it. Unless you're using 8% of an 8-core, 4GHz CPU. Then... that would be kinda weird.
The clear to color is neccessary, and sadly removing it doesn't solve the problem either.
I identified the code which is responsible for the bad performance and unsuprisingly
it is the loops with which the tiles are drawn
This is the first time I used Tilemaps and I kinda made that stuff up myself, so
I don't know if its really efficient code. If anyone has a way to improve the drawing
of the tiles, it would be nice if you could share that knowledge. Meanwhile I will
look at some tilemap tutorials.
How frequent is your timer "timer" ?
60 times a second.
Strange, how many tiles should you be drawing? (meaning how many should be on the screen)
Out of a total of how many tiles that make up the full map?
The test map is a 30 x 8 two dimenstional array, which will later on differ with
each map. The number of drawn tiles is normally a number of 8x12 (so 96), but since
the tilemap has only some actual content right now it only has to draw about 12
tiles.
What's the code for map1.getWidth()?
It returns the horizontal length of the 2D array, which in this case would be 30.
A few questions :
1) What are focus_horizontal and vertical for?
2) What is offset_horizontal? Is that your camera's x position?
3) Why are you drawing from the bottom up ((SCREEN_H-TILE)-j*TILE) instead of from the top down (j*TILE - camera_y)? You're just making your code harder to read and understand.
Advice :
When you get your tile engine going, you want to draw batches of the same bitmap or sub bitmaps from it at the same time using al_hold_bitmap_drawing before you start, and then again when you're done.
You may want to get into processing arrays by row first instead of by column. It mirrors the arrangement in memory usually (you would have to swap your dimensions and indexing to do so).
And you could probably combine your left and right edge tile drawing into your main tile drawing loop.
It mirrors the arrangement in memory usually
Which ought to improve caching, so that should increase performance too.
1) What are focus_horizontal and vertical for?
focus_horizontal is the number of the first visible tile (array position) on the left side. focus_vertical is the same for the vertical position.
So if we have this screen:
0000000000
0000000000
0000000000
0000000000
the zero in the bottom left corner defines the focus horizontal and vertical.
2) What is offset_horizontal? Is that your camera's x position?
I always draw one tile outside of the visible range. When I move to the right the offset_horizontal increases and once it reachs the tile width focus_horizontal is
incremented by 1 and the offset is set to 0 again.
3) Why are you drawing from the bottom up ((SCREEN_H-TILE)-j*TILE) instead of from the top down (j*TILE - camera_y)? You're just making your code harder to read and understand.
I don't know, it's been a while since I wrote it and I've been lazy with comments.
But since I did it, it might have a reason, probably will make something easier I
will do in future.
I'll try to do that with al_hold_bitmap_drawing. So if I have a row which looks
like this:
111000011111144444
where each number represents a differen image, should I set al_hold_bitmap_drawing
false and true again with each new row of bitmaps coming or just leave it on true
until the row is drawn?
You shold defer bitmap drawing when drawing:
- the same bitmap over and over
- many sub bitmaps from the same parent (either with al_draw_bitmap_region or when created with al_create_sub_bitmap)
...which by the way seems something common when using tilesets
It could all be so much simpler though - I wrote out an example for you. Tilemaps should be fairly simple.
Note, I didn't code any of the loading, that's up to you. Included is a simple camera.