# XNA - Drawing 2D Primitives (Boxes) and Understanding Matrices in Computer Graphics

I have two issues which I wish to solve by creating 2D primitives in XNA.

1. In my game, I wish to have a "debug mode" which will draw a red box around all hitboxes in the game (Red outline, transparent inside). This would allow us to see where the hitboxes are being drawn AND still have the sprite graphics being drawn.

2. I wish to further understand how matrices work within computer graphics. I have a basic theoretical grasp of how they work, but I really just want to apply some of my knowledge or find a good tutorial on it. To do this, I wish to draw my own 2D primitives (With Vertex3's) and apply different transormation matrices to them.

I was trying to find a tutorial on drawing primitives using Direct3D, but most tutorials are only for c++, and just tell me to use XNA's Spritebatch. I wish to have more control over my program than just with Spritebatch.

Any Help on using Direct3D or any other suggestions would greatly be appreciated.

Thank you.

-
I don't see a question nor can I tell what you are trying to accomplish. If you simply want a wire frame of all your hit boxes that is very easy but I'm not sure what your goal is. –  ClassicThunder Nov 20 '11 at 23:01
I'm trying to wireframe my hitboxes, yes. However, i'm trying to do that by drawing primitive shapes, which im unsure of how to do. If I can figure out how to draw primitive shapes, I can both draw my hitboxes wireframes AND start applying different kinds of matrix translations to them (to mess around with) –  MintyAnt Nov 21 '11 at 3:34
You are probably looking for DrawUserIndexedPrimitives in conjunction with LineList. –  Jonathan Dickinson Nov 22 '11 at 10:19

If you are dead-set on using Matrix math and wanting a wireframe hitbox, DrawUserIndexedPrimitives is probably the way to go. (As Jonathan said)

However, the whole point of a debug mode is to be quick, with little overhead, is it not? I wish to suggest an alternative that I personally use in my game:

public void CollisionRectToDraw(GameObject G, int RedValue, int GreenValue, int BlueValue)
{
SpriteBatch.Draw(Pixel, new Rectangle((int)G.position.X - (int)G.center.X, (int)G.position.Y - (int)G.center.Y, G.sprite.Width, G.sprite.Height),
new Color((byte)RedValue, (byte)GreenValue, (byte)BlueValue, (byte)120));
}


Now, this will stretch a single-pixel Texture2D (that's a white pixel) to the size of your sprite's width and height. It will be solid, however. If you want to only draw the wire-frame of it (which may take more time) you simply need to make the stretched rectangle slightly larger, and use a Rectangular Region (which would be your Sprite.Position.X, Sprite.Position.Y, Sprite.Width, Sprite.Height) to "cut out" the part that overlaps your sprite.

This method is both quick, and accurate. While not as pretty as what I'm sure you're imagining in your head, it gets the job done and could be much less expensive than actually having to drawing many LineLists.

### EDIT:

This will draw four lines as Drackir suggested.

public void CollisionWireFrameToDraw(Gameobject G, int LineThickness, int RedValue, int GreenValue, int BlueValue)
{
Rectangle ObjectRect = new Rectangle((int)G.position.X - (int)G.center.X, (int)G.position.Y - (int)G.center.Y, G.sprite.Width, G.sprite.Height);

game.SpriteBatch.Draw(Pixel, new Rectangle(ObjectRect.Left - LineThickness, ObjectRect.Y,LineThickness,ObjectRect.Height),
new Color((byte)RedValue, (byte)GreenValue, (byte)BlueValue, (byte)255));//This is the line on the Left

game.SpriteBatch.Draw(Pixel, new Rectangle(ObjectRect.Right, ObjectRect.Y, LineThickness, ObjectRect.Height),
new Color((byte)RedValue, (byte)GreenValue, (byte)BlueValue, (byte)255)); //This is the line on the Right

game.SpriteBatch.Draw(Pixel, new Rectangle(ObjectRect.X, ObjectRect.Top - LineThickness, ObjectRect.Width, LineThickness),
new Color((byte)RedValue, (byte)GreenValue, (byte)BlueValue, (byte)255)); //This is the line on the Top

game.SpriteBatch.Draw(Pixel, new Rectangle(ObjectRect.X, ObjectRect.Bottom, ObjectRect.Width, LineThickness),
new Color((byte)RedValue, (byte)GreenValue, (byte)BlueValue, (byte)255)); //This is the line on the Bottom

}


This draws a line on each of the four sides (left, right, top, bottom). You can change the thickness of the line by passing in a larger (or smaller) LineThickness.

The important thing to note here is that on the Left and Top line, you have to subtract the LineThickness from it's position. (X for Left, Y for Top).

But why?

Because if you don't, the line will "creep" on top of your source sprite. By subtracting your LineThickness, you move the line back out (by offsetting it, so the width of the line doesn't widen onto the sprite.

One thing to note here is that you will have a gap in the four corners where the lines don't meet up. You simply have to choose two lines (Left and Right, or Top and Bottom) and add an offset to them to make it a complete Wire Frame. If you need help with that, I can update my code - but I thought it would be fun for you to solve.

-
You could also draw four lines using the same technique. –  Richard Marskell - Drackir Nov 28 '11 at 17:14
@Drackir Updated my answer, thanks for the suggestion! I hadn't thought of using it like that. –  electroflame Nov 28 '11 at 21:03
Cool. Thanks for updating. :) –  Richard Marskell - Drackir Nov 28 '11 at 21:13
You claim that SpriteBatch is going to be less overhead than drawing user indexed lines. This is ridiculous. Drawing a colored line doesn't do any alpha blending or color interpolation, using SpriteBatch obviously does. Also, SpriteBatch is drawing textured quads. This is texture interpolation, AND it's occurring even for pixels that never get drawn. Using a simple primitive drawer has MUCH less overhead. –  Christopher Harris Nov 28 '11 at 22:31
Also, since when is drawing 4 textured quads (16 vertices and 24 indicies) faster than drawing 4 line segments (4 vertices and 8 indicies) ? –  Christopher Harris Nov 28 '11 at 22:33

Debug Drawing

My suggestion is to create a simple "DebugDraw" class with a few methods for drawing lines, circles, and convex polygons. You can have two flavors of these methods: One for drawing outlines and the other for drawing solids.

The solid shapes would be stored in one set of vertex and index lists, and the outline shapes would be stored in the second.

All shapes should be converted to either line segments or triangles (depending on outline vs solid), and stored in the appropriate vertex or index list. When the lists get to their maximum size, automatically draw them using the BasicEffect with vertex coloring turned on.

I would use VertexPositionColor for the vertices, and I would allow the color of each shape to be specified when drawing ("myDebugDraw.DrawCircle(24, 128, 255, 0);" - where 24 is the number of sides).

I'll try to post an actual class later.

Matricies

I don't have any matrix resources, other than my math books. :)

I will say this though... Unless your doing something complex with matricies that no-one has thought of yet, as a game designer, you should probably just look at matrices as "black boxes"... It doesn't matter how they work, it just matters that you know when you transform a certain vector by a certain matrix, you get a certain result. Take a world space vector, multiply it by a view and projection matrix, and magically it's turned into a screen space vector. What more do you need to know?

-

If you are still looking for a simple way to draw shapes check this out:

http://drippingflames.com/xna/

-

I also use SpriteBatch to render 2D "hitboxes"; supply values for "_" variables.

Rectangle rectangle = _absoluteBounds;
if (_drawBorder)
{
SpriteBatch.Draw(WhiteTexture, rectangle, null, _borderColor, _rotation, Vector2.Zero, SpriteEffects.None, 0.0f);
rectangle.Inflate(-2, -2); //<=== border thickness
}
if (_texture == null) SpriteBatch.Draw(WhiteTexture, rectangle, null, _backColor, _rotation, Vector2.Zero, SpriteEffects.None, 0.0f);
else SpriteBatch.Draw(_texture, rectangle, null, _backColor, _rotation, Vector2.Zero, SpriteEffects.None, 0.0f);


-WhiteTexture is a 1x1 Texture2D

1) Fills _absoluteBounds with WhiteTexture using _borderColor for the tint

2) Shrinks rectangle by border width

3) Fills new rectangle with either the face texture, if supplied (scaled to fit in the shrunken rectangle), or WhiteTexture using _backColor for the tint

Swapping a repeating sequence of textures for _texture can produce a few basic/dirty effects, like the border lighting up and scrolling while the hitbox is active/hovered.

Using a custom Effect with SpriteBatch enables further bling.

-

Extensive research on matrix math is often quoted and, probably, gets mostly ignored. You might read and read and read and still never get it. The important thing is that XNA/DirectX/video cards DO get it. Rather than learning how and why they work, you need to learn how and when to use them. In graphic programming, Matrices are primarily used to move "Object Space" coordinates to "Screen Space".

It is important to note that this IS math so standard order-of-operations applies with a few extras. In any space, matrix transforms are performed around the resulting coordinate system's (0, 0, 0), not the source's. If you move a coordinate away from (0, 0, 0), then scale the coordinate, it will move even further away. Usually, you want to scale first, then translate(move).

Coordinate * Scale * Translation != Coordinate * Translation * Scale


In 3D games, this happens in 3 phases and uses 3 matrices, World, View, and Projection. They are actually applied together, but it is easier to visualize their use one at a time.

The World matrix allows you to move and size geometry in the world. You can use geometry created with any actual scale/size/units, from any software. Object Space is typically, but not necessarily, centered at (0, 0, 0). Object Space units, axis angles, etc., are all user-defined. There is no software-defined upper or lower limits for coordinate values in Object Space.

ObjectCoordinate * Objects_WorldMatrix = WorldCoordinate


Once everything has been translated to World Space, the entire world acts as a single model, centered at (0, 0, 0). You can optionally move/rotate/scale the entire universe with an additional matrix. There is no software-defined upper or lower limits for coordinate values in World Space.

WorldCoordinate * Worlds_WorldMatrix = FinalWorldCoordinate


The View matrix typically represents the Camera. The View matrix moves, rotates, and scales the entire world into its' own coordinate system. The Camera's location becomes (0, 0, 0). View Space coordinates range from (-1, -1, -1) to (1, 1, 1). Values that are out-of-range, are not visible. Coordinates are not discarded whether they are visible or not.

FinalWorldCoordinate * View = ViewCoordinate


The Projection matrix specifies the portion of the Camera's 3D view volume to draw to the current Viewport, set on the current RenderTarget. By default, the entire "screen". The Projection matrix defines the distance at which "behind the camera" occurs, as well as how far into the scene to draw. Geometry that is behind the camera, too far away, too far left, etc., gets discarded.

ViewCoordinate * Projection = ViewportCoordinate


There are only a few more options to consider. By default, the "screen" is the background texture of a Windows.Forms.Form. You can specify another RenderTarget with a different size. Additionally, setting a Viewport specifies a portion of the current RenderTarget to move/scale draw calls to.

In 2D games, the same things happens, except you draw with ObjectCoordinates that are already in Screen Space units. A square, defined at (0, 0) with a width and height of 1, can be used to draw all squares by adding a "World" matrix. The World matrix scales the square to the correct size, then moves it into position. You can draw the one square over and over, supplying each of your object's World matrices, one per draw.

ObjectCoordinate_AlreadyInScreenSpace * World = ViewportCoordinate

-