Managed World

Techno-babble from yet another babbler RSS 2.0
# Wednesday, May 24, 2006

A couple minor changes (or not so minor when it comes to control schemes). Tonight I took some time to play Geometry Wars Evolved for a while (the game Spaceballs is based on) and I came to a decision.

One of the difficulties is translating the control scheme to the PC as the console gamepad has the two joysticks that are both used to control the ship in Geometry Wars. As of earlier today, I was using a combination of the mouse and the keyboard (nearly Quake-style controls). You "dragged" the ship around with the mouse and turned where it was facing using the A and D keys. After trying it out for a while (and going back to play Geometry Wars), I realized that it felt unnatural and was not very intuitive. I have changed it to flying the ship forward using the W key, and flying backwards using the S key (full-blow Quake-style control scheme now).

With this change I realized that I needed zero mouse support for my game, so I had the pleasure of ripping all that code out (have I mentioned the sick twisted pleasure I get ripping code out of a code base?). It wasn't much code to rip out, but it still gave me a pleasure :). I saw in an earlier posts of Chris that he was considering support a Gamepad. That is a fabulous idea and I might need to steal the idea (Chris, you want to check out XInput now, I believe, not Direct Input). Heck, I have an extra 360 controller lying around from Microsoft Meltdown so I might just have to put it to use here. I will save that until the end though because I don't want to get hung up on a feature that is only "a nice to have" and not "a must have".

I had talked about it earlier, and after much internal debate, I have decided to re-introduce the messaging and tasking system. However, I am only re-introducing a much simplified model. It won't be nearly as complex or as feature complete as I am only going to add the bare necessities this time around. Once those are finished, I will change my ship to fire continuously like Geometry Wars (rather than based on an input command). Hrmph, even as I'm typing this I'm still having an internal debate about whether to go forward with this. Perhaps that is a sign that I still haven't quite decided yet and the back of my brain wants to work some additional things out. Oh well! I'm not going to let that hold me up from making more progress. Back to coding.....

::code, code, code, code::

::two hours later::

Sidetracked!! I ended up re-working my keyboard handling since I wasn't happy with it (it was quite *hackish*). That is all fixed, and I did some "cleanup on aisle 7"-style refactorings (nothing too big). I went ahead and converted the ship controls to be completely keyboard driven. It feels a lot better, but it's still not as comfortable as I would like it. It will work for now though.

Tomorrow I will probably whip up a quick Vector2D class (if I was using DirectX, I could just use the one that is built in). I will move all location/velocity values over to be Vector2D rather than PointF (I'm really getting tired of this ".X"/".Y" crap everywhere rather than using simple Vector-based math). Once I get that in place, I might go ahead and add a "slowdown" feature of controlling the ship where it will slow down after you let up the key rather than stopping right away.

My hope is that once I get some of these architectural issues settled, hooking up enemies, collision detection, scoring, etc. should be pretty easy. At least the technical aspect should be easy, there would still be the fun part of writing the AI :). So far, I'm making progress though.

My goal for tomorrow is to have the Messaging and Task subsystems hooked in and working by the end of the day. I would also like to get the GameObjectRepository hooked up and doing some rudimentary boundary checking (like destroying game objects (like bullets) when they leave the playing area). Once the GameObjectRepository is working, adding some easy collision detection (I probably won't do per-pixel at this time and will settle simply for bounding volume checking) shouldn't take that long.

Anyways, time for sleep :).

P.S. Minor Annoyance #2 with VCS Express - The limited debugging features. Visual Studio's debugging capabilities in the IDE seem much more robust (like forcing the code execution to a specific line (aka "going back in time")), etc.

 #       Comments [3]
# Tuesday, May 23, 2006

Although I didn't give an update yesterday, I did get some work done. Even though I've had the last several days off of work, I'm sure Chris would feel more comfortable knowing that I haven't been spending my entire days working on Spaceballs (I have a feeling that Chris would only feel truly comfortable if I dropped out of the competition since he knows he's fighting a losing battle).

My spaceship is all hooked up and working. It drives off the mouse and can rotate both directions just fine. I just finished hooking up the bullets. Now you can hit the spacebar to fire and the bullet will fly in whatever direction the ship is/was facing.

To limit the sheer number of bullets (and to add another game mechanic), I went ahead and added a firing rate to the ship (or, more specifically, the weapon). If I have the time to implement three different ships like I want to, each one will have a different firing rate to differentiate the behavior and strategies for each different ship type.

Before I move on to hooking up an enemy and getting collision detection working, I need to do some cleanup refactoring. I also need to do some "bulking up" of my infrastructure to make sure that the game continues to be easy to develop.

After I had removed it earlier, I'm thinking of re-introducing the messaging system since I don't like how coupled my various classes are getting. I'm holding off on that now though as I really don't want to push it too far if it isn't necessary. I figure that I'll actually just continue to push forward and if my coupling becomes worse, then I will revisit the topic. There might be other ways though that I can manage the dependencies and coupling without introducing an entire message system. I'll have to do some more thinking on that.

Well, I'm back off to coding. I'll try to get in another update before I go to bed tonight (hence the "Part 1" in the title :)). I'll feel a lot better about the progress in the game once I get an enemy and collision detection hooked up. I know it's only Day 6, but once an enemy and collision detection is hooked up, I'll be a heck of a lot closer to having an entire tracer bullet hooked up.

 #       Comments [2]
