Ball Race – Day 11

The first thing I did this day was to implement the Farseer physics engine into my project. What a tremendous step forward. Not only was it easy to do, it also delivered the results I had been hoping for from the moment on I got it working.

Screenshot of a tilted wooden maze with a ball in it

I’m still not sure what to do about the holes in the floor. Farseer is a pure 2D physics engine and it simulated the effect of tilting the maze board simply by applying forces to the ball, but, essentially, the ball is a circle that’s moving around inbetween rectangles for Farseer. Maybe I can get away with a fake simulation where I apply forces that push the ball further towards the center of the hole and let it accelerate downwards on the Y axis without the knowledge of Farseer.

The ball is still looking rather dull and I’m beginning to think about implementing real-time reflection mapping in my little game, so it properly reflects the walls around it. The other solution would be to make the ball non-reflective, however, however, the ball must not be textured since the rotation would never be right as long as the physics are 2D.

Ball Race – Day 10

Beta 2 of XNA Game Studio Express has been released to the public today. Porting my code to Beta 2 took me about one hour since some genius decided to make the all the model framework classes sealed and remove their generic versions. Also, the GameServices collection now lost its generics as well and requires manual downcasting.

While updating the code, I also broke something in the stencil buffer drawing code which now, instead of limiting the shadow to shadowed regions, limits the walls to holes in the floor. Fiddling around with the shader effect files for the stencil and shadow drawing solved the problem.

Next, finding some swept circle vs. aligned rectangle collision detection code on the net has prooven itself to be harder than it seemed. I don’t have the strong math backgound needed to code such stuff myself. I ported the only code that seemed usable, even thought it was originally intended for sphere/polygon collisions. My first attempt at simple ball physics doesn’t go to well and I fear I will have to integrate something like Ode at the end. Maybe the pure .NET Farseer Physics Engine can fill this gap?

Ball Race – Days 8 and 9

I just couldn’t stop thinking how cool it would be if the walls of the maze would cast realistic shadows, so on Day 7, I began implementing stencil shadow volumes in my little game. Generating the silhouettes, something I was scared of, has been extremely easy since all you need to do is find all neighboring triangles in a mesh where one triangle is facing away from the light source and the other is facing towards the light source.

Generating quads for the silhouette edges wasn’t exactly difficult either after I already generated the entire maze geometry programmatically. However, I didn’t know what to do about the shadow caps, so I just left them be. This is not a problem because the camera will never enter a shadow volume and the caps will always be clipped by the Z buffer.

Screenshot of a programmatically generated maze with stencil shadows

Finally, it was time to start with the gameplay code. I still needed to a main menu, level selector, the game itself, maze/ball collision detection and some dummy physics to make the ball behave in a realistic manner.

If you’re wondering why this screenshot now shows a Windows Vista frame, this afternoon Windows XP self-destructed and took the whole partition with it. Forced to reinstall from scratch, I decided to check out Windows Vista RC2…

Ball Race – Day 7

On day 7, I finally completed the scene graph component. With this component, it is easy to place the meshes of my game in relation to each other. For example, the physics for the ball in my game are actually 2D (the ball will never hop, no matter how quick or hard you tilt the maze). The ball will be a child of the maze scene node. That means I only need to modify the ball scene node’s position and do not have to take into account the maze’s current rotation or where in the scene the box is placed. The scene graph handles that automatically and efficiently for me.

There also is a new component to manage effect files: The EffectManagerComponent. It loads and compiles effect files so I don’t have to do it all manually.

I spent some time cleaning up what I had so far. The GameComponents now make proper use of the GameServices concept and can handle device resets as well as do clean shutdowns. Models can now release their resources and will do so when it is required. All this has been implemented in a way that I can still develop care-free and happens seemingly on its own.

Ball Race – Day 6

My texture coordinates had some minor issues as well. Thanks to the “show normals” shader in ATI RenderMonkey I was able to visually verify that all normals and texture coordinates are continuous and correct.

I also spent some time writing code to generate the tilt knobs that will be on the sides of my mounting box and added code to generate polygons for the underside of the maze. So theoretically, you could now view the maze from below as well. This also makes my entire geometry solid, meaning that there are no leaks where you could see ‘inside’ an object, which is important if I decide to try myself at shadow volumes later in the project.

Screenshot of a maze board rendered with textures and lighting

For the rest of the day, I’ve been improving on my usage of the XNA model classes and then designed a little scene graph system, as seen from the current state of things, this is the cleanest way to decouple the scene from the game logic. I need the scene building stuff separate because I want to create a cool level selection system which renders previews of the maze. It wouldn’t be the best thing to always have the game logic all over the place when I just need an image of the maze!

