I have a renderer which, with no game logic, no shaders, just blitting only lets me draw 1200 sprites per frame and retain 60 FPS, is this too slow?
How can I improve it?
The main idea stems from a previous thread about renderers and decoupling the rendering logic from the game logic. To that end, I created a renderInfo struct to contain the important sprite drawing information.
Each game loop, every object that wants to get drawn adds a renderInfo (or set of renderInfos if it is composed of multiple sprites) to the renderList.
As renderInfos are added they are sorted first by layer, then by yposition... (originally i also sorted by spriteSheet to draw all sprites from a particular spritesheet at the same time, but that could endup with a sprite from a lower y pos being drawn before one above b/c it shares a spritesheet with something even higher, although i suppose I could sort by spriteSheet after sorting by y, but I don't know how useful that would be)
The weird thing is that, if I scale down the sprite (original or at runtime), or if i change the size of the display... i still get the exact same performance.
Out of curiosity, approximatly how many sprites are generally drawn onto a screen? I realize that simpler games may have less, but what about say, a bullet hell game?
#pragma once
#include "allegro5\allegro.h"
#include "allegro5\allegro_primitives.h"
#include "boost\property_map\vector_property_map.hpp"
#include "boost\foreach.hpp"
#include <vector>
#include <map>
#include <cstdlib>
#include "AssocVector.h"
struct BOX
{
float X1;
float Y1;
float X2(){return X1+W;}
float Y2(){return Y1+H;}
float W;
float H;
};
struct renderInfo
{
ALLEGRO_BITMAP* SpriteSheet;
BOX SpriteBox;
BOX DrawBox;
ALLEGRO_COLOR Tint;
float Rotation;
int Layer;
};
class Renderer
{
private:
std::vector<renderInfo> renderList;
renderInfo ri;
ALLEGRO_COLOR bgClearClr;
public:
ALLEGRO_DISPLAY* display;
Renderer::Renderer(void){
display=al_get_current_display();
al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA);
al_init_primitives_addon();
bgClearClr=al_map_rgb(0,0,0);
}
Renderer::~Renderer(void){}
void Renderer::Add(ALLEGRO_BITMAP* spriteSheet, BOX spriteBox, BOX drawBox, float rot, ALLEGRO_COLOR tint, int Layer)
{
renderInfo r;
r.SpriteSheet=spriteSheet;
r.SpriteBox=spriteBox;
r.DrawBox=drawBox;
r.Rotation=rot;
r.Tint=tint;
r.Layer=Layer;
binaryInsert(r,0,renderList.size());
}
bool renderInfoCompare(renderInfo ri1,renderInfo ri2)
{
if (ri1.Layer!=ri2.Layer) return ri1.Layer<ri2.Layer;
//if((int)(ri1.SpriteSheet)!=(int)(ri2.SpriteSheet)) return (int)(ri1.SpriteSheet)<(int)(ri2.SpriteSheet);
if(ri1.DrawBox.Y1!=ri2.DrawBox.Y1) return ri1.DrawBox.Y1<ri2.DrawBox.Y1;
return false;
}
void binaryInsert(renderInfo ri,int low, int hi)
{
if (low==hi)
{
renderList.insert(renderList.begin()+low,ri);
return;
}
int indx=floor((low+hi)/2.0);
if (renderInfoCompare(ri,renderList[indx]))
return binaryInsert(ri,low,indx);
return binaryInsert(ri,indx+1,hi);
}
void Render()
{
al_clear_to_color(bgClearClr);
int dCount=0;
al_hold_bitmap_drawing(true);
for(std::vector<renderInfo>::iterator ri=renderList.begin();ri!=renderList.end();ri++)
{
dCount++;
renderInfo r= *ri;
al_draw_tinted_scaled_rotated_bitmap_region(r.SpriteSheet,
r.SpriteBox.X1,r.SpriteBox.Y1,r.SpriteBox.W,r.SpriteBox.H,
r.Tint,
r.SpriteBox.X1+r.SpriteBox.W/2.0,r.SpriteBox.Y1+r.SpriteBox.H/2.0,
r.DrawBox.X1,r.DrawBox.Y1,
r.DrawBox.W/r.SpriteBox.W, r.DrawBox.H/r.SpriteBox.H,
r.Rotation,0);
}
al_hold_bitmap_drawing(false);
renderList.clear();
printf("Draws: %i",dCount);
/*
for(int j=1;j<al_get_display_height(display);j+=10)
{
al_draw_line(0,j,al_get_display_width(display),j,al_map_rgb(255,0,0),1);
}
for(int i=1;i<al_get_display_width(display);i+=10)
{
al_draw_line(i,0,i,al_get_display_height(display),al_map_rgb(255,0,0),1);
}
*/
al_flip_display();
}
};