4

I have read a few tutorials explaining transform matrices for XNA/Monogame. The problem is that these matrices are applied to

SpriteBatch.Begin(...matrix);

This means that all Draw code will be transformed. How do I apply a transformation matrix to a single drawable object? In my case I want to transform a scrolling background so that it automatically wraps.

SpriteBatch.Draw(.. this has no transform matrix parameter?);
Kokodoko
  • 26,167
  • 33
  • 120
  • 197

2 Answers2

3

If you want to use a specific spritebatch begin call for some drawing calls only, you can start a new one as needed.

for example

SpriteBatch.Begin(...matrix);

//Draw stuff with matrix

SpriteBatch.End();

SpriteBatch.Begin();

//do the rest of the drawing

SpriteBatch.End();

this is commonly used to draw a bunch of objects with a "camera" matrix at appropraite position, scale and rotation, then another spritebatch.Begin is called to draw the flat, static UI on top, etc.

irreal
  • 2,217
  • 18
  • 23
  • Thanks. I also read that you shouldn't call more than one spriteBatch.Begin in each Draw loop... :-) I'm going to try this out! – Kokodoko May 26 '15 at 13:54
  • You should absolutely keep it to a minimum. In my experience, calling it twice was not a noticable performance hit. Your case will of cousre depdent heavily on how heavy your game is and what type of hardware you run it on. In case you have to get rid of the second begin / end block, you can apply the transformations manually in the extended .Draw() overload. You can also adjust some other parameters inside a begin call. I'd suggest only messing with that stuff if the second begin end becomes a serious performance hit. – irreal May 26 '15 at 14:02
  • But I don't see an overload method for Draw() that includes a transformation matrix?? There is an origin Vector but that's not the same. I need my texture to wrap around when it transforms off screen. – Kokodoko May 26 '15 at 14:19
  • I meant you can apply individual elements such as x/y scale, rotation, source and dest rect, etc. For wrap around you'd have to use a shader effect or hack in something with multiple draw calls and some math. I still think you should go with two spritebatch calls, it shouldn't tax your game too much. – irreal May 26 '15 at 14:21
0

I had this same issue, but using SpriteBatch.Begin() and SpriteBatch.End() didn't work for my situation.

You can transform a single drawable object like this (this code assumes that the object is being drawn to a destination Rectangle):

static Point Transform(Point point, Matrix matrix)
{
    var vector = point.ToVector2();
    var transformedVector = Vector2.Transform(vector, Matrix.Invert(matrix));
    return transformedVector.ToPoint();
}

// matrix below is the same as the matrix you used in SpriteBatch.Begin(...matrix).

var destinationRectangle = new Rectangle(
    Transform(bounds.Location, matrix),
    Transform(bounds.Size, matrix)
);

// Draw the object to the destination rectangle!
Captain Delano
  • 427
  • 1
  • 4
  • 12