I'm trying to implement dirty rectangles in a game I'm making in directx. For those who don't know, this means that when the background is drawn, not all of it is drawn every time, when a player/bullet/whatever moves, it marks the area that it used to occupy as a dirty rectangle, ie an area which needs to be redrawn. This saves a few fps because the background is the largest texture in the game and drawing it every single game loop is wasteful.
So, when an entity moves, it marks the area as dirty like so:
1 2
|
WORLD.Dirty(m_pos, VIS.getFrameWidth(m_gfxID), m_scale);
m_pos += m_direction;
| |
the dirty function is shown below
1 2 3 4 5 6 7 8
|
void CWorld::Dirty(D3DXVECTOR2 pos, int width, float scale)
{
D3DXVECTOR2 minimum(pos.x - width/2*scale, pos.y - width/2*scale);
D3DXVECTOR2 maximum(pos.x + width/2*scale, pos.y + width/2*scale);
CRectangle* rect = new CRectangle(minimum, maximum);
m_dirtyRectangles.push_back(rect);
}
| |
m_dirtyRectangles is an std::vector storing pointers to CRectangles.
After drawing all entities, the world class deletes all dirty rectangles and then more are made in the next update loop.
1 2 3 4 5 6 7
|
for (unsigned int i=0; i<m_entityVector.size(); i++)
{
if (m_entityVector[i]->IsActive())
m_entityVector[i]->Draw();
}
m_dirtyRectangles.erase(m_dirtyRectangles.begin(), m_dirtyRectangles.end());
| |
Here is the CBackground::Draw function, which calls CVisualisation::DrawBackground() which calls CSprite::DrawBackground.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
|
void CBackground::Draw()
{
std::vector<CRectangle*> *rects = WORLD.getDirtyRectangles();
std::vector<CRectangle*>::iterator iter;
for (iter = rects->begin(); iter < rects->end(); iter++)
{
CRectangle * rect = *iter;
VIS.DrawBackground(m_gfxID, rect);
}
}
void CVisualisation::DrawBackground(int id, CRectangle* rect)
{
assert ( id < (int)m_spriteVector.size() );
m_spriteVector[id]->DrawBackground(m_sprite, rect);
}
void CSprite::DrawBackground(LPD3DXSPRITE spritePtr, CRectangle* rect)
{
RECT rct;
rct.left = rect->m_min.x;
rct.right = rect->m_max.x;
rct.top = rect->m_min.y;
rct.bottom = rect->m_max.y;
spritePtr->Begin(D3DXSPRITE_ALPHABLEND);
spritePtr->Draw(m_texture,&rct,NULL,NULL,0xFFFFFFFF);
spritePtr->End();
}
| |
When entities are rotated the dirty rectangles don't work properly, the wrong part of the background texture is drawn over the entity's old location. Testing it with an entity moving directily downwards with a rotation value of 0.0f it works as it should. The rectangle class has been tested and works fine so that is not the cause of the problem. Other than that, I am confused!
Sorry that was so long. Danke =)