Allegro.cc - Online Community

Allegro.cc Forums » Game Design & Concepts » Increase FPS for a parallax platform game with 9 background levels

Credits go to Frank Drebin and Neil Walker for helping out!
This thread is locked; no one can reply to it. rss feed Print
Increase FPS for a parallax platform game with 9 background levels
Kevin Epps
Member #5,856
May 2005
avatar

I've been reading just about every thread for about 3 hours trying to figure out a way to improve my FPS for my ATI Rage Pro 28 card. It works fine for my Radeon x300. Does ANYONE have any suggestions? The FPS is 20 on the Rage and around 60 on the Radeon.

Here's the game loop code:

1//main loop
2 while (!key[KEY_ESC])
3 {
4 while(speed_counter > 0)
5 {
6
7 sprintf(buf, "Current Frame: %d, Current Action: %d, FPS: %d", player.curframe, player.action, speed_counter);
8 player.do_action();
9 player.key_presser();
10 player.scroll();
11 if((player.scroll_left) && (player.mapxoff < (mapwidth * mapblockwidth - WIDTH)) && (player.mapxoff > 0))
12 {
13 if(player.is_state(STATE_RUNNING))
14 {
15 bg_x-=player.x_vel + 3 + 1;
16 foreground_x-=player.x_vel + 2;
17 grass_x[3]-=player.x_vel + 1;
18 grass_x[0]-=player.x_vel;
19 grass_x[1]-=player.x_vel - 1 - 1;
20 grass_x[2]-=player.x_vel - 2 - 1;
21 front_x-=player.x_vel - 3 - 2;
22 }
23 else
24 { bg_x-=player.x_vel + 3;
25 foreground_x-=player.x_vel + 2;
26 grass_x[3]-=player.x_vel + 1;
27 grass_x[0]-=player.x_vel;
28 grass_x[1]-=player.x_vel - 1;
29 grass_x[2]-=player.x_vel - 2;
30 front_x-=player.x_vel - 3;
31 }
32 }
33 if((player.scroll_right) && (player.mapxoff > 0) && (player.mapxoff < (mapwidth * mapblockwidth - WIDTH)))
34 {
35 if(player.is_state(STATE_RUNNING))
36 {
37 bg_x-=player.x_vel - 3 - 1;
38 foreground_x-=player.x_vel - 2;
39 grass_x[3]-=player.x_vel - 1;
40 grass_x[0]-=player.x_vel;
41 grass_x[1]-=player.x_vel + 1 + 1;
42 grass_x[2]-=player.x_vel + 2 + 1;
43 front_x-=player.x_vel + 3 + 2;
44 }
45 else
46 {
47 bg_x-=player.x_vel - 3;
48 foreground_x-=player.x_vel - 2;
49 grass_x[3]-=player.x_vel - 1;
50 grass_x[0]-=player.x_vel;
51 grass_x[1]-=player.x_vel + 1;
52 grass_x[2]-=player.x_vel + 2;
53 front_x-=player.x_vel + 3;
54 }
55 }
56 if(player.x < 5)
57 {
58 player.x = 5;
59 }
60 if(player.x > 6340)
61 {
62 player.x = 6340;
63 }
64 
65 speed_counter--;
66 }
67 //This is the closing bracket for the (speed_counter > 0) test
68 draw_sprite(buffer, bg, bg_x, 0);
69 draw_sprite(buffer, foreground, foreground_x, 0);
70 masked_blit(foreground, buffer, 0, 0, foreground_x + foreground->w, 0, foreground->w, foreground->h);
71 masked_blit(foreground, buffer, 0, 0, foreground_x + foreground->w + foreground->w, 0, foreground->w, foreground->h);
72 masked_blit(grass[3], buffer, 0, 0, grass_x[3], 335, grass[3]->w, grass[3]->h);
73 masked_blit(grass[0], buffer, 0, 0, grass_x[0], 355, grass[0]->w, grass[0]->h);
74 masked_blit(grass[3], buffer, 0, 0, grass_x[3] + grass[3]->w, 335, grass[3]->w, grass[3]->h);
75 masked_blit(grass[0], buffer, 0, 0, grass_x[0] + grass[0]->w, 355, grass[0]->w, grass[0]->h);
76 masked_blit(grass[0], buffer, 0, 0, grass_x[0] + grass[0]->w + grass[0]->w, 355, grass[0]->w, grass[0]->h);
77 //draw the background tiles
78 MapDrawBGT(buffer, player.mapxoff, player.mapyoff, 0, 0, WIDTH-1, HEIGHT-1);
79 //draw foreground tiles
80 MapDrawFG(buffer, player.mapxoff, player.mapyoff, 0, 0, WIDTH-1, HEIGHT-1, 0);
81 masked_blit(grass[0], buffer, 0, 0, grass_x[0], 419, grass[0]->w, grass[0]->h);
82 masked_blit(grass[1], buffer, 0, 0, grass_x[1], 429, grass[1]->w, grass[1]->h);
83 masked_blit(grass[2], buffer, 0, 0, grass_x[2], 439, grass[2]->w, grass[2]->h);
84 masked_blit(grass[0], buffer, 0, 0, grass_x[0] + grass[0]->w, 419, grass[0]->w, grass[0]->h);
85 masked_blit(grass[0], buffer, 0, 0, grass_x[0] + grass[0]->w + grass[0]->w, 419, grass[0]->w, grass[0]->h);
86 masked_blit(grass[1], buffer, 0, 0, grass_x[1] + grass[1]->w, 429, grass[1]->w, grass[1]->h);
87 masked_blit(grass[1], buffer, 0, 0, grass_x[1] + grass[1]->w + grass[1]->w, 429, grass[1]->w, grass[1]->h);
88 masked_blit(grass[2], buffer, 0, 0, grass_x[2] + grass[2]->w, 439, grass[2]->w, grass[2]->h);
89 masked_blit(grass[2], buffer, 0, 0, grass_x[2] + grass[2]->w + grass[2]->w, 439, grass[2]->w, grass[2]->h);
90 masked_blit(grass[2], buffer, 0, 0, grass_x[2] + grass[2]->w + grass[2]->w + grass[2]->w, 439, grass[2]->w, grass[2]->h);
91 player.draw(buffer);
92 masked_blit(front_trees, buffer, 0, 0, front_x, 0, front_trees->w, front_trees->h);
93 masked_blit(front_trees, buffer, 0, 0, front_x + front_trees->w, 0, front_trees->w, front_trees->h);
94 masked_blit(front_trees, buffer, 0, 0, front_x + front_trees->w + front_trees->w, 0, front_trees->w, front_trees->h);
95 masked_blit(front_trees, buffer, 0, 0, front_x + front_trees->w + front_trees->w + front_trees->w, 0, front_trees->w, front_trees->h);
96 masked_blit(front_trees, buffer, 0, 0, front_x + front_trees->w + front_trees->w + front_trees->w + front_trees->w, 0, front_trees->w, front_trees->h);
97 textprintf_ex(buffer, font, 200, 100, makecol(255,255,255), -1, buf);
98 
99 textout(buffer, font, fps, 100, 200, makecol(255,255,255));
100 vsync();
101 acquire_screen();
102 blit(buffer, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);
103 release_screen();
104 FpsTimer ++;
105 while(speed_counter == 0){rest(1);}
106 } //while

