I'm still struggling with performance issues. If anyone has the time, please take a look at this example. I've pulled out the general structure of my render loop and made it work with the default 2d game wizard for MSVS 2008. With my setup I can just paste this into main.cpp and it will execute. It uses the media that is provided by the wizard; a 1024x1024 'background.bmp' and 512x512 'sprite.bmp'.
The idea is that with a 100x100 map of 32px tiles and a viewport of 800 x 600 I get about 12 fps with 2 layers of sprites. The demo allows you to change the viewport with 'w' and 's' and move the map around with arrows. If you shrink the viewport to 600x400 ish things speed up nicely.
Is there an issue in my loop or is this just the performance to expect from multiple layers of sprites?
#include "DarkGDK.h"
#define MAP_HEIGHT 100
#define MAP_WIDTH 100
class Tile
{
public:
int layer0spriteId;
int layer0imageId;
int layer1spriteId;
int layer1imageId;
};
Tile map[MAP_HEIGHT][MAP_WIDTH];
int FIRST_L0_IMG_ID = 100;
int LAST_L0_IMG_ID = 0;
int FIRST_L1_IMG_ID = 0;
int LAST_L1_IMG_ID = 0;
int FIRST_SPRITE_ID = 100;
int CAMERA_X = 400;
int CAMERA_Y = 300;
int VIEWSIZE_X = 800;
int VIEWSIZE_Y = 600;
int TILE_SIZE = 32;
void handleInput();
void load();
void DarkGDK()
{
dbSyncOn();
dbSyncRate(60);
dbSetDisplayMode(800,600,32);
dbDisableEscapeKey();
dbRandomize(dbTimer());
dbSetImageColorKey(255,0,255);
dbDrawSpritesFirst();
// Load bitmaps and create test map (tile array)
load();
char buf[1024];
while(LoopGDK())
{
if (dbEscapeKey()) break;
handleInput();
// Begin render loop
dbHideAllSprites();
int priority = 0;
for (int row = 0; row < MAP_HEIGHT; ++row)
{
for (int col = 0; col < MAP_WIDTH; ++col)
{
int x = TILE_SIZE * col - CAMERA_X;
int y = TILE_SIZE * row - CAMERA_Y;
if (x > 0 && y > 0 && x < VIEWSIZE_X && y < VIEWSIZE_Y)
{
if (col == 0)
{
// New row, bump up priority (depth order)
priority++;
}
dbSprite(map[row][col].layer0spriteId, x, y, map[row][col].layer0imageId);
dbSetSpritePriority(map[row][col].layer0spriteId, priority);
dbShowSprite(map[row][col].layer0spriteId);
if (map[row][col].layer1imageId != 0)
{
dbSprite(map[row][col].layer1spriteId, x, y, map[row][col].layer1imageId);
dbSetSpritePriority(map[row][col].layer1spriteId, priority+1);
dbShowSprite(map[row][col].layer1spriteId);
}
}
else
{
if (dbSpriteExist(map[row][col].layer0spriteId))
dbDeleteSprite(map[row][col].layer0spriteId);
if (map[row][col].layer1imageId != 0)
if (dbSpriteExist(map[row][col].layer1spriteId))
dbDeleteSprite(map[row][col].layer1spriteId);
}
}
}
sprintf(buf, "FPS: %i", dbScreenFPS());
dbText(0,0,buf);
dbText(0,15,"w and s to change viewport size, arrows to move");
sprintf(buf, "Camera : %d, %d View : %d, %d", CAMERA_X, CAMERA_Y, VIEWSIZE_X, VIEWSIZE_Y);
dbText(0,30,buf);
dbSync();
}
return;
}
void load()
{
// Load tiles
dbLoadBitmap("backdrop.bmp", 10);
dbSetCurrentBitmap(10);
int imgId = FIRST_L0_IMG_ID;
// Load background as layer 0 (img is 1024px)
for (int i = 0; i < (1024 /TILE_SIZE) ; ++i)
{
for (int j = 0; j < (1024 /TILE_SIZE); ++j)
{
dbGetImage(imgId, TILE_SIZE * j,
TILE_SIZE * i,
TILE_SIZE * (j + 1),
TILE_SIZE * (i + 1),
1); // Not a texture
imgId++;
}
}
LAST_L0_IMG_ID = imgId-1;
FIRST_L1_IMG_ID = imgId;
dbSetCurrentBitmap(0);
dbLoadBitmap("sprite.bmp", 11);
dbSetCurrentBitmap(11);
// Load sprite as layer 1 (img is 512 px)
for (int i = 0; i < (512/TILE_SIZE); ++i)
{
for (int j = 0; j < (512/TILE_SIZE); ++j)
{
dbGetImage(imgId, TILE_SIZE * j,
TILE_SIZE * i,
TILE_SIZE * (j + 1),
TILE_SIZE * (i + 1),
1); // Not a texture
imgId++;
}
}
LAST_L1_IMG_ID = imgId;
dbSetCurrentBitmap(0);
// Init to 0
for (int i = 0; i < MAP_HEIGHT; ++i)
{
for (int j = 0; j < MAP_WIDTH; j++)
{
map[i][j].layer0spriteId = 0;
map[i][j].layer0imageId = 0;
map[i][j].layer1spriteId = 0;
map[i][j].layer1imageId = 0;
}
}
// Create a randomly generated map
int spriteId = FIRST_SPRITE_ID;
for (int i = 0; i < MAP_HEIGHT; ++i)
{
for (int j = 0; j < MAP_WIDTH; j++)
{
map[i][j].layer0spriteId = spriteId;
map[i][j].layer0imageId = FIRST_L0_IMG_ID + dbRND(LAST_L0_IMG_ID - FIRST_L0_IMG_ID - 1);
spriteId++;
if (dbRND(10) > 5)
{
map[i][j].layer1spriteId = spriteId;
map[i][j].layer1imageId = FIRST_L1_IMG_ID + dbRND(LAST_L1_IMG_ID - FIRST_L1_IMG_ID - 1);
}
spriteId++;
}
}
}
void handleInput()
{
if (dbUpKey() && CAMERA_Y > 0) CAMERA_Y -= 8;
else if (dbDownKey() && CAMERA_Y < MAP_HEIGHT * TILE_SIZE) CAMERA_Y += 8;
else if (dbLeftKey() && CAMERA_X > 0) CAMERA_X -= 8;
else if (dbRightKey() && CAMERA_X < MAP_WIDTH * TILE_SIZE) CAMERA_X += 8;
else
{
char* c = dbGetEntry();
if (c != NULL)
{
switch(c[0])
{
case 'w' :
VIEWSIZE_X -= 64;
VIEWSIZE_Y -= 64;
break;
case 's' :
VIEWSIZE_X += 64;
VIEWSIZE_Y += 64;
break;
}
}
dbClearEntryBuffer ();
}
}