Question

I have a 2D game in XNA which has a scrolling camera. Unfortunately, when screen is moved, I can see some artifacts - mostly blur and additional lines on the screen.

I thought about changing coordinates before drawing (approximating with Ceiling() or Floor() consistently), but this seems a little inefficient. Is this the only way?

I use SpriteBatch for rendering.

This is my drawing method from Camera:

Vector2D works on doubles, Vector2 works on floats (used by XNA), Srpite is just a class with data for spriteBatch.Draw.

public void DrawSprite(Sprite toDraw)
{
    Vector2D drawingPostion;
    Vector2 drawingPos;
    drawingPostion = toDraw.Position - transform.Position;
    drawingPos.X = (float) drawingPostion.X*UnitToPixels;
    drawingPos.Y = (float) drawingPostion.Y*UnitToPixels;

    spriteBatch.Draw(toDraw.Texture, drawingPos, toDraw.Source, toDraw.Color,
        toDraw.Rotation, toDraw.Origin, toDraw.Scale, toDraw.Effects, toDraw.LayerDepth + zsortingValue);
}

My idea is to do this:

drawingPos.X = (float) Math.Floor(drawingPostion.X*UnitToPixels);
drawingPos.Y = (float) Math.Floor(drawingPostion.Y*UnitToPixels);

And it solves the problem. I think I can accept it this way. But are there any other options?

Était-ce utile?

La solution

GraphicsDevice.SamplerStates[0] = SamplerState.PointWrap; 

This isn't so much a problem with your camera as it is the sampler. Using a Point Sampler state tells the video card to take a single point color sample directly from the texture depending on the position. Other default modes like LinearWrap and LinearClamp will interpolate between texels (pixels on your source texture) and give it a very mushy, blurred look. If you're going for pixel-graphics, you need Point sampling.

With linear interpolation, if you have red and white next to each other in your texture, and it samples between the two (by some aspect of the camera), you will get pink. With point sampling, you get either red or white. Nothing in between.

Autres conseils

Yes it is possible... try something this...

bool redrawSprite = false;
Sprite toDraw;

void MainRenderer()
{
   if (redrawSprite)
   {
      DrawSprite(toDraw);
      redrawSprite = false;
   }
}

void ManualRefresh()
{
   "Create or set your sprite and set it to 'toDraw'"
   redrawSprite = true;
}

This way you will let main loop do the work like is intended.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top