# Monday, May 22, 2006

Yay for GDI+ :). To create a rudimentary Sprite class (and we are talking *rudimentary* here) and hook in Rotation using a Matrix Transformation took less than 45 minutes (and most of that was cleanup refactoring and moving files around in SVN).

Now I'm very glad I dropped SDL.NET like a bad habit and moved over to GDI+. If you are doing 2d game programming in .NET, I do think that you might as well go the GDI+ route and just forget about SDL.NET (at least for the graphics). With all the powerful code and classes in the .NET Framework (and how ironed out that code has become), you will be experience a lot less frustration, *trust me*.

I look at yesterday's update and I kind of have to laugh. No wonder Chris thought I was crazy :). After my change in direction, I myself am starting to realize just how easy this is (granted, it is just GDI+ and is no Gears of War :)).

If I could offer one piece of advice to any budding hobbyist developers out there, it would be to not put the cart in front of the horse. Don't try to do your first game directly against DirectX. While it is certainly possible, I think you would only cause your self grief in the long run. Now that there are great higher-level libraries at our disposal, there is no excuse to use them while you are just getting started in game programming.

I'm only glad that I came to this realization/decision now instead of 30 days from now.

Oh, and if you _are_ a new guy on the scene of game development and are curious about all this GDI+ stuff I am talking about, I _strongly_ encourage you to look at the games you can find on Coding4Fun as part of the UpgradeYourGame Sweepstakes (basically Pong, Space Invaders, and a small RPG). And while you're at it, drop Andy "ZBuffer" Dunn a quick thank you over at The ZBuffer for the work he did putting those together.

 #       Comments [0]

Well, SDL.NET is completely ripped out. Spaceballs is running entirely on GDI+. Believe it or not, I ended up ripping out the entire Messaging system as well. I'm not entirely sure that it is really even needed for this game. In fact, I think it probably _is_ quite overkill.

It's funny, I always get a tingle when ripping out a bunch of code and making the code a lot simpler. I'm still happy as the components are pretty isolated and are still enabled to be unit tested fairly easily.

I think that tomorrow I will crank out a quick and dirty Sprite class built directly on a Bitmap and use that for rendering. I only hope that the rotation capabilities of that or significantly better than that of SDL.NET. Once the Sprite class is built, I will hook up the ship into my PlayController. After that, on to one small enemy :).

As for Visual C# Express, I have noticed a couple of things. For one, I wish there were more refactorings than Rename and ExtractMethod. Also, I do wish they would have kept the add-in capabilities enabled. While Jamie Cansdale has done a wonderful job getting TestDriven.NET to work, I have had no end of trouble trying to get "Test With... Debugger" working. Arg!!! It's frustrating enough that I do wish I was in Visual Studio. But that may also be because I like to have my unit tests, darn it :).

At least after all of this I am only a single day behind schedule. Hopefully I don't run into this again. One thing I have noticed after todays efforts? I'm pleasantly surprised to see how easy GDI+ programming is.

As much as I feel ashamed to admit it, I've _never_ written a C# game using GDI+. I've always jumped to Managed DirectX (or some pre-packaged library like Irrlicht) and only gotten a fraction into the game development process. I'm starting to get the impression that now that I've chosen GDI+, this whole process should go a bit smoother. My other hope is that this will ultimately make the code a lot more accessible to others out there as a lot of the necessary support architecture that one has to put in place with Managed DirectX is not there.

I'm glad that at this point I'm still having fun. We'll see if that's still true in a week :). 

 #       Comments [0]
# Sunday, May 21, 2006

After chatting with Chris earlier today, and browsing both the Coding4Fun and UpgradeYourGame sites, I have come to the conclusion that I'm over-complicating things here. Like Chris, I want to be able to encourage everyone and show that anyone can do this. With my last post, I fear I have violated this principle of encouragement.

This decision isn't only because of others though. I've been fighting with the rotation capabilities of SDL.NET today (or rather, the lack of decent ones), and am currently quite frustrated. I don't want to fight over this. And with the 40 day deadline approaching, I don't necessarily want to fight getting it up to speed and working in Managed DirectX. If I've learned anything from work, it is the importance of managing scope.

In the hope of managing scope, I have decided to take a stab to see if GDI+ (like the samples on Coding4Fun) will be sufficient for me. I'm assuming that due to the fact that the game I'm working on is a simple 2d game, GDI+ should do just the trick for me.

