|
How to structure the program for a Sleep() or al_rest() |
Xenowar
Member #12,630
March 2011
|
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: 1 while(1) {
2 ALLEGRO_EVENT ev;
3 al_wait_for_event(event_queue, &ev);
4
5 if(ev.type == ALLEGRO_EVENT_TIMER && ev.timer.source == timer) {
6 redraw = true;
7 }
8
9 if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
10 return 1;
11 }
12
13 if(ev.type == ALLEGRO_EVENT_KEY_DOWN) {
14 if(ev.keyboard.keycode==ALLEGRO_KEY_UP) {
15
16 }
17 if(ev.keyboard.keycode==ALLEGRO_KEY_DOWN) {
18
19 }
20 if(ev.keyboard.keycode==ALLEGRO_KEY_LEFT) {
21 left=true;
22 }
23 if(ev.keyboard.keycode==ALLEGRO_KEY_RIGHT) {
24 right=true;
25 }
26 }
27 if(ev.type == ALLEGRO_EVENT_KEY_UP){
28 if(ev.keyboard.keycode==ALLEGRO_KEY_UP) {
29
30 }
31 if(ev.keyboard.keycode==ALLEGRO_KEY_DOWN) {
32
33 }
34 if(ev.keyboard.keycode==ALLEGRO_KEY_LEFT) {
35 left=false;
36 }
37 if(ev.keyboard.keycode==ALLEGRO_KEY_RIGHT) {
38 right=false;
39 }
40 }
41
42
43 if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN) {
44 al_get_mouse_state(&state);
45 mouse_x=al_get_mouse_state_axis(&state,0);
46 mouse_y=al_get_mouse_state_axis(&state,1);
47 if ([...]){
48 [...]
49 }
50 }
51
52 if(redraw && al_is_event_queue_empty(event_queue)) {
53 redraw = false;
54
55 offset_horizontal = camera_x % TILE;
56 focus_horizontal = camera_x / TILE;
57
58 if(left){
59 if(player_x>0){
60 player_x-=8;
61 if(player_x>=SCREEN_W/2)
62 camera_x-=8;
63 }
64 }
65 if(right){
66 player_x+=8;
67 if(player_x>SCREEN_W/2)
68 camera_x+=8;
69 }
70
71
72 al_clear_to_color(al_map_rgb(0,0,0));
73 for(int i = 0; i < 10;i++){
74 for(int j =0; j<8;j++){
75 switch(map1.Map2D[focus_horizontal+i][focus_vertical+j]){
76 case 0:
77 break;
78 case 1:
79 al_draw_bitmap(grass, i*TILE-offset_horizontal, (SCREEN_H-TILE)-j*TILE, 0);
80 break;
81 default:
82 break;
83 };
84
85 }
86 }
87 if(focus_horizontal>0){
88 for(int j = 0; j < 10;j++){
89 switch(map1.Map2D[focus_horizontal-1][focus_vertical+j]){
90 case 0:
91 break;
92 case 1:
93 al_draw_bitmap(grass, -TILE-offset_horizontal, (SCREEN_H-TILE)-j*TILE, 0);
94 break;
95 default:
96 break;
97 };
98 }
99 }
100 if(focus_horizontal<map1.getWidth()-1-(SCREEN_W/TILE)){
101 for(int j = 0; j < 10;j++){
102 switch(map1.Map2D[focus_horizontal+(SCREEN_W/TILE)][focus_vertical+j]){
103 case 0:
104 break;
105 case 1:
106 al_draw_bitmap(grass, SCREEN_W-offset_horizontal, (SCREEN_H-TILE)-j*TILE, 0);
107 break;
108 default:
109 break;
110 };
111 }
112 }
113 if(player_x >= SCREEN_W/2){
114 al_draw_bitmap(chara, SCREEN_W/2, player_y, 0);
115 }
116 else{
117 al_draw_bitmap(chara, player_x, player_y, 0);
118 }
119 al_flip_display();
120 }
121 }
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. |
Kris Asick
Member #1,424
July 2001
|
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(). --- Kris Asick (Gemini) |
GaryT
Member #14,875
January 2013
|
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 |
Edgar Reynaldo
Major Reynaldo
May 2007
|
Kill IE with fire. Use Firefox / SeaMonkey / Chrome My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
GaryT
Member #14,875
January 2013
|
Cheers Edgar |
Xenowar
Member #12,630
March 2011
|
Hey Kris, thanks for your answer! I didn't have vsynch enabled, however enabling {"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"} 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. |
GaryT
Member #14,875
January 2013
|
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: 1#include <allegro5\allegro.h>
2#include <allegro5\allegro_primitives.h>
3
4const int WIDTH = 800;
5const int HEIGHT = 600;
6
7int FPS = 60;
8
9bool done = false;
10
11int main(void)
12{
13 ALLEGRO_DISPLAY *display = NULL;
14 ALLEGRO_EVENT_QUEUE *event_queue = NULL;
15 ALLEGRO_TIMER *timer = NULL;
16
17 if(!al_init())
18 return -1;
19
20 display = al_create_display(800, 600);
21
22 if(!display)
23 return - 1;
24
25 al_init_primitives_addon();
26 al_install_keyboard();
27
28 event_queue = al_create_event_queue();
29 timer = al_create_timer(1.0 / FPS);
30
31 al_register_event_source(event_queue, al_get_keyboard_event_source());
32 al_register_event_source(event_queue, al_get_display_event_source(display));
33 al_register_event_source(event_queue, al_get_timer_event_source(timer));
34
35 al_start_timer(timer);
36
37 while(!done)
38 {
39 ALLEGRO_EVENT ev;
40
41 al_wait_for_event(event_queue, &ev);
42
43 if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE)
44 done = true;
45
46 if(ev.type == ALLEGRO_EVENT_KEY_DOWN)
47 {
48 switch(ev.keyboard.keycode)
49 {
50 case ALLEGRO_KEY_C:
51 al_draw_filled_circle(WIDTH/2, HEIGHT/2, 100, al_map_rgb(50, 200, 50));
52 break;
53
54 case ALLEGRO_KEY_SPACE:
55 al_draw_filled_circle(WIDTH/2, HEIGHT/2, 100, al_map_rgb(0, 0, 0));
56 break;
57 }
58 }
59
60 if(ev.type == ALLEGRO_EVENT_TIMER)
61 al_flip_display();
62 }
63
64 al_destroy_timer(timer);
65 al_destroy_display(display);
66 al_destroy_event_queue(event_queue);
67
68 return 0;
69}
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. |
Xenowar
Member #12,630
March 2011
|
Hmm, it has a CPU usage of 0. I guess I will add my code bit by bit and see how that |
Kris Asick
Member #1,424
July 2001
|
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. --- Kris Asick (Gemini) |
Xenowar
Member #12,630
March 2011
|
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 1//draws all tiles in focus
2 for(int i = 0; i < 10;i++){
3 for(int j =0; j<8;j++){
4 switch(map1.Map2D[focus_horizontal+i][focus_vertical+j]){
5 case 0:
6
7 break;
8 case 1:
9 al_draw_bitmap(grass, i*TILE-offset_horizontal, (SCREEN_H-TILE)-j*TILE, 0);
10 break;
11 default:
12 break;
13 };
14
15 }
16 }
17 //draws tiles out of the left of the window
18 if(focus_horizontal>0){
19 for(int j = 0; j < 10;j++){
20 switch(map1.Map2D[focus_horizontal-1][focus_vertical+j]){
21 case 0:
22
23 break;
24 case 1:
25 al_draw_bitmap(grass, -TILE-offset_horizontal, (SCREEN_H-TILE)-j*TILE, 0);
26 break;
27 default:
28 break;
29 };
30 }
31 }
32 //draw the tiles at the right of the screen
33 if(focus_horizontal<map1.getWidth()-1-(SCREEN_W/TILE)){
34 for(int j = 0; j < 10;j++){
35 switch(map1.Map2D[focus_horizontal+(SCREEN_W/TILE)][focus_vertical+j]){
36 case 0:
37
38 break;
39 case 1:
40 al_draw_bitmap(grass, SCREEN_W-offset_horizontal, (SCREEN_H-TILE)-j*TILE, 0);
41 break;
42 default:
43 break;
44 };
45 }
46 }
This is the first time I used Tilemaps and I kinda made that stuff up myself, so |
Audric
Member #907
January 2001
|
How frequent is your timer "timer" ? |
Xenowar
Member #12,630
March 2011
|
60 times a second. |
pkrcel
Member #14,001
February 2012
|
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? It is unlikely that Google shares your distaste for capitalism. - Derezo |
Xenowar
Member #12,630
March 2011
|
The test map is a 30 x 8 two dimenstional array, which will later on differ with |
Kris Asick
Member #1,424
July 2001
|
What's the code for map1.getWidth()? --- Kris Asick (Gemini) |
Xenowar
Member #12,630
March 2011
|
It returns the horizontal length of the 2D array, which in this case would be 30. |
Edgar Reynaldo
Major Reynaldo
May 2007
|
A few questions : Advice : 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. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
l j
Member #10,584
January 2009
|
Edgar Reynaldo said: It mirrors the arrangement in memory usually Which ought to improve caching, so that should increase performance too.
|
Xenowar
Member #12,630
March 2011
|
1) What are focus_horizontal and vertical for? 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? 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'll try to do that with al_hold_bitmap_drawing. So if I have a row which looks 111000011111144444 where each number represents a differen image, should I set al_hold_bitmap_drawing |
pkrcel
Member #14,001
February 2012
|
You shold defer bitmap drawing when drawing: - the same bitmap over and over ...which by the way seems something common when using tilesets It is unlikely that Google shares your distaste for capitalism. - Derezo |
Edgar Reynaldo
Major Reynaldo
May 2007
|
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. 1
2#include <allegro5/allegro.h>
3#include <vector>
4#include <map>
5
6std::vector< std::vector<int> > tilemap;// 2D array of integers representing tiles
7std::map<int , ALLEGRO_BITMAP*> int_to_image_map;// mapping of integers in tilemap to images
8
9// Basic setup
10int camx = 0;
11int camy = 0;
12const int scrw = 800;
13const int scrh = 600;
14const int tilew = 24;
15const int tileh = 32;
16
17// To be determined during loading of map...
18int mapntileswide = 0;
19int mapntilestall = 0;
20int worldw = 0;
21int worldh = 0;
22
23
24
25// repositions camera, centering on new coords and adjusting for out of bounds
26void SetCamera(int centerx , int centery) {
27 camx = centerx - scrw/2;
28 camy = centery - scrh/2;
29 if (camx < 0) {camx = 0;}
30 if (camy < 0) {camy = 0;}
31 if (camx > worldw - scrw) {camx = worldw - scrw;}
32 if (camy > worldh - scrh) {camy = worldh - scrh;}
33}
34
35
36// draws our map
37void DrawMap() {
38
39
40 int tilexstart = camx/tilew;
41 int tileystart = camy/tileh;
42 int tilexstop = (camx + scrw)/tilew;
43 int tileystop = (camy + scrh)/tileh;
44
45 /// asserts about 'tilemap's size should go here, or verify elsewhere
46
47 // if all our tiles are sub bitmaps of the same parent, we can use al_hold_bitmap_drawing
48 al_hold_bitmap_drawing(true);// cache drawing ops
49
50 // draw visible tiles
51 for (unsigned int row = tileystart ; row <= tileystop ; ++row) {
52 for (unsigned int col = tilexstart ; col <= tilexstop ; ++col) {
53 al_draw_bitmap(int_to_image_map[tilemap[y][x]] , row*tileh - camy , col*tilew - camx , 0);
54 }
55 }
56
57 al_hold_bitmap_drawing(false);// send it off to the gpu
58
59}
My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
|