I know it's pretty long. I also have a question on how I coded the blitting of the background layers. The images are small but I have them blitted in a repeating pattern. Is that the right way if I want this to run effectively?

Frank Drebin
Member #2,987
December 2002
avatar

for me programs run well without using vsync(), aquire_screen and release_screen but i don't know if that makes things slower...
btw: i think you know that you won't get more fps than your timer is with this code here:

while(speed_counter == 0){rest(1)};

Neil Walker
Member #210
April 2000
avatar

Have you tried using MapLoadVRAM?

Also, does your card support paging or triple buffering?

Also, your timer code seems wrong. If you are doing FPS limiting looping you should have two separate parts. One being logic that compensates for slowness and the second for pure drawing only when it needs it.

Neil.
MAME Cabinet Blog / AXL LIBRARY (a games framework) / AXL Documentation and Tutorial

wii:0356-1384-6687-2022, kart:3308-4806-6002. XBOX:chucklepie

Kevin Epps
Member #5,856
May 2005
avatar

Hey Neil,

MapLoadVRAM made my FPS even slower. Triple Buffering and Page Flipping is supported, and it's a really nice, smooth movement, but the fps is really slow.

As far as the timer code, I thought that's what I was doing. Having one place that controlled the logic and one place that controlled the drawing. Is that what I'm not doing? If not, what should be changed?

Hey Frank,

I was actually slower when I took the while call out.

Krzysztof Kluczek
Member #4,191
January 2004
avatar

Quote:

Does ANYONE have any suggestions?

Think about OpenGL/Direct3D if you'd like to achieve good frame rates. OpenLayer (add-on library for Allegro+AllegroGL) probably can help you in case of 2D games. :)

Neil Walker
Member #210
April 2000
avatar

Well VRAM would be slower if you are blitting this to a memory bitmap afterwards. I'm not an expert by any means, but I remember someone more clever than me saying VRAM->MEMORY was very slow.

So the moral is if you want to use paging/triple buffering which should increase speeds, you need to make sure you are doing it throughout.

Oddly enough, the third and final exciting part of my AXL projects (as below) is the framework and I've just incorporated a complete system for handling double/paged/triple buffering amongst other things without your code needing to worry about it.

Quote:

Think about OpenGL/Direct3D

He is using a third party tile map system that doesn't support opengl via allegro.

Neil.
MAME Cabinet Blog / AXL LIBRARY (a games framework) / AXL Documentation and Tutorial

wii:0356-1384-6687-2022, kart:3308-4806-6002. XBOX:chucklepie

Kevin Epps
Member #5,856
May 2005
avatar

Hey Neil,

I just downloaded what you have now and it's great so far! :) I get at least 40 FPS with the programs, which is a lot better than 20!

When do you plan on having the full framework done?

Neil Walker
Member #210
April 2000
avatar

It's almost done, just tracing a few bugs. It's pretty cool now. You set up exactly what you want allegro to do (graphics mode, triple/paged/double buffering, windowed/fullscreen, etc) via XML/constructors, it loads up all your animations and graphics and set you up in a nice allegro state. All you then need do is pass it the name of your functions that do logic/drawing and it sets up and runs a FPS based timer loop handing everything for you. You are given a bitmap pointer and you just use it as your drawing buffer and it is updated to the screen at the correct time, etc.

It also has some helper functions, for example instead of using the limited play_sample/stop_sample it wraps up the more in-depth voice control functions (e.g. voicestart/stop - to allow you to set voice priority instead of stopping playing sounds).

Neil.
MAME Cabinet Blog / AXL LIBRARY (a games framework) / AXL Documentation and Tutorial

wii:0356-1384-6687-2022, kart:3308-4806-6002. XBOX:chucklepie

Kevin Epps
Member #5,856
May 2005
avatar

Oh yeah!!

That's going to be awesome when you finish! :) Please do let me know when you do. Right now I'm using what you've already posted. :)

Maybe I'll just wait on that to be finished before I continue coding, then.

Neil Walker
Member #210
April 2000
avatar

I can gladly upload what is there if you want (it effectively works, but no documentation other than in the examples and anything other than double buffering crashes at the minute).

Neil.
MAME Cabinet Blog / AXL LIBRARY (a games framework) / AXL Documentation and Tutorial

wii:0356-1384-6687-2022, kart:3308-4806-6002. XBOX:chucklepie

Kevin Epps
Member #5,856
May 2005
avatar

That would be great! I'll be you test subject! ;)

Frank Drebin
Member #2,987
December 2002
avatar

Quote:

I was actually slower when I took the while call out.

this is strange.
this line waits after one frame is drawn until it is time to draw the next one (your logic timer has incremented).
that means if you have your timer set up to 50 BPS you'll never get more than 50 FPS though 1000000 could be drawn in this time!

Kevin Epps
Member #5,856
May 2005
avatar

Hey Guys,

I think I have the triple buffering to a point were it works fine for both systems. The FPS is at 60 for both cards at 16bpp. For 32bpp, on the radeon, it's still 60 FPS and on the Rage it's 30.

This is resulting from only having the tile map, player, and a big none moving background displaying.

So at least it's better. I'm going to start one more thread. That's the best possible action to coding parrallax scrolling. I don't think mine is completely write as I have the scroll based off of the character's speed instead of the main layer's xoffset.

Thanks for all of your help!! :)

Neil Walker
Member #210
April 2000
avatar

Well, remember when you use paging or triple buffering the maximum fps you will get is the refresh rate of your monitor as they wait for the vertical retrace. To avoid over or under loading your system, maybe a call to try and set_refresh_rate() might help? For double buffering if you combine this with vsync it might make things a lot more smooth.

Neil.
MAME Cabinet Blog / AXL LIBRARY (a games framework) / AXL Documentation and Tutorial

wii:0356-1384-6687-2022, kart:3308-4806-6002. XBOX:chucklepie

Tobias Dammers
Member #2,604
August 2002
avatar

Quote:

that means if you have your timer set up to 50 BPS you'll never get more than 50 FPS though 1000000 could be drawn in this time!

Why would you want to do that? Since the logic runs at 50 fps, there is absolutely no point in drawing more frames than that - you will just render the exact same scene over and over. Waste of cpu time, better play nice and release it to the OS (read: MSN, antivirus, whatever runs in the background). Drawing 1000000 frames per second gives you nothing but an impressive number displayed on screen. Heck, you hardware can't even display more frames per second than the physical retrace rate, so why bother?
If it's performance you're interested in, then there are better ways to measure that. Just clock the actual drawing time using a high-resolution timer.

---
Me make music: Triofobie
---
"We need Tobias and his awesome trombone, too." - Johan Halmén

axilmar
Member #1,204
April 2001

Dear Kevin,

in order to ensure a good frame rate in a bitmap-based game, you have to do the following (assuming bitmap blitting is the issue here):

1) ensure that you use a mode like triple-buffering or page-flipping that uses vram buffers.

2) ensure your most frequently used/large bitmaps are loaded in vram.

An effective way to do parallax scrolling with multiple layers is to avoid drawing blocks twice.

You need a flag for each block of each layer that tells you if the block has already been covered by one of the above layers. Then you need to do two passes over your layers:

a) the first pass will be from top layer to bottom in order to set the 'covered' flag;

b) the second pass will be from bottom to top layer to draw those blocks at each layer that have not been covered yet.

By carefully choosing block sizes (i.e. not too small, not too big) you can minimize overdraw and do many layers of scrolling (even more than 9!).

Frank Drebin
Member #2,987
December 2002
avatar

Quote:

Why would you want to do that?

cause he wants to get more FPS!

Go to: