I’ve just started codeing a SDL game engine for a RTS game. But The frame
rate sucks. I want to use Isometric tiles in my RTS, my test engine give me
8fps when i blit about 450 objects to the screen. Im running RedHat 7.3 on
a 800mhz 128 mb RAM and a nvida graphiccard. My code isn’t special and I
don’t draw any objects ouside the screen. If anyone like to test compile my
code send a private e-mail to me (perrascout at linux.nu) and I’ll share the
complete source code and grahics.
My goal is o create a rts that can run on a PII 300Mhz or slower if
possible.
A smilar code i M$ Visual Basic and DirectX 7.0 give me at least 30fps with
500 object on the screen.
-------------------------- my code -----------------------------
/*I know the code is a mess of coments i swedish and english
*but the code is just created to test the framrate.
*/
#include <stdio.h>
#include <stdlib.h>
#include <SDL.h>
#include “CBmpFont.h”
//Functions
int SetFullscreenFlag(int flag, int width, int height, int depth, char
*name, char *icon);
int InitImages(); //Load all images thats we might need
void DrawScene(); //Main routine to call DrawIMG
void DrawIMG(SDL_Surface *img, int x, int y); //a primitive DrawIMG funct
void DrawIMG(SDL_Surface *img, int SpriteNr, int x, int y, int w, int h);
int frames; //store fps
int gTimeLastSecond; //handy helper for timer.
char strFPS[255];
void createmap();
//Some global stuff
SDL_Surface *screen; //The visable surface
SDL_Surface *back; //a surface to store the back img loaded in InitImage
SDL_Surface *sprite; //same as back…
SDL_Surface *meny;
//N?gra globala variabler att sno.
int gTileWidth; //Pixel
int gTileHeight;//Pixel
int gMapWidth=128; //Rutor
int gMapHeight=128; //Rutor
int gGameWindowWidth; //Rutor
int gGameWindowHeight; //Rutor
int gScreenWidth=800;
int gScreenHeight=600;
int scrollspeed=40; //scroll speeden b?r vara halva tile bredden
unsigned long offsetX;
unsigned long offsety;
class CTile
{
public:
//givetvis s? f?r dessa inte vara publika senare
int tilenr;
int posx;
int posy;
};
CTile gTile[128][128];
CTile gTrees[128][128]; //lager 2
CBmpFont akbar;
//////////////////////////////////////////////////////////////////////////
//class CScreenData contains all useful data about the screen
//
class CScreenData
{
public:
CScreenData(); //constructor
~CScreenData(); //destructor
char *Name; //Project name - shown in windows mode
char *Icon; //Project Icon - shown in windows mode
int ScreenWidth;
int ScreenHeight;
int ScreenBpp;
int Fullscreen; //fullscreen flag (0= fullscreen)
private:
//no private stuff yet
};
CScreenData::CScreenData()
{
//the constructor assing the value to the CScreenData
Name = “No Use For A Name”;
Icon = NULL; //if Icon = NULL: SDL standard icon will be used
ScreenWidth = gScreenWidth;
ScreenHeight = gScreenHeight;
ScreenBpp = 16;
Fullscreen = 0; // 0 set the Fullscreen flag to full screen
}
CScreenData::~CScreenData()
{
}
/////////////////////////////////////////////////////////////////////////
//
//
int main(int argc, char argv[])
{
Uint8 keys; //anv?nd f?r tagent bordet senare…
CScreenData mySetings; //create mySetings
InitImages();
createmap();
akbar.create(“akbar512”, 512);
//init video (add sound if wanted)
if(SDL_Init(SDL_INIT_VIDEO)<0)
{
printf(“Unable to init SDL: %s\n”, SDL_GetError());
}
atexit(SDL_Quit);
//seting screen res
SetFullscreenFlag(mySetings.Fullscreen, mySetings.ScreenWidth,
mySetings.ScreenHeight,mySetings.ScreenBpp,
mySetings.Name, mySetings.Icon);
//check if the user want to quit
int done = 0;
while(done == 0)
{
SDL_Event event;
while(SDL_PollEvent(&event))
{
if(event.type == SDL_QUIT) {done =1;}
if(event.type == SDL_KEYDOWN)
{
if(event.key.keysym.sym == SDLK_ESCAPE){done = 1;}
}
}
/*
Scrollen flyttar “sk?rmen” och inte kartan.
*/
keys = SDL_GetKeyState(NULL);
if(keys[SDLK_RIGHT])
{
for(int y=0; y<gMapHeight; y++)
{
for(int x=0; x<gMapWidth; x++)
{
gTile[y][x].posx-=scrollspeed;
gTrees[y][x].posx-=scrollspeed;
}
}
}
if(keys[SDLK_LEFT])
{
for(int y=0; y<gMapHeight; y++)
{
for(int x=0; x<gMapWidth; x++)
{
gTile[y][x].posx+=scrollspeed;
gTrees[y][x].posx+=scrollspeed;
}
}
}
if(keys[SDLK_DOWN])
{
for(int y=0; y<gMapHeight; y++)
{
for(int x=0; x<gMapWidth; x++)
{
gTile[y][x].posy-=scrollspeed;
gTrees[y][x].posy-=scrollspeed;
}
}
}
if(keys[SDLK_UP])
{
for(int y=0; y<gMapHeight; y++)
{
for(int x=0; x<gMapWidth; x++)
{
gTile[y][x].posy+=scrollspeed;
gTrees[y][x].posy+=scrollspeed;
}
}
}
DrawScene();
}
return 0;
}
/////////////////////////////////////////////////////////////////////////
// Function InitImage() load all graphics into desired surfaces
// Function DrawScene() calls DrawIMG in order to draw a sprite on screen
// Functions DrawIMG() is overlayed to fit
void DrawScene()
{
SDL_FillRect(screen, NULL, 0x000000);
//DrawIMG(back,0,0); //draw the background image
for(int y=0; y<gMapHeight; y++)
{
for(int x=0; x<gMapWidth; x++)
{
if(((gTile[y][x].posx>-80) && (gTile[y][x].posx < (gScreenWidth-170)))&&
((gTile[y][x].posy >-80) && (gTile[y][x].posy<gScreenHeight)))
{
DrawIMG(sprite,gTile[y][x].tilenr,gTile[y][x].posx,gTile[y][x].posy,80,80);
//lite fusk…
if(gTrees[y][x].tilenr>0){DrawIMG(back,gTrees[y][x].tilenr,gTrees[y][x].posx,gTrees[y][x].posy,80,80);}
}
}
}
//Calculate fps:
if( gTimeLastSecond + 1000 <= SDL_GetTicks() )
{
gTimeLastSecond=SDL_GetTicks();
sprintf(strFPS,“FPS: %i”, frames);
frames=0;
}
DrawIMG(meny,640,0);
//Prints FPS:
akbar.drawString(screen,2,5,strFPS);
SDL_Flip(screen); //flip backbuf
frames+=1;
}
int InitImages()
{
//write the rutine to load images here as shown
//define SDL_Surfacesd as Global in the beginig of the .cpp file
back = SDL_LoadBMP(“tr?d.bmp”);
sprite = SDL_LoadBMP(“mark_tiles.bmp”);
meny = SDL_LoadBMP(“meny.bmp”);
//error handleing, edit to fit your needs
if(back == NULL){printf(“could not load tr?d.bmp\n”);}
if(sprite == NULL){printf(“could not load sprites.bmp\n”);}
if(meny == NULL){printf(“could not load meny.bmp\n”);}
if(sprite != NULL){SDL_SetColorKey(sprite,SDL_SRCCOLORKEY,
SDL_MapRGB(sprite->format, 255,0,255));}
if(back != NULL){SDL_SetColorKey(back,SDL_SRCCOLORKEY,
SDL_MapRGB(back->format, 255,0,255));}
return 0;
}
void DrawIMG(SDL_Surface *img, int x, int y)
{
SDL_Rect dest;
dest.x = x;
dest.y= y;
SDL_BlitSurface(img, NULL, screen, &dest);
}
void DrawIMG(SDL_Surface *img, int SpriteNr, int x, int y, int w, int h)
{
SDL_Rect dest;
dest.x = x;
dest.y = y;
SDL_Rect scrImg;
scrImg.x= w*SpriteNr;
scrImg.y= 0;
scrImg.w= w;
scrImg.h= h;
SDL_BlitSurface(img ,&scrImg , screen, &dest);
}
/////////////////////////////////////////////////////////////////////////
// Function SetFullscreenFlag() handle the the screen res, it’s might
// be changed at runtime.
int SetFullscreenFlag(int flag, int width, int height, int depth, char
*name, char *icon)
{
if(flag == 0) //set to fullscreen
{
screen =
SDL_SetVideoMode(width,height,depth,SDL_FULLSCREEN|SDL_HWSURFACE|SDL_DOUBLEBUF);
if(screen == NULL)
{
printf(“Unable to set requested screen res: %s\n”,
SDL_GetError());
}
}
if(flag == 1) //set to window mode
{
screen = SDL_SetVideoMode(width,height,depth,SDL_HWSURFACE|SDL_DOUBLEBUF);
if(screen == NULL)
{
printf(“Unable to set requested screen res: %s\n”,
SDL_GetError());
};
SDL_WM_SetCaption(name, icon);
}
return 0;
}
int ett_tal;
void createmap()
{
for(int y=0; y < gMapHeight; y++)
{
for(int x=0; x < gMapWidth; x++)
{
ett_tal=(int)((100.0)*rand()/RAND_MAX);
if(ett_tal < 50){gTile[y][x].tilenr=0;}
if((ett_tal > 49)&&(ett_tal <
95)){gTile[y][x].tilenr=(int)((7.0)*rand()/RAND_MAX)+1;}
//(int)((7.0)*rand()/RAND_MAX)+1
if(ett_tal>94){gTile[y][x].tilenr=(int)((2.0)*rand()/RAND_MAX)+8;}
//gTile[y][x].tilenr=ett_tal;
//mer fusk
ett_tal=(int)((100.0)*rand()/RAND_MAX);
if(ett_tal < 50){gTrees[y][x].tilenr=0;}
if((ett_tal > 49)&&(ett_tal <
95)){gTrees[y][x].tilenr=(int)((7.0)*rand()/RAND_MAX)+1;}
//(int)((7.0)*rand()/RAND_MAX)+1
if(ett_tal>94){gTrees[y][x].tilenr=(int)((2.0)*rand()/RAND_MAX)+8;}
//80=tilebredd(och h?jd) 40 = HALVA tilebredden(h?jden) 20 = 1/4 av tile
BREDD(h?jd)
//y MOD 2 ?r 1 n?r talet ?r udda, detta ?r s? h?rdk?dat att man vill
gr?ta.
if(y%2==1){gTile[y][x].posx=(80x)+40; gTile[y][x].posy=(20y)-40;}
else{gTile[y][x].posx=(80x); gTile[y][x].posy=(20y)-40;}
if(y%2==1){gTrees[y][x].posx=(80x)+40; gTrees[y][x].posy=(20y)-40;}
else{gTrees[y][x].posx=(80x); gTrees[y][x].posy=(20y)-40;}
/*
if(y%2==1){DrawIMG(sprite,gTile[y][x].tilenr,(80x)+40,(20y),80,80);}
else{DrawIMG(sprite,gTile[y][x].tilenr,(80x),(20y),80,80);}
*/
}
}
}