![]() |
|
Optimizing Draw Functions |
Gatleos
Member #12,534
January 2011
|
So. My ascii library's draw functions are EVIL CPU-SUCKERS. There are two parts: a Draw_Char function that doesn't draw anything to the screen but updates the symbol at a certain location, and Win_Draw, which updates the given Window by redrawing every character in it. Obviously running them every time the game loops isn't the best idea, but does anyone have any tips on how to best optimize these things to prevent lag? Draw_Char: void Draw_Char(int code,Window& window,int x,int y) { if(x<window.mw && x>=0 && y>=0 && y<window.mh) { window.oldtile[x][y]=window.tile[x][y]; window.tile[x][y].symbol=code; window.tile[x][y].color="white"; window.tile[x][y].backcolor="black"; } } Win_Draw: 1void Win_Draw(Window& windowsource)
2{
3for(int j=0;j<=windowsource.h;++j)
4for(int i=0;i<=windowsource.w;++i)
5{
6ALLEGRO_COLOR color=al_map_rgba(0,0,0,0);
7if(strcmp(windowsource.tile[i][j].color,"black")==0)
8color=al_map_rgba(0,0,0,255);
9else if(strcmp(windowsource.tile[i][j].color,"lightgrey")==0)
10color=al_map_rgba(192,192,192,255);
11else if(strcmp(windowsource.tile[i][j].color,"blue")==0)
12color=al_map_rgba(0,0,128,255);
13else if(strcmp(windowsource.tile[i][j].color,"green")==0)
14color=al_map_rgba(0,128,0,255);
15else if(strcmp(windowsource.tile[i][j].color,"cyan")==0)
16color=al_map_rgba(0,128,128,255);
17else if(strcmp(windowsource.tile[i][j].color,"red")==0)
18color=al_map_rgba(128,0,0,255);
19else if(strcmp(windowsource.tile[i][j].color,"magenta")==0)
20color=al_map_rgba(128,0,128,255);
21else if(strcmp(windowsource.tile[i][j].color,"brown")==0)
22color=al_map_rgba(128,128,0,255);
23else if(strcmp(windowsource.tile[i][j].color,"darkgrey")==0)
24color=al_map_rgba(128,128,128,255);
25else if(strcmp(windowsource.tile[i][j].color,"lightblue")==0)
26color=al_map_rgba(0,0,255,255);
27else if(strcmp(windowsource.tile[i][j].color,"lightgreen")==0)
28color=al_map_rgba(0,255,0,255);
29else if(strcmp(windowsource.tile[i][j].color,"lightcyan")==0)
30color=al_map_rgba(0,255,255,255);
31else if(strcmp(windowsource.tile[i][j].color,"lightred")==0)
32color=al_map_rgba(255,0,0,255);
33else if(strcmp(windowsource.tile[i][j].color,"lightmagenta")==0)
34color=al_map_rgba(255,0,255,255);
35else if(strcmp(windowsource.tile[i][j].color,"yellow")==0)
36color=al_map_rgba(255,255,0,255);
37else if(strcmp(windowsource.tile[i][j].color,"white")==0)
38color=al_map_rgba(255,255,255,255);
39ALLEGRO_COLOR backcolor=al_map_rgba(0,0,0,0);
40if(strcmp(windowsource.tile[i][j].backcolor,"black")==0)
41backcolor=al_map_rgba(0,0,0,255);
42else if(strcmp(windowsource.tile[i][j].backcolor,"lightgrey")==0)
43backcolor=al_map_rgba(192,192,192,255);
44else if(strcmp(windowsource.tile[i][j].backcolor,"blue")==0)
45backcolor=al_map_rgba(0,0,128,255);
46else if(strcmp(windowsource.tile[i][j].backcolor,"green")==0)
47backcolor=al_map_rgba(0,128,0,255);
48else if(strcmp(windowsource.tile[i][j].backcolor,"cyan")==0)
49backcolor=al_map_rgba(0,128,128,255);
50else if(strcmp(windowsource.tile[i][j].backcolor,"red")==0)
51backcolor=al_map_rgba(128,0,0,255);
52else if(strcmp(windowsource.tile[i][j].backcolor,"magenta")==0)
53backcolor=al_map_rgba(128,0,128,255);
54else if(strcmp(windowsource.tile[i][j].backcolor,"brown")==0)
55backcolor=al_map_rgba(128,128,0,255);
56else if(strcmp(windowsource.tile[i][j].backcolor,"darkgrey")==0)
57backcolor=al_map_rgba(128,128,128,255);
58else if(strcmp(windowsource.tile[i][j].backcolor,"lightblue")==0)
59backcolor=al_map_rgba(0,0,255,255);
60else if(strcmp(windowsource.tile[i][j].backcolor,"lightgreen")==0)
61backcolor=al_map_rgba(0,255,0,255);
62else if(strcmp(windowsource.tile[i][j].backcolor,"lightcyan")==0)
63backcolor=al_map_rgba(0,255,255,255);
64else if(strcmp(windowsource.tile[i][j].backcolor,"lightred")==0)
65backcolor=al_map_rgba(255,0,0,255);
66else if(strcmp(windowsource.tile[i][j].backcolor,"lightmagenta")==0)
67backcolor=al_map_rgba(255,0,255,255);
68else if(strcmp(windowsource.tile[i][j].backcolor,"yellow")==0)
69backcolor=al_map_rgba(255,255,0,255);
70else if(strcmp(windowsource.tile[i][j].backcolor,"white")==0)
71backcolor=al_map_rgba(255,255,255,255);
72
73int code=windowsource.tile[i][j].symbol;
74if(code<0 || code>255)
75code=63;
76int backcode=219;
77int row = code / colnum;
78int backrow = backcode / colnum;
79while(code>=colnum)
80code-=colnum;
81while(backcode>=colnum)
82backcode-=colnum;
83if(i<windowsource.w && j<windowsource.h)
84{
85al_draw_tinted_bitmap_region(ascii, backcolor, tilewidth*backcode, tileheight*backrow, tilewidth, tileheight, (tilewidth*i)+(tilewidth*windowsource.x), (tileheight*j)+(tileheight*windowsource.y), 0);
86al_draw_tinted_bitmap_region(ascii, color, tilewidth*code, tileheight*row, tilewidth, tileheight, (tilewidth*i)+(tilewidth*windowsource.x), (tileheight*j)+(tileheight*windowsource.y), 0);
87}
88}
89}
|
Mark Oates
Member #1,146
March 2001
![]() |
al_color_name(); will help clean up your code, at least. -- |
Gatleos
Member #12,534
January 2011
|
The problem is that the ALLEGRO_COLOR names aren't the same as traditional ASCII colors. I'll try to see what I can do with it, though.
|
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
What's with all the strcmp's in Win_Draw? Make a color map : ColorMap.hpp #include <map> #include <string> extern std::map<std::string , ALLEGRO_COLOR> color_map; void InitializeColorMap(); ColorMap.cpp using std::map; using std::string; map<string , ALLEGRO_COLOR> color_map; void InitializeColorMap() { color_map.clear(); color_map["black"] = al_map_rgba(0,0,0,255); color_map["lightgrey"] = al_map_rgba(192,192,192,255); // repeat for all of your named colors } Win_Draw.cpp 1#include "ColorMap.hpp"
2
3void Win_Draw(Window& windowsource)
4{
5for(int j=0;j<=windowsource.h;++j)
6for(int i=0;i<=windowsource.w;++i)
7{
8const char* wcolor = windowsource.tile[i][j].color;
9const char* wbcolor = windowsource.tile[i][j].backcolor;
10ALLEGRO_COLOR color=al_map_rgba(0,0,0,0);
11if (color_map.find(wcolor) != color_map.end()) {
12 color = color_map[wcolor];
13}
14ALLEGRO_COLOR backcolor=al_map_rgba(0,0,0,0);
15if (color_map.find(wbcolor) != color_map.end()) {
16 color = color_map[wbcolor];
17}
18
19
20
21int code=windowsource.tile[i][j].symbol;
22if(code<0 || code>255)
23code=63;
24int backcode=219;
25int row = code / colnum;
26int backrow = backcode / colnum;
27while(code>=colnum)
28code-=colnum;
29while(backcode>=colnum)
30backcode-=colnum;
31if(i<windowsource.w && j<windowsource.h)
32{
33al_draw_tinted_bitmap_region(ascii, backcolor, tilewidth*backcode, tileheight*backrow, tilewidth, tileheight, (tilewidth*i)+(tilewidth*windowsource.x), (tileheight*j)+(tileheight*windowsource.y), 0);
34al_draw_tinted_bitmap_region(ascii, color, tilewidth*code, tileheight*row, tilewidth, tileheight, (tilewidth*i)+(tilewidth*windowsource.x), (tileheight*j)+(tileheight*windowsource.y), 0);
35}
36}
37}
Other things - Why are you using al_draw_tinted_bitmap_region? Why not just use al_draw_filled_rectangle? And I don't see you actually draw the character anywhere. Using the std::map will at least give you a binary search, which should be decently faster than strcmp'ing every known color value every iteration of the loop. Also, why is tile one wider and one taller than window? 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 |
SiegeLord
Member #7,827
October 2006
![]() |
As Peter Wang said in the other thread, why not just use ALLEGRO_COLOR directly, instead of storing the color name? "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
Gatleos
Member #12,534
January 2011
|
I could not, for the life of me, get ALLEGRO_COLORs to work correctly. But using the code above, that doesn't really matter anymore. Edgar Reynaldo said: Why not just use al_draw_filled_rectangle? And I don't see you actually draw the character anywhere. I assume primitives are faster than drawing bitmap regions, then? The character is drawn by the second al_draw_tinted_bitmap_region in Win_Draw. Anyway, I think the code above helped a bit, but it's still using more CPU than it has any right to.
|
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
Gatleos said: I assume primitives are faster than drawing bitmap regions, then? Maybe, maybe not. But al_draw_filled_rectangle should be faster than using al_draw_tinted_bitmap_region, at least I would think so. How do your draw your characters background using al_draw_tinted_bitmap_region? And why are you tinting it? Don't you want just the colors from the background/foreground? Why not use al_draw_text for the character? Just use a char array[2] and set array[0] to your character and array[1] to '\0'. About the colors : just add an ALLEGRO_COLOR entry to your TILE class and when your users set the color using a color name, find the ALLEGRO_COLOR from your color map and use that. 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 |
Gatleos
Member #12,534
January 2011
|
Edgar Reynaldo said: Maybe, maybe not. But al_draw_filled_rectangle should be faster than using al_draw_tinted_bitmap_region, at least I would think so. How do your draw your characters background using al_draw_tinted_bitmap_region? And why are you tinting it? Don't you want just the colors from the background/foreground? Why not use al_draw_text for the character? Just use a char array[2] and set array[0] to your character and array[1] to '\0'. About the colors : just add an ALLEGRO_COLOR entry to your TILE class and when your users set the color using a color name, find the ALLEGRO_COLOR from your color map and use that.
The ascii table is in a bitmap like this one: Can al_draw_text use unicode characters, or just regular old keyboard characters?
|
SiegeLord
Member #7,827
October 2006
![]() |
Gatleos said: But using the code above, that doesn't really matter anymore. Yeah, it kind of does. std::map is still a lot slower than doing absolutely nothing would be. Here's how it'd look:
1void Win_Draw(Window& windowsource)
2{
4for(int j=0;j<=windowsource.h;++j)
5for(int i=0;i<=windowsource.w;++i)
6{
7ALLEGRO_COLOR color = tile[i][j].color;
8ALLEGRO_COLOR backcolor = tile[i][j].backcolor;
9
10int code=windowsource.tile[i][j].symbol;
11if(code<0 || code>255)
12code=63;
13int backcode=219;
14int row = code / colnum;
15int backrow = backcode / colnum;
16while(code>=colnum)
17code-=colnum;
18while(backcode>=colnum)
19backcode-=colnum;
20if(i<windowsource.w && j<windowsource.h)
21{
22al_draw_tinted_bitmap_region(ascii, backcolor, tilewidth*backcode, tileheight*backrow, tilewidth, tileheight, (tilewidth*i)+(tilewidth*windowsource.x), (tileheight*j)+(tileheight*windowsource.y), 0);
23al_draw_tinted_bitmap_region(ascii, color, tilewidth*code, tileheight*row, tilewidth, tileheight, (tilewidth*i)+(tilewidth*windowsource.x), (tileheight*j)+(tileheight*windowsource.y), 0);
24}
25}
27}
EDIT: nvm EDIT2: Also, try adding al_hold_bitmap_drawing like I did above (highlighted). "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
Nazerith
Member #12,551
February 2011
|
How are are changes occurring on the screen? Are all the ascii constantly changing (like an ascii video player), or only changing periodically? If the ascii isn't changing every time you draw the screen, you could store a copy to use when you refresh, so you are not needlessly going through this loop to produce the same results. |
|