Ball Race – Day 5

Have… to… continue! Yesterday, I bought Gothic 3. I have played all its predecessors and the entire series is highly addictive to me. This will wreak havoc on my development of this little project.

Anyway, as I found out, it’s not possible to load .x files with the XNA beta yet, so my original plans of modeling some stuff in 3dsmax will fall flat. Maybe I could use the Mesh classes to still get some vertices loaded, but since there’s only one non-dynamic shape (the knobs on the sides of the board), I’ll just go ahead and build my geometry programmatically.

After checking out some phong shaders I found on the need, I noticed that my normals still weren’t right for the walls. Turned out to be a minor typo. With some lighting, everything is looking so much better. I’d love to add shadowing, too, but I feel that it’s too complicated to tackle just now.

Ball Race – Day 4

My wall geometry generator now produces proper normals for all the walls so the lighting should now yield the results I’m hoping for. Because I’ve never done shader programming before, I downloaded ATI’s RenderMonkey in the hope that it could help me create some simple shaders nevertheless. Not only did RenderMonkey give me the exact shader I needed to test my texture coordinate generation code, it also greatly increased my understanding of shaders with its excellent shader code generator.

So now that the walls were working, the floor came up on the task list. Normal floor plates are just boring quads, but making holes in the floor was a bit more difficult. In the end, I simply arranged some vertices in a circle and built triangles from the circle points to the nearest corner of the surrounding floor tile.

So this is what I had at the end of day 4:

Screenshot of a maze board with smeary textures und no lighting

In case you are wondering why the floor texture is so smeary, that’s intentional. Otherwise, as long as I don’t have lighting implemented yet, you wouldn’t be able to see the walls clearly in a static screenshot :)

Ball Race – Day 3

The wall generation code has finally taken shape and generates the vertices for the walls exactly like it was meant to be. Vertices are optimally shared between the walls and no polygons are ever generated that the user wouldn’t be able to see. The code also avoids T vertices in order to prevent flickering pixels at the wall junctions.

Screenshot of a wireframe mesh showing a maze forming the letters H I

Nevertheless, I fear I will have to change this code soon. It currently doesn’t generate texture coordinates and the shared vertices will become a problem if I want a continuous surface on my maze walls (which I plan to do by calculating u,v as x+z,y – which doesn’t work for the top of the walls since y [==v] would be the same everywhere).

Plus, the current code generates normals that are diagonally pointing away from the walls. If I would use these normals for ligthing, the walls would look as if they were rounded. I’ll still have to see whether I’m going to use normal-based lighting at all.

Ball Race – Day 2

After finishing up the level parser with some minor tweaks and writing some unit tests which immediately highlighted several mistakes I then fixed, I began with the geometry building code.

The level file format is really easy and anyone should be able to create his own mazes. For example, this simple text file will be enough to have my game make a nice, textured 3D maze board of it:

###############
#O            #
# + +-+-+-+-+ #
# |    O      #
# + +-+-+ + +-#
# |       |   #
# +-+-+ + + + #
#     | | | |O#
#-+-+ + + + + #
#       | | | #
# + +-+-+ + + #
#F|       |   #
# + +-+-+ +-+ #
#        O|S  #
###############

After taking an in-depth look at the XNA model classes, I decided to build a special MazeModel class that would construct a model from a maze provided to it in its constructor.

That took most of day 2. While writing the mesh generation code, I noticed that my original idea with equally sized tiles and walls that only used a fraction of the tile they were on didn’t work out. But because I had already made the decision to limit the tiles walls can be on, it was not a drastic change to use alternating tile sizes.

Ball Race – Day 1

It took me some time to figure out how to organize my code so it fits in with the XNA framework design. Because the game is so small, I did this by building some dummy classes and that I renamed and moved around in the project tree until I had reached an adequate design.

Maybe some people would have used an UML prototyping tool, but I am used to thinking in terms of design and code, so, just like a good chess player, I can see when a design will work out or when it will blow up.

Then I identified the hardest, probably most demotivating task at hand. If you can, I think it’s always good to start there because this is likely the point where you would "postpone" working on the project for the rest of eternity.

The hardest part in this project seemed to be the dynamic construction of the level’s 3D model out of a simple text file that defines the maze using pure ascii characters. You have to create a bullet-proof parser and then somehow build a contiguous vertex array for all the walls, floor plates and holes in pure code.

So day 1 ended with me writing a parser for the textual level file format I have layed out before.