I'm also hoping that by using GDI+, it will help appeal to the hobbyist developers out there wanting to "get into" hobbyist game development using the free tools now at our disposal.

Besides, if GDI+ doesn't get in my way too much than I should be able to spend my time working on the game mechanics, game features, and the code architecture of the entire project. In the future, I can always "upgrade" this to Managed DirectX (maybe after XNA Framework has been released).

Back to work.

 #       Comments [0]
# Saturday, May 20, 2006

Okay, let's chat a bit about class design and the pattern I will be using in Spaceballs. I will be using an in-memory, message-driven architecture. Messages will be the nervous system of the game engine. Nearly all communication will take place through messages. The "brain" of this nervous system is the MessageProcessor.

The MessageProcessor is responsible for broadcasting a message to all listeners that are interested in listening to that type of message. But how does the MessageProcessor know which listeners to send a message to? A listener is registered with the MessageProcessor for a specific type of message. Currently, this act of registration is done by the MessageConfigurator. Eventually, the MessageConfigurator could be driven by an external XML file. However, in the mean time, this is done in code within the MessageConfigurator.

The goal to this system is that a Message would have numerous listeners (IMessageHandler) associated with it. For example, if we are talking about a PlayerDamagedMessage, we would have our GameLogic listening to it as well as our PlayerView. The GameLogic would take the PlayerDamagedMessage and update the player's health and send out any more messages necessary. The PlayerView on the other hand might play a damage sound, add some particle effects around the player, and update the Health meter to reflect the new health level of the player.

Let's look at the relationships between these classes.

As you can see from this picture, the SystemController handles the three main messages we have defined that are at the core of our game loop. We will see later what this communication looks like in action.

Let's talk about the other area that drives this system, Services:

Hm, there that *Configurator thing again. I have to admit something: I "stole" the Configurator idea from open source projects out there like log4net. This isolates the act of configuring an object to one class. This way, the object can be configured using different sources, like code or XML. The ServiceConfigurator above configures the ServiceLocator with all the various service types and instances that the engine will be using.

All services registered with the ServiceLocator are driven off of interfaces. To configure the two services above, the ServiceConfigurator might look like the following:

ServiceLocator.Register(typeof(IStateService), typeof(GameStateService));
ServiceLocator.Register(typeof(IGraphicsService), typeof(SdlGraphicsService));

Then a message handler can use the graphics service like so:

IGraphicsService svc = (IGraphicsService)ServiceLocator.GetService(typeof(IGraphicsService));
svc.BeginScene(Color.Black);

One of the advantages of having message handlers retrieve services using this pattern is that unit testing becomes easier. I could just as easily register a mock service that implements IGraphicsService with the ServiceLocator. Then I could do assertions on the mock asserting that the message handler is behaving as expected under certain situations. Basically, this is a round about way of doing dependency injection (rather than using Constructor injection of Property injection).

As you can see, there are currently two services in the game. This number will most likely increase throughout the course of development on Spaceballs (i.e. the introduction of various services: GameObjectRepositoryService, ScriptingService, etc.). First, we have our IGraphicsService. This service is essentially a Facade around the graphics system. You will find methods like BeginScene, EndScene, WindowCaption, etc. in this interface. SdlGraphicsService is an implementation of IGraphicsService that is an SDL-specific implementation of IGraphicsService.

The next service is the IStateService. This is the main component in the state machine that ultimately controls the flow of the game. You will find methods like OnUpdate(timeElapsed), ChangeState(IState), etc. in this interface. Let's see some of the core states that are stubbed out in Spaceballs:

I think they are pretty self explanatory. I may go into a breakdown of a flow between all the states in a later update.

Well, that's basically the gist of our services/state layer as it exists today. Nothing too complicated here. Now let's see how messages and services work together, shall we?

To use this architecture to drive our game loop, there are essentially three core messages we will be dealing with (that were outlined above): PreProcessFrameMessage, ProcessFrameMessage, and PostProcessFrameMessage.

So, that's the core of our engine. Although it may seem like overkill at first, it will help us manage the dependencies in the future and enable us to easily add new features.

Do I have any updates on the use of Visual C# Express. Not really. In this case, no news is good news. The IDE has not gotten in my way one time which makes me a happy camper. Of course I miss the Class Designer but you have to have _some_ features that are limited to Visual Studio to encourage people to upgrade :).

Until next time, I'm off to continue implementing my various services (starting with the PlayState). Catch ya' on the flip side :).

 #       Comments [0]

Contact

Email Me Send mail to the author(s)

Calendar

<May 2006>
SunMonTueWedThuFriSat
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910

About this site

Jason Olson's thoughts on Programming, Games, Music and Life in General

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2008
Jason Olson

Sign In
All Content © 2008, Jason Olson
Theme based on 'Business' created by Christoph De Baene (delarou)