Pregunta

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!

¿Fue útil?

Solución

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.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top