Doing 2D in SlimDX

Now that I've had a couple of weeks to play around with 2D programming in Direct3D9 via SlimDX, here are a few things that I've found.

After creating the Direct3D Device (as explained in the "Graphics Enumeration and Launching the Game Form" post), I create a Direct3D Sprite object (which I will be calling a "Sprite Batch" object):

varSB = New Direct3D9.Sprite(varD3D_Device)

This will be passed through the main Nimble2D object to each of the 2D objects that will be drawing themselves to the screen.

The magical math-thingy that makes the whole thing work is how Matrices and Matrix Transformations are used to determine where and how 2D sprites are drawn.  As mentioned earlier, all objects within a gamespace (including cameras) will have a location (simply a "Current X" and "Current Y") within "game space", which essentially is a way to measure their positions relative to each other.  They will also have a "Facing" angle and a "Scale".  These are the main pieces used within SlimDX's nifty Transformation2D function to get the matrix needed to draw things how they should appear on screen.

First, the camera:

varActualMatrix = SlimDX.Matrix.Transformation2D(New SlimDX.Vector2(varWidth / 2, varHeight / 2), 0, New SlimDX.Vector2(varScale), New SlimDX.Vector2(varWidth / 2, varHeight / 2), varN2D.QuickTrig.DegreesToWinRadians(varFacing), New SlimDX.Vector2(varCurX, varCurY))

varInverseMatrix = SlimDX.Matrix.Invert(varActualMatrix)

The parameters of that function are as follows:

  • scalingCenter - A Vector2 around which to scale things (set to the middle of the screen)
  • scalingRotation - A Single that indicates rotating the X/Y scaling away from the identity angle
  • scaling - A Vector2 that gives the actual X/Y scaling (1.0 = original size)
  • rotationCenter - A Vector2 around which to rotate things
  • rotation - The angle to rotate (I like to work with angles in degrees ... DirectX and Windows trig functions prefer radians ... so I have a translator function)
  • translation - A Vector2 to relocate everything in X/Y space

The first line sets the camera's actual matrix ... the second line uses that to create the inverse of it, which will be passed to the sprites within the gamespace to relocate them in relation to the camera.

 So, the sprites go like so:

Me.varMyTransform = SlimDX.Matrix.Transformation2D(New SlimDX.Vector2(varCurX, varCurY), 0, New SlimDX.Vector2(varSourceScale.X * varScale, varSourceScale.Y * varScale), New SlimDX.Vector2(varCurX, varCurY), varN2D.QuickTrig.DegreesToWinRadians(varFacing), New SlimDX.Vector2(0))

(For my sprites, I have a "SourceScale" that indicates if the initial source image is always to be stretched.)

To draw things, the following steps are taken:

  1. Begin Scene & Clear to Background color (Direct3D Device)
  2. Cycle through all layers ...
    1. Begin Drawing Sprites (Sprite Batch)
    2. Cycle through all sprites ...
      1. Transform the Sprite Batch Matrix
      2. Draw the sprite
    3. End Drawing Sprites
  3. End Scene
  4. Present to Screen

In this system, these steps are scattered through several objects, but put together, they look something like this:

     varD3D_Device.BeginScene()

     varD3D_Device.Clear(ClearFlags.Target, varCurGameSpace.BackgroundColorOnly, 1, 0)

     varN2D.SpriteBatch.Begin(SpriteFlags.AlphaBlend Or SpriteFlags.DoNotSaveState)

     varN2D.SpriteBatch.Transform = SlimDX.Matrix.Multiply(varMyTransform, LayerTransform)

     varN2D.SpriteBatch.Draw(varSourceTexture, varSourceRect, New SlimDX.Vector3(varOrigin.X, varOrigin.Y, 0), New SlimDX.Vector3(varCurX, varCurY, 0), Color.FromArgb(varAlpha, varColorOnly))

     varN2D.SpriteBatch.End()

     varD3D_Device.EndScene()

     varD3D_Device.Present()

I have other code bits in between things here and there to handle stuff like allowing for additive blending effects, full-screen fade in/out, writing "screen info" (screen size, camera position, FPS) to the screen, etc.

What I'm working through now is the sprite-based primary shapes (filled rectangles, circles, and triangles, lines, empty rectangles, filled rectangles with borders, and empty polygons using lines).  I hope to give some details about the lookup-table trig system being used at some point as well.

-Matt

Published Tuesday, February 12, 2008 7:22 PM by MattWorden
Filed under: , , ,

Comments

# re: Doing 2D in SlimDX

Its good to see some new life in 2D!

Not since the DXGame days have I felt the 2D enthusiasm of programming with VB.

Reminds me of the DXGame days?

I'm looking forward to future developments!

Monday, March 10, 2008 2:15 AM by Programit

# re: Doing 2D in SlimDX

Hello ProgramIt!

Nice to hear from you.  Yes ... VB.Net + SlimDX has gotten me excited as well.  And my intention *is* to essentially replace DXGame (and extend a bit beyond it) as my main go-to toolset for 2D games.

We'll see if I can deliver! ;-)

-Matt

Monday, March 10, 2008 10:45 AM by MattWorden