Wednesday, May 13, 2009

Getting a Move On

I recently took my first foray into animation, and it wasn't nearly as scary as I expected. As it turns out, animation was based largely upon the work I did with sprite sizes in the last post. As a recap, since textures need to be sized by powers of two, I found I needed to pull out rectangles within the textures to create sprites of varying sizes. I also made three sprites out of one texture that included all three images.

Well, animation follows the same idea. For reference, take a look at this texture image:

(What you're not seeing is that this image has transparency in it, something else I recently figured out.)

So, this texture has six frames of animation in it for our swirly circle. To animate it I simply display a different rectangle within the texture on each pass of OnPaint. I made a SimpleAnimatedSprite class to handle these animations. It stores the number of rows and columns of sprites inside the texture, as well as the size of each frame (they all must be the same). Then it just iterates through each image and displays them in order.

This worked perfectly well, but it animated extremely fast so I added another property to my class, the length of time between frames in milliseconds. I made the OnPaint loop display the same frame until the correct amount of time has passed, then move to the next frame and calculate the time for the frame after that one. I was able to successfully control the speed of the spiral, and even make it controllable by the user.

There are a few limitations to this class. First off, all the frames have to be the exact same size, and the frames need to be arranged in the texture image such that the final row of frames is full (you couldn't have seven frames for example). I'll create a ComplexAnimationSprite class to overcome these limitations.

Sunday, May 10, 2009

Sprite Sizes

I set myself to displaying a nice logo screen before my game came up recently. I figured this would be a fairly straightforward process given the work I had done so far. Just setup a Scene object with one sprite in it and stick it in the center of the screen. Easy!

Well, nothing is ever easy, as soon as I slapped my logo on the screen the image was stretched! It look horrible! Since I was testing this in my monitor's native resolution I knew exactly how the image should look. I began the process of debugging and found that it was reading my logo in as a 1024x1024 image, when the actual image was something more like 600x600.

With a bit of Googling I undercovered that the textures I'm using as sprites need to be loaded in with square resolutions in powers of two (2x2, 4x4, 8x8, 16x16, 32x32, 64x64, 128x128, 256x256, 512x512, 1024x1024, etc). The two colored dot images I was using were 100x100 and 200x200, but as expected it turns out these were being loaded in as 128x128 and 256x256 respectively. I just hadn't noticed because it wasn't too drastic at that size.

Well, the solution to this is to load your sprites in as textures of the allowed size, and the grab out the pieces you need. Example:

sprite.Draw(spriteTexture, textureSize, new Vector3(0, 0, 0), new Vector3(xPos, yPos, 0), this.alphaColor);

The second parameter of the D3D Sprite.Draw method takes a Rectange object (textureSize) that specifies what portion of your texture you want to draw. I created a sprite subclass called BlitSprite (I *think* the term for this is blitting, thus the name) which is overloaded to take a rectangle instead of just using the entire texture square.

You can (and should!) also combine sprites into a single texture. Now I'm pulling three colored dots from one image file like this:



















Also, I added a parameter to my Sprite baseclass that allows me to pass in a black value to the image. So, against a black background that behaves like a fade. I used it to gently fade my logo in and out before the game starts up. Of course, the user can just hit any key to skip it :).

Thursday, May 7, 2009

A Real Engine

The farther I got into the project the more types of games I was coming up with that could use the framework that I am creating here. Everything I've done is pretty generic so far, but it was coupled with the game logic fairly tightly (or rather, where future game logic will go). If I wanted to make another game using the same structure I would have to re-engineer a lot of the code to reuse it.

So I recently spent some time breaking the code apart and creating a game engine that is separate from the game implementation. I took all the code dealing with graphics and devices and sprites and placed it all in a separate .DLL project that I could include into the main project. This was a fairly successful endeavor. The main game project doesn't even include references to the DirectX libraries anymore, just to the engine .DLL. The game project can just create Scene objects using the Scene base class from the engine and just worry about managing sprites and logic.

For what its worth, I called the engine the same as my design 'group', the FirstLight engine. Sounding important is all part of the fun, right?

Tuesday, May 5, 2009

A Logo!



















I figured I needed some sort of logo for my development. Something that looked really official. A banner I could fly above my little game, and any future games I create. I came up with the name FirstLight Studios and put together this logo today. I'm usually fairly critical of my own art work, but I'm pretty happy with how this turned out. I know, I know...'studios' is a little silly as it's really just me in my pajamas banging out code at my desk, but I thought it sounded fun.

So, now when my game starts up the logo of FirstLight Studios can gently fade in, all professional like.

Sunday, May 3, 2009

Making a Scene

With my sprite abstraction layer in place I needed some larger structure that could manage groups of sprites and the application logic associated with them. What I ended up with was something I called a 'scene'. A scene would be some discrete function of the game, like a main menu, a map screen or a battle screen. Each scene manages its own sprites by registering them with the GraphicsManager and has an UpdateScene method that gets called by the main form on each game loop right before the graphics are updated in the GraphicsManager. All of this is handled by another interface called IScene.

I created a class named SampleScene which loads a single sprite into memory, my favorite blue dot, and handles the logic to move this dot with the arrow keys. When the enter key is pressed the scene tells the main form that it should load the next scene (which in this case is the exact same scene. The first scene is torn down and the next scene is created and away we go. On the screen this means that the blue dot just moves back to the starting location, but under the hood a scene has been swapped out.

Along with all this I added a few nice things here and there. Sprites and Scenes can dispose of themselves now to get their resources out of memory. This is done behind the scenes when a scene is torn down before the incoming scene is initialized. I also built out some factory classes for sprite and scene creation. Both need access to resources like the GraphicsManager to intialize properly so I wrapped all that up in the factory pattern. Requesting a new sprite or scene flows nicely now.

Quite a productive weekend!

Saturday, May 2, 2009

Abstract Thinking

As I mentioned yesterday, I set out to create an abstraction layer around the early graphics work I did yesterday and ended up with something I'm quite happy with. I worked and reworked my classes several times before I came up with something that seemed straightforward and hid the implementation of the graphics rendering well enough. There's still a few things being passed around that I'd rather not pass around, but I'm not too worried about it.

I now have a class called GraphicsManager which houses the Direct3D device instance. It's job is to setup the instance and handle the rendering of each frame in the game loop. The GraphicsManager is created in the 'static void main' class (which I named Launch) along side the windows form and is immediately passed into the windows form so the form holds the reference to it. GraphicsManager has a method called PerformFrameRender which the form calls in it's overloaded OnPaint event. That was the form doesnt need to know a thing about rendering any graphics. It acts purely as a container and pump to drive the game loop. Later, the logic loop will be driven from here too.

With this framework in place I can create sprites on the screen very easy with code like this:

BasicSprite sprite1 = this.graphicsManager.CreateBasicSprite();
sprite1.LoadSprite(@"../../images/blue.tga", 100, 200);
this.graphicsManager.RegisterSprite(sprite1);


I am requesting a BasicSprite object from the GraphicsManager, loading it with an image file and a screen location, and then registering it with the GraphicsManager. (I went round and round about creating and registering in the same step or seperate steps, but figured this was more flexible when it cames to preloading a ton of image data before pushing it into the pipeline).

All sprites inherit from an ISprite interface I created. This way the rendering of the sprite is up to the implementation of the particular sprite class, but the GraphicsManager can just loop through all registered sprites and draw them. Right now I just have BasicSprite, a stationary image, but later I can make things like AnimatedSprite and MovingSprite with this framework.

Friday, May 1, 2009

Baby Steps

Today I decided to start writing some code. Not code that will ever make it into a finished product, but rather some simple DirectX tests to get something running and compiling. And this, ladies and gentlemen, is the product of my hard work....
















Ok, so it's not much. There's a blue dot in the upper lefthand corner of the screen.

My understanding was that one would use DirectDraw for 2D sprite rendering and Direct3D for, well, 3D rendering. As it turns out, DirectDraw is completely depricated in DirectX 9, and may have been for several versions now. What I found out was that I should use Direct3D to draw images on flat surfaces. Fortunately this requires no 3D work at all and Direct3D has classes to facilitate this.

This little application bascially requests a full screen from the hardware with a back buffer to draw to. It would seem I do not need to manually draw to the back buffer and flip it to the front like I would in DirectDraw, Direct3D seems to handle that aspect for me. After a full screen has been presented I setup a sprite using a .tga file I created in GIMP (a blue dot in this case). Finally I overloaded the OnPaint event of the (full screen) window and told it to draw my sprite there. The OnPaint event ends by calling this.Invalidate() which basically means that OnPaint will be called immediately again, thus running a very, very game loop. Each time the screen is obliterated and the sprite redraw. Again, there seems to be a back buffer here but I'm not managing it. All the better. Our little application also overloads the OnKeyUp event so that an escape keypress will end the application.

This simple code will form the foundation of the graphics abstration layer. I need to wrap some classes and such around this so that these nuts and bolts aren't something I need to worry about as I write the game presentation and logic. I think I'll work on that next.