Trouble getting a stable framerate (C++/Allegro 4)

Started by
1 comment, last by Alpha_ProgDes 10 years, 7 months ago

I programmed a vertical shooter, but the frame keeps on jumping around from 30 fps to 190fps. It just leaves game so slow with a few seconds of smooth speed. How can I lock the framerate to one specific value? Heres some of my code


#include "warbirds.h"


//interrupt handeler
//Timer variables
volatile int counter;
volatile int ticks;
volatile int framerate;
volatile int resting;
volatile int rested;


//displays the stats
void displaystats()
{
	
	//display some status information
	textprintf_ex(buffer, font, 0, 410, WHITE, -1, "Life %d", health); 
	textprintf_ex(buffer, font, 0, 420, WHITE, -1, "Firing rate %d", firedelay);
	textprintf_ex(buffer, font, 0, 440, WHITE, -1, "Counter %d", counter);
	textprintf_ex(buffer, font, 0, 450, WHITE, -1, "Yoffset %d", yoffset);*/
	textprintf_ex(buffer, font, 0, 460, WHITE, -1, "Framerate %d", framerate); 

	//display score
	textprintf_ex(buffer, font, 22, 22, GRAY, -1, "SCORE: %d", score);
	textprintf_ex(buffer, font, 20, 20, RED, -1, "SCORE: %d", score);
}

//calculate framerate every second
void timer1()
{
	counter++;
	framerate = ticks;
	ticks = 0;
	rest(2);
}
END_OF_FUNCTION(timer1)


int main()
{
	int n;

	//Intialize the game
	initialize();

	//indetify variables used by interupt funtion
	LOCK_VARIABLE(counter);
	LOCK_VARIABLE(framerate);
	LOCK_VARIABLE(ticks);
	LOCK_FUNCTION(timer1);

	//create new interupt handler
	install_int(timer1, 1000);

	//Load in all the sprites 
	loadsprite();

    //Start the main game loop
	while(!key[KEY_ESC])
	{
		//check if the player is interacting with the controls
		checkinput();

		//draw/update the map to the buffer
		updatescroller();

		//update and draw the enemy and player
		updateplayer();
		updateenemyplanes();

		//draw and update the bullets 
		updatebullets();
		
		//draw and update the explosions
		updateexplosions();

		//draw and update bonuses and
		//apply its effects on players if it collideds
		updatebonuses();

		//display health
		displayprogress(health);

		//display the stats
		displaystats();

		//check if the game needs to end
		endgame(health, score);

		//blit the double buffer
		acquire_screen();
		blit(buffer, screen, 0, 0, 0, 0, SCREEN_W-1, SCREEN_H-1);
		release_screen();

		ticks++;
		firecount++;
	}

	//delete mappy level
	MapFreeMem();

	//delete bitmaps
	destroy_bitmap(buffer);
	destroy_bitmap(progress);
	destroy_bitmap(bar);

	for(n = 0; n < 6; n++)
	{
		destroy_bitmap(explosion_images[n]);
	}
	for(n = 0; n < 3; n++)
	{
		destroy_bitmap(player_images[n]);
		//destroy_bitmap(bullet_images[n]);
		destroy_bitmap(enemy_plane_images[n]);
	}

	//delete the sprite pointers
	delete player;
	for(n = 0; n < MAX_EXPLOSIONS; n++)
	{
		delete explosions[n];
	}
	for(n = 0; n < MAX_BULLETS; n++)
	{
		delete bullets[n];
	}
	for(n = 0; n < MAX_ENEMIES; n++)
	{
		delete enemy_planes[n];
	}


	allegro_exit();
	return 0;

}
END_OF_MAIN()

Ive been playing around with the interrupt handler but its not changing much. How do I tackle this problem?

Advertisement

limit your speed to a sliding window:

1. Keep a sliding window (queue) of your last 50 frames' times (or any other number)

2. If your current frame is too far ahead of it's time: You want 50 FPS, but a second has not passed since the last 50 frames, then sleep a little bit.

3. You will also want to check the last 2 frames, to set an upper bound for speed: It is ok for the game to accelerate to compensate for missed frames, but there should be a limit on the maximum rate. If you do not do this, and you have some long frames, then your game will jitter.

Regardless of these points, you should separate your logic code from your render code. Your logic should never fall behind as a result of frame drawing speed. If you use a single thread it should look something like this.


while(true){
   bool wasUpdated=false;
   int targetLogicTime=CalculateTimeFromSlidingWindowAsMentionedAbove();
   while(currentTime()>targetLogicTime){
       //calculate logic:
       calculateStuff();//put all your logic code here
       wasUpdated=true;
       //limit and stabalize your FPS:
       UpdateSlidingWindowAsMentionedAbove(currentTime());
       targetLogicTime=CalculateTimeFromSlidingWindowAsMentionedAbove();
   }
   if(wasUpdated){
     drawStuff();//Draw everything here
   }else{
       sleep(1ms);//give the CPU time to rest to avoid busy waiting.
   }
}

Basically, this loop makes sure:

1. Your frame rate doesn't explode

2. If your drawing rate goes down, your game rate stays the same (car still takes 60 seconds to drive from A to B regardless of frame rate)

3. You don't draw redundant frames (frames where nothing has changed)

4. If available, you give the CPU some time to rest. (Very important for desktop CPU temperature, and laptop/phone battery life).

You can get better performance if you do this on two threads, but that's a whole other story.

My Oculus Rift Game: RaiderV

My Android VR games: Time-Rider& Dozer Driver

My browser game: Vitrage - A game of stained glass

My android games : Enemies of the Crown & Killer Bees

I have one question that's tangential to what you're doing. Why aren't you using Allegro 5?

Beginner in Game Development?  Read here. And read here.

 

This topic is closed to new replies.

Advertisement