Reputation: 143
I recently made some major optimizations to a certain method that returns the value of a block at a position:
public int blockGet(x, y, layer)
I use this method in a lot of places, including this method, which draws blocks in an area:
public void DrawBlock()
{
Stopwatch swblock = new Stopwatch(); swblock.Start();
//Set variables
Color drawColor = Color.White;
for (int x = viewbX - 1; x < viewbX + viewWidth; x ++)
{
for (int y = viewbY - 1; y < viewbY + viewHeight; y ++)
{
//Update
#region Variables
int blockBG = blockGet(x, y, layerBG);
int blockBG2 = blockGet(x, y, layerBG2);
int blockFG = blockGet(x, y, layerFG);
int blockFG2 = blockGet(x, y, layerFG2);
Rectangle tilePos = new Rectangle((x * blockSize - viewX), (y * blockSize - viewY), blockSize, blockSize);
#endregion
#region Update
if (globalUpdater == true)
{
if (blockGet(x, y, layerFG) > 0)
{
blockUpdate(x, y, blockBG, blockFG, blockFG2);
}
//Destroy Deco
if (block.GetTransparent(blockGet(x, y, layerFG)) && blockGet(x, y, layerFG2) != 0) blockSet(x, y, layerFG2, 0);
if (block.GetTransparent(blockGet(x, y, layerBG)) && blockGet(x, y, layerBG2) != 0) blockSet(x, y, layerBG2, 0);
}
#endregion
//Draw
#region Draw backdrop
if (globalBackdrop == true)
{
if (y > heightmapGet(x) + 16) spriteBatch.Draw(Game1.spriteBackdrop, tilePos, Color.White);
}
#endregion
#region Draw background layer
if (blockBG > 0)
{
spriteBatch.Draw(Game1.spriteBlock, tilePos, new Rectangle(mathImgX(blockBG), mathImgY(blockBG), 32, 32), Color.White);
if (blockBG2 > 0)
spriteBatch.Draw(Game1.spriteDeco, tilePos, new Rectangle(mathImgX(blockBG2), mathImgY(blockBG2), 32, 32), Color.White);
spriteBatch.Draw(Game1.spriteHalfpixel, tilePos, Color.White);
}
#endregion
#region Draw foreground layer
if (blockFG > 0)
{
spriteBatch.Draw(Game1.spriteBlock, tilePos, new Rectangle(mathImgX(blockFG), mathImgY(blockFG), 32, 32), Color.White);
if (blockFG2 > 0)
spriteBatch.Draw(Game1.spriteDeco, tilePos, new Rectangle(mathImgX(blockFG2), mathImgY(blockFG2), 32, 32), Color.White);
}
#endregion
#region Draw drop shadow
if (blockBG > 0)
{
if (block.GetTransparent(blockFG) == true)
{
int up = blockGet(x, y - 1, layerFG);
int down = blockGet(x, y + 1, layerFG);
int left = blockGet(x - 1, y, layerFG);
int right = blockGet(x + 1, y, layerFG);
if (up > 0) { if (block.GetTransparent(up) == false) spriteBatch.Draw(Game1.spriteBlurTop, tilePos, Color.White); }
if (down > 0) { if (block.GetTransparent(down) == false) spriteBatch.Draw(Game1.spriteBlurBottom, tilePos, Color.White); }
if (left > 0) { if (block.GetTransparent(left) == false) spriteBatch.Draw(Game1.spriteBlurLeft, tilePos, Color.White); }
if (right > 0) { if (block.GetTransparent(right) == false) spriteBatch.Draw(Game1.spriteBlurRight, tilePos, Color.White); }
}
}
#endregion
}
}
swblock.Stop(); debugTime.Add("Draw Blocks = " + swblock.Elapsed);
}
Basically this method does a for() loop that draws the four blocks layers (BG, BG2, FG, FG2), and a shadow effect on the uncovered background (drop shadow).
It is also measured by StopWatch
.
This is the region of my draw method that calls the DrawBlock()
above.
Stopwatch sw2 = new Stopwatch(); sw2.Start();
spriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.PointClamp, s1, null, a);
//Draw blocks
if (globalDrawBlocks)
DrawBlock();
//Player
if (globalDrawPlayer) player.draw(spriteBatch);
spriteBatch.End();
sw2.Stop(); debugTime.Add("Draw Game = " + sw2.Elapsed);
The problem is that this causes obvious (and measured, using an FPS meter) lag. What's weird is that the stopwatch above tells me that the operation takes about 00.005ms, which is about 5 times faster than the amount of time it used to take, but yet it still lags as if I had changed nothing. Am I misinterpreting this measurement, or is it actually a problem?
I cannot tell if this is a measurement or performance or interpretation issue!
Upvotes: 0
Views: 89
Reputation: 995
See the SpriteSortMode documentation.
It states that the Deffered
mode waits for the call to SpriteBatch.End
before drawing anything, so the call to Draw
queues the draw action. The Immediate
mode draws sprites as soon as a call to Draw
is made.
Therefore, the Stopwatch
doesn't give the correct measurement because nothing is actually drawn while it runs.
Upvotes: 4