Well, I didn't think I was going to be able to make much progress on the game until next week (since I'm going to be gone all weekend), but I was able to get in some coding time tonight that I wasn't expecting. And you know what? I'm glad I did :).
My tracer bullet is completely finished now (take that George, :P) :).
Tonight I wrapped up the High Score system and made it persistent using simple XML serialization to the game's own folder under the Application Data directory. The High Score screen is displaying the results and the Recap screen will congratulate you if you have achieved a new high score.
So, all the major "required" features are done and checked off the check list. That means that what is left is making it look good, adding more enemies, tuning game play mechanics, etc. This is one feeling that I love about implementing tracer bullets: once you finish the tracer bullet, you realize that a large portion of your system is fully operational and ready to be added onto.
So, now I'm on to simply making it fun. Not bad for Day 14. I still have roughly 28 days to finish the game (giving me some wiggle room, just in case). I'm fairly confident I will have quite a fully-featured game by that time considering that I have twice as long left than I've already spent on it.
Yee haw :).
Perhaps I will take some time next to do some performance profiling and getting my framerate back up since it has dipped to under 100 fps. Although, on second though, I won't worry about that until it dips under 60 fps since it won't be noticeable 'til then anyways.
Soooooo, I guess I'm on to adding some new enemies, weapons, power-ups, and the like. Sweet! Here's where the real fun begins :).
Well, since Sir Georgio decided to give me some crap about losing focus, I figured I would post about what I've been doing.
The MVC work is all finished, cleaned up, refactored, and ready to drop a bunch of new types of enemies into the game. Before I did that though, I decided to clean up the graphics a bit.
One of the first tasks was to implement a "playing field" that play would take place on. Before, play was just the whole screen which wasn't very conducive for HUD-like UI (like Score, Lives, etc.). The playing field is now implemented and operational.
I still think it is important for me to hook up the High Score system before plugging in new enemies. Once the high score system is fully implemented (shouldn't take that long), my tracer bullet will actually be entirely complete and functional. Then I can move on to beautify-ing the application and adding some more gameplay elements.
Here's a new screenshot of how it looks now. Still not stellar, but a definite improvement over my last post (and yes, I made the Sprites myself (although any artists out there can probably tell that fact already)).
The tracer bullet is basically all finished now. I have enemies being spawned on a regular basis, the scoreboard is operational, the "Recap" screen is working. The only thing that is not implemented yet is the High Score system and screen. Of course, currently there is only one "type" of enemy and the game stays at an even pace and never "accelerates" to make it harder.
Obviously, there is a lot more work to do. I'm just happy to be at a point where the game is basically entirely functional now. That makes me happy :).
Tomorrow night will probably be spent doing some cleanup and refactoring to make up for today's coding session(s). Once I hook up the High Score system, I will need to add some different types of enemies and add some increased pacing to the game. I will probably also have to tweak the game flow a bit (ship speed, bullet speed, enemy speed, etc.).
Now, to show how truly pathetic I am at art, and to show off my extreme programmer art, I present this screenshot. Just remember that to this point, I am _not_ worrying about graphics. I am worrying about gameplay and functionality. Perhaps posting this screenshot will really make Chris and George think that I will definitely lose :).
I noticed that in Chris's "latest post", he is merely talking about what technologies he will use, what the game will be, etc. Chris, I'm going to give you a little tip. If you want to win the contest, you have to WRITE SOME DAMN CODE! It's ironic that at the start of your project, you were trash talking me about how I wouldn't get anything done. Where are you now? Huh? For goodness sakes, a guy who has never written a game is further along than you :P. I'm just curious, how does that feel?
Although, I must fully admit, I want to see some updates from Chris on writing code as I want to be able to steal any ideas if necessary to guarantee my victory over him :) (I could care less about winning the 360 as long as I beat Chris (and George, for that matter :))). I also like reading about people's progress on their games as I think the "behind the scenes" aspect is one of the best things you get with blogging.
So, get to blogging tattoo boy :P.
On a different note: George and Rick, you are still in the Portland area right? If so, we should geek out on developing our games together some time :).
Okay, just one last update before I head off and hit the sack. I was able to get the Wall game object written. I also just wrapped up my CollisionDetectionService so I have collision detection working in my game now. For now, the collision detection is rather rudimentary. It just uses bounding boxes along with the RectangleF.Intersects() method in the .NET Framework to do bounding volume collision detection. Pretty simple, but pretty effective (I may not even have to change it for the rest of the project).
I'm liking how the collision detection reads. I'll have to show that at a later time though (maybe in my retrospective?). I'm also storing a "cache" of collisions so you don't see "Ball1 collided with Wall1" and "Wall1 collided with Ball1" as two separate collisions. All my game objects derive from a common GameObject base class which has an ID property that is generated by producing a new Guid. So, the "cache key" that I'm using is basically xor'ing the hashcode of both objects' Guids together. Once again, pretty simple.
My one concern with the collision detection algorithm now is that it is brute force (checking every object against every other game object). Since this game is a simple 2D game that may not grow that complex in regards to the number of game objects, I'm hoping this algorithm will continue to work. If not, I'll look at moving the game object repository to storing by quadtree or something like that to better cut down on the number of collision checks that I'm having to do.
With this progress, I'm thinking that I can spend Friday night and Saturday working on plugging in some enemies (e.g. the Spaceballs that will gives the game its name), getting the scoreboard working, and perhaps getting health on the ship working as well. All in all, I'm happy with where I am. I'm well on my way to getting a functional tracer bullet up and running in a week or so. Then I can start working on polishing the game up (aka making the game look pretty and be fun).
Good night, all!
Luckily, I was able hit most of my goals for the day. I still have yet to get to collision detection, but that's not that big of a deal as I can whip that up sometime on Friday night or Saturday. I have my ship automatically firing now according to a firing rate and have all controls working through the messaging system. The architecture is starting to shape up a bit and I can see that it is going well.
Next is to add one enemy and get collision detection working. After that is when the fun really starts. I then get to start hooking up the ship's health, number of lives, the scoreboard, various different enemies, etc. Basically, all the fun stuff :).
Perhaps I will post a picture here soon. Just be aware that it is suffering from programmer art something FIERCE. Of course, for the first half of the project, my focus won't be on looks, it will be on gameplay. I want to get the tracer bullet in place as soon as possible.
Back to coding for now :).
::code, code, code, code::
::some time later::
More updates. I got some boundary checking finished. The code now checks if bullets have left the field of play. If they have, they are immediately removed from the game. I don't like the way it feels though. I'm thinking of implementing a Wall game object. This way, there will be four Walls that comprise the "field of play". If I go this route, than I can use normal collision detection for boundary checking as well. Basically, if a bullet collides with a wall, remove it from play. Also, if a ship collides with a wall, don't let it go any further. I will feel more comfortable when all this code is using the same collision detection algorithm rather than numerous "special cases". This could also open up some interesting game mechanics (like having a non-rectangular field of play or adding obstructions in the middle of the field of play, etc.).
So after that last coding session, I am exactly where I wanted to be by the end of tonight (and I still have another hour of coding left :)). Maybe I will move on now to writing up the Wall object I talked about above. If I can crank that out real quick-like, I will whip up a CollisionDetectionService that will be used to detect collisions. Then the SpaceballsGame class can determine what collision interactions it needs to deal with (like Bullet -> Wall, Ship -> Wall, etc.).
If I can get all that finished tonight, I will be ahead of where I was hoping to be at this point in the project (although perhaps not, since I won't have any coding time on Thursday Night, Sunday, or Monday :(). The good news would be that almost everything would be in place to start dropping in enemies and getting them going :).
Until next time, I'll see you on the flip side :).
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.
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.
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.
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 :).
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.
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 :).
Seeing that George is so willing to be open about his plans and progress, I've decided to follow you suit. After all, this should make it more enjoyable for you readers out there (is there anybody out there?). So, on to a progress report, shall we?
In order to help manage the scope of this project due to the time frame, I have decided that Spaceballs will be a 2d game instead of 3d. This should simplify many aspects of the coding by minimizing the sheer amount of code that needs to be written. The other thing that I am doing to help manage the scope is that I'm not writing my own "engine" code from scratch. That's right, you won't see a lick of Managed DirectX or OpenGL code out there (which some of you may find shocking).
So, if no Managed DirectX or OpenGL, what am I using? I'm actually using the .NET wrapper for SDL. Since I won't have to write much graphics or input code, I should be able to spend more time focusing on the game features and game play.
In the vein of controlling scope (aka preventing scope creep), there are several features that I was getting around to implementing in Tanks that I have decided to axe in Spaceballs. Mainly, I will not be writing a virtual in-game Console, and I won't be doing saved games or game replays.
To help me get from start to finish sooner, I have decided to adopt the "Tracer Bullet" paradigm from The Pragmatic Programmer. I will get my game fully functional through and through (with very few features) and then I will improve on that over time. As of tonight, I have actually made progress in this regard.
Where do I stand tonight? I have my MessageProcessor (the "nervous system" of the game) completed and hooked up. I have also created my GraphicsService and StateService classes and completed the ServiceLocator that will be able to lookup and retrieve these services at runtime. I will go into this pattern in a future post and explain how it will also make unit testing the game quite easy (well, at least easier than what it would be using other means).
I also have all my main game states (MenuState/PlayState/RecapState/HighScoreState) hooked up to the StateService. Not only that, but I have the keyboard handling working and pumping into the StateService. Currently, you can use keys to navigate through every state of the game. The "instructions" for how to navigate are printed on each state and state transitions are handled when the correct keys are pressed. I'm thinking that this weekend I'll probably add a ShipSelectionState and DirectionsState.
Sooooooo, to make a long story short, I have my "framework" set up and a good start to a tracer bullet working. Everything is also logging as expected by using log4net.
Sometime this weekend I will try to make a longer post on the patterns I am using to establish the architecture of my game code. If done properly, this should definitely easy the development process while cranking this game out the door. Until then, I'll see you all next time :).
P.S. I now officially have this coming Monday-Wednesday off of work (PTO), so expect me to make a serious push to getting this sucker playable :P.
Well, it looks like Tattoo-Boy is back to his old tricks. With all the time he is spending on writing comics (don't quit your day job, buddy), it's obvious that he needs some help to get going in this project. In that vein, I have put together this project plan that he can use to help him "compete" in this contest (and by "compete", I mean write useless code while thinking that you stand any chance to beat the Almighty George of the Jungle):
Day 1: Buy book "Learn to Program VB in 21 Days"
Day 2-25: Read book (<-- Notice the extra days, that helps give some padding because of the slower mental processes due to the amount of absorbed tattoo ink over the years (I've been meaning to ask you Chris, can you get through a metal detector at the airport with out it going off?))
Day 26-28: Write Hello World application
Day 29: Try to figure out why Hello world application is not working
Day 30-37: Learn the intricacies of Console.WriteLine and design some ASCII art for game
Day 38: Have main character (aka "@" symbol) respond to keyboard events and move around the screen
Day 39-40: Create a dragon that has "AI" that doesn't respond to any input
Day 41: Get game compiling
Day 42: Submit partially functional game, with partially working code, with Trash Talking posts as blogging progress, and with pretty colors to make game "fun"
Day 43: Proclaim self winner
Day 44: Lose
Now, on the other hand, here is what George and I will be doing (or have already done):
Day 1: Open up IDE, immediately ensuring victory over Chris
Chris, if it makes you fell any better, I'm sure you could beat several monkeys if they entered the contest (okay, that might stretching it a bit, how 'bout dogs?).
Okay, I'm taking a bit of a break from the trash talking for this post. I have to say one thing: I'm really excited about how this game development contest is shaping up. It looks like George is off to a great start. I read through his design document and if he can complete his game, I think that I for one will definitely enjoy it and that he would stand a good chance at winning that 360. I really love reading about other people writing games and I have a feeling that there is going to be no shortage of that in the next 40+ days.
Another thing that excites me is that, if this continues, it might be able to bring some good attention to leveraging .NET as a hobbyist game developer since you can do it for completely free now.
Anyways, sorry for the diversion. Back to the trash talking and game programming :).
I just happened to have the television on while writing my winning entry in the GWB gaming contest and the Andy Milonakis Show just came on. OMG. WTF?!?!?! Is this actually a show? And why am I still watching? OMG, LMAO, ROFL. I can't believe this show. It just keeps getting better and better.
Okay, I'm just speechless. What is up with this rapping? How old is this kid? OMG. I can't take my eyes off the screen, I'm transfixed. This is nuts. It's utterly crap but it's utterly funny. "Pork fat in my Sippy Cup"???????? Okay, I'm..... just...... shocked. And why am I laughing?!?!?!?!?
Not much to report today. I had some family engagements so I was only able to spend 20 minutes or so on the game. I did get a new repository on my Subversion server created and a bare-bones project imported into it. I have the simple "Hello World" app per usual. Tomorrow evening I'll really get started on the sucker :).
Why Spaceballs? Well, I was feeling frisky and, frankly, _maybe_ just a tad bit drunk (those of you who know me may laugh now). I also wanted to give a bit of an homage (as we learned (that's Learn-Ed) people call it) to the great Mel Brooks, simply by the name though since the game has absolutely nothing to do with the movie by the same name.
This game that I'm creating for the GWB game coding contest is inspired by the XBox-great Geometry Wars Evolved. There are some changes I'm making though to hopefully give it a little BAM-WHIZ-BANG flavor to it. I'll go into those features at a later date though.
My renewed impressions of Visual C# Express? After being used to using Visual Studio 2005, it is truly striking just how much of the same functionality the Express Editions truly have. So far, I have yet to truly miss a single feature. With the work that Jamie Cansdale has done getting the TestDriven.NET add-in working with the Express Editions, I have nearly everything I need.
The one feature I kind of miss? The Class designer. To tell you the truth, it was basically the only reason I upgraded to Visual Studio 2005 for my hobby projects at home. However, at the time, it was simply because I wanted to start using the feature. In practice, I realized that I don't actually use that feature that much (at least not yet). I kind of expect to go along and not experience too many holes of missing features in the Express Editions for the hobbyist development I'm doing (which is great since they are now officially free forever).
I suppose I'll see you all next time around when I have a bit more information to share with you. Until then, I need to do some thinking about a project plan and how long I have to get a functional prototype so I can start messing around with actual gameplay. Mmmmmmm, gameplay!
Well, it turns out that someone is wanting to make a go of this game programming challenge for GWB. If I recall, the contest rules dictate that part of the winning total also comes from blogging your progress. I have one thing to say to Mr. Maximus in that regards: "You're In Deep Horsey Doo-Doo!!". I fully expect that Chris will be able to "step away from the methodology buffet and actually produce something that works" as he puts it (speaking of producing, how's that next release of HA! coming, monkey boy?), but as for writing about it? Ha, that's a funny one!
You see, the advantage I have is that I can actually write well and be understood. Sure, Chris looks pretty cool with all his "tattoos" and such, but there are proven side-effects from having so much ink in your blood (and by "proven", I mean that I'm like totally making this crap up). One of the medically known side effects is that you can't write code worth crap. It's true! It's proven medical fact! I have a strong feeling that on June 29th, he's still going to be trying to figure out why his code won't compile :). (Hey Chris, here's a hint, it's probably because you're trying to compile VB code in C# Express :P).
"GAME ONNNNNNNNNN!!!"
Looks like I have a reason now to get my butt in gear with game programming: http://geekswithblogs.net/jjulian/archive/2006/05/17/78737.aspx. I'm going to enter the contest. However, to make it fair, I'm going to start with a fresh code base since I've been working on my game for a bit (and I would _hope_ that Chris does the same thing and doesn't submit HA!).
Now for the debate, which game to base the game play on.... hmmmmm....
So, in the meantime, expect to see a new series of updates. I'll have it be a series with a title like "A game in 45 days - the journal" or something silly like that. You won't see any "Tanks" updates for now since I will be doing the game development journal instead.
Fun, fun, fun. I highly doubt I'll win, but it's worth a shot. My goal is to do this with high quality code to. I want my code to follow good coding standards. I want mine to be the highest unit tested, best architecture, etc. Now's the time to get started :).
After talking last night about integrating a collaboration pattern I was working on at work with a coworker, I have decided to go a different route. I stubbed out the framework tonight for a Microkernel that will drive the game engine. The current version as it exists tonight is very simplistic. The only current functionality in this Microkernel is the ability to add a Task for per-frame processing.
This new Microkernel should help decouple my system a bit more and make it easier to enhance. For instance, instead of your "usual" game loop where you might actually see direct calls to game objects to update themselves, in this system you basically see one call to the TaskMaster within the Microkernel instead. So, if I have a GameStateManager and GraphicsDriver that both need to be updated once per frame, they would register tasks with the Microkernel. This means that when I am "boot-strapping" the game, I essentially am hooking up the components into the TaskMaster. In the case above, you would see something like "taskMaster.Attach(new CallbackTask(gameStateManager.OnUpdate));" and "taskMaster.Attach(new CallbackTask(graphicsDriver.OnUpdate));".
Where this tasking system really starts to shine is when you start doing animations. For instance, if I am implementing a 3-second respawn feature into my game, I can create a special task like "new WaitTask(TimeSpan.FromSeconds(3));" and then attach a SpawnTask as a child task to the WaitTask (so that it is automatically called when the wait time has elapsed). That's just one minor example. There's a whole slew of other examples if we go into the GUI world.
Eventually this TaskMaster will grow and probably have the ability to do "time sharing". I'm thinking of adding that feature in the future so that I can time slice the Tank AI since the AI will be implemented in scripts by the end user (yes, you programmers). This will ensure that a Tank doesn't hog too much time when updating itself and should ensure that every tank is on a level playing field when it comes to processing time.
Tomorrow I will probably start on a MessageProcessor to the Microkernel that will enable cross-sub-system communication within the engine. After that, the Microkernel will probably be done for a while. I might eventually expand the Microkernel to support a virtual file system as well for game files, but I don't want to put the cart in front of the horse here. The more I think about, the more I feel that this is almost like implementing a mini-OS in software that is specialized to running a game. Pretty fun stuff.
There are some other things I've been thinking about though. I've been thinking about introducing a service layer that would host services that would be stateful and would basically drive the underlying functionality in the engine. You might see a GraphicsService, a ScriptingService, a PersistenceService, a GameObjectService, etc. Then the various Message handlers would communicate with a ServiceLocator to get references to the different services in order to do their deeds. This pattern is an adaptation of the pattern I've said that I'm working on at work so hopefully being inspired by that won't take too long :). The ServiceLocator does seem to be quite Spring'ish after a while, but that should be fine. Heck, if I eventually want to power it off of Castle or Spring.NET I could do so if I choose to.
Anyways, off to bed for the night. As usual, I'll keep you updated on the latest happenings in the development of Tanks :). 'Til thenz, my friendz.
In light of my recent purchase of a 360, I know that many of you out there thought that I would drop off the face of the planet for a while. Well, too bad, I'm back (well, still here actually). I've asked my wife to help me with my nearly-half-year-just-bought-a-360-and-don't-want-to-drop-off-the-face-of-the-planet resolution. This resolution is that I won't play the 360 during the week (or at least limit to one night or two), and that weekends are free game (no pun intended, of course). This should help me at least get _some_ work done on my other hobbies (like this game). So now that you know that, it's time for an update :).
I've decided to make one fairly major change. My first stab at this game will actually be in 2d. Now before all of you start yelling, there is a good reason for this. Frankly, I want to get to the game programming stuff that interests me: game playbacks, saved games, AI, programmable bots using a scripting language like Boo, etc. The quickest way to get there is to "prototype" the game using 2d. My goal is to code the game in such a way that I can "upgrade" the game to 3d at a later date.
In that vein, I have downloaded SDL.NET and am changing the application framework as it exists right now to use that. My hope is that I can finish this conversion by tomorrow evening and then be on my way again. That is at least my short-term goal for tonight and tomorrow night.
After that, I will be integrating a collaboration/eventing pattern that a coworker started putting together at work. I have started working on it myself and helping move the development of it forward and I am really loving it. It is not far from the event-driven pattern I was using in the Boom! engine before. My goal is to have that integrated and unit tested by sometime early next week. I would shoot for earlier (because it won't be too much work) but I have some prior engagements that will keep me busy several nights this week/weekend.
Anyways, back to work :).
I am now XBox 360 bound :D. It was one hellish of an experience getting one (that, and an HDTV). I called around to at least six different GameStops and EBGames in the Portland area. Not a single one had a single 360 in stock (hell, at this point in time, I was willing to buy just a core system and buy the various pieces in the bundle even though I would be spending more money in the long run). At this point, I'm thinking that Microsoft must be _SOOOO_ rich that they don't even want my money in the first place. Luckily, the last GameStop I called said they didn't have any but they were sure some of the stores in Vancouver (the 'Couv as we yokels call it) did. The first GameStop I called in Vancouver had a couple of the Bundles, just what I was looking for! Yay!
So, off I go. I stop at the GameStop in da 'couv, pick up my 360 and then I'm on my way to Best Buy to pick up an HDTV (after all, isn't it sort of pointless to spend the cash on a 360 if you don't have an HDTV to run it on? (I mean, why push all those pixels and amazing graphics if you can't truly experience them, right?)). We (my wife and I) ended up buying a 27" slimfit so it would fit in our car and existing television cabinet at home (plus, anything larger than 27-29" is really too big for the size of room we have it in). I even found a great price on one that supported both 720p and 1080i so I don't have to worry about all that mumbo-jumbo (at least I think, but I'm sure there are others out there that could "educate" me on the situation and show that I still have a lot to worry about (like "native resolution/display", etc. but _whatever_)).
Now just to get the bad boy home. And that's when it starts. We get the tv out to the car and..... it doesn't fit. Boy am I feeling like a jack-arse at this point. So, we call up the good ol' father-in-law since he has a full size car. Luckily, he was footloose and could come help us out. So, we're sitting out in the parking lot with our tv sitting behind our car while he is on his way. Then it starts raining. GREAT. So, I rush back in and grab a cart, rush back out, put the tv on the cart, and haul it back inside. Whew! That was a close one.
My father-in-law then arrives on the scene. We go to put the tv in the trunk, doesn't fit. Crap! We go to put it in the back seat, doesn't fit. CRAP CRAP! Buuuutttt, it _almost_ fit in the back seat. With a bit of coaxing and box "reshaping" we were able to get it in the back seat. At this point, I'm utterly ecstatic since I'm close to getting my new toys home and I get to be in bless for an hour or so before some friends show up for dinner plans that we had made earlier.
I get home, take out the tv and go to place the tv in the entertainment center: doesn't fit! Crap, the opening for the tv is about two inches two small to accept the new television. Well, time to do some cabinet modding ::grins::. Since the entertainment center is one of those cheap Sauder-like cabinets, I have no qualms about doing some exploratory surgery on it. I go ahead and unscrew the top off and whack out _everything_ in the middle (the divider down the middle between the component shelves and the tv as well as all the shelves themselves). With how the tv is shaped, I can fit my components just behind the front of the tv and off to the side. Sweet! Everything fits now. On to the 360 :).
So, I take everything out, hook it all up and decide to clean up after myself since we have company coming over. After throwing all my trash away, I plug in the control and sit back on the couch (ready to have my socks knocked off). Then as soon as my first game boots up, DING DONG, guests are here. Damn! So close. We spent most of the evening with our friends so by the time they left, I was exhausted and had to go to bed in order to get some sleep for work today.
I can't tell you just how tempting it was to stay home from work today to give my 360 some much needed love. But seeing as my mommy didn't raise no fool, I know where my paycheck comes from (the thing that enabled me to get a 360 in the first place, I might add). So, here I am sitting at work doing "my thang" while my 360 sits at home gathering dust. Luckily I came into work quite early today so I can leave work quite early :). Then, it will be all-out 360 gaming bliss :D.
I suppose now that Rory has posted about it, the secret is out. Yes, I am _indeed_ a Crazy Man. This last Saturday, I was at Rory's most of the day shooting my part for a new video he is doing (I won't get into any more detail than that though, as my lips are sealed). However, what should really confuse people about this new "project", is the following video Rory has released on his blog: http://neopoleon.com/blog/posts/18742.aspx.
I'm guessing Rory just got a crash course in just how silly I can be since that scene was shot on the spot as I got into "costume". Here's where you all can feel sorry for my wife since this is how I just behave sometimes when I'm in my "silly moods" (which is more often than you might think).
Anyways, I can only imagine what y'all are going to think. All I will say is that I can't wait until the "new project" is officially released as I think y'all will enjoy it :).
P.S. This is also the reason (as well as another post coming up) that no progress was made on Tanks lately. More on that later.
I kind of touched on this issue in my last Tanks update. Thomas was nice enough to leave a comment and a follow up post that he made. I went to leave a comment on his blog in response to his post but "anonymous" comments aren't allowed and, frankly, I don't want to sign up for an iBlogger account simply so I can leave a comment. So, with that said, I'm just going to post my response here.
------
When writing unit tests, I no longer really think about methods. What I have started to think about is a behavior or responsibility of the class under test (which is _really_ done if you're doing TDD). If this test involves testing multiple methods so be it. Then if the behavior changes, you only have to change a small amount of tests.
I also believe that thinking about behavior when testing encourages developers to think about the "Single Responsibility Principle". If you're focusing on behavior and the test is hard to write, there is a good chance that the behavior of your class is too convoluted or complicated to test well. Or if the test becomes very long, it is likely that the responsibilities imposed on the class are too great.
In my opinion, developers need to get used to thinking about the "test matrix" for the class under test and focusing on code coverage. The number of "edge cases" can be minimized by using a Design By Contract approach to ensure the state of the class is always in an expected state. This way you don't have to have a separate test case for everything under the sun (fail fast, fail often). So, if I can get full coverage of a behavior by simpling expanding the scope of one test (like sending more commands/events through the system), than I will do that and get higher test coverage using a single test.
Of course you always have to be conscious of striking that balance between a test that gets a lot of code coverage done versus a test that is hard to read because it is too large and convoluted itself.
However, my opinion is still morphing on this subject the more unit testing I do. My only concrete rule of thumb is that if you start testing the abilities of the framework itself, you've dug too deep (like setting a property and asserting the value is what you expect it to be). A lot of the scenarios that test the behavior of the framework itself can be covered by "side effect" where other tests would fail if the framework every changes the way it behaves (but how likely is that?).
Anyone have any strong thoughts or opinions on the subject of unit testing granularity? When is it too granular, when is it not granular enough? Where do you draw the line?
Great. If it wasn't bad enough being sick still, my internet connection just had to be down all evening. Luckily, it _just_ came back up so I can actually post this update. So let's discuss the progress on Tanks, shall we?
Most of my "free time" I've had lately (which hasn't been much with me being sick (since my body proclaimed several hours at a time to be "nappy time")) I've spent writing the unit tests around the last couple of classes I ported over from my previous project. The process has made me appreciate the work Microsoft has put into Visual Studio 2005. Having the integrated Code Coverage reports is pretty nice. I know you can get that with NCover/NCoverExplorer, it's just nice to have it "out of the box". You add to that all the amazing work that Jamie Cansdale has put into the TestDriven.NET add-in and it makes for a wonderful environment to be writing unit tests in :). I don't know why, but I get a certain thrill out of writing some unit tests and then seeing my code coverage increase.
The ConsoleModel class is finally wrapped up in unit tests and tucked in to bed for the night. What kind of surprised me is that by writing the unit tests I wanted to write against the ConsoleModel class, it just so happened that I got full coverage on my ConsoleEntryLine class as well (which is used by the ConsoleModel class). Killing two birds with one stone is nice sometimes :). For my Tanks.exe, I'm up to 67% test coverage. That number is a little misleading though as I have all my unit tests within the executable itself. If I don't count my "Test" namespace and only count the core "ManagedWorld.Tanks" namespace, I'm actually sitting around 51% test coverage (right around where I thought I would be at this time).
The problem I have right now is the rest of the code currently in the code base (or about to join the code base), is all device specific around the IrrlichtDevice. I don't really want to unit test down to that level as the ROI would start to decline dramatically with the time I would have to invest simply writing the unit tests. However, that doesn't mean I don't want it tested. I'm thinking that sooner or later I'll work on introducing a script-based testing framework for the application. Then I'll write a harness that can be run from NUnit. My hope currently is that the NullDriver for the IrrlichtDevice will still be fully functional under the hood but simply won't be driving the graphics card. If that is the case, then I should be able to write this script-based testing framework (not that it won't be without it's hardships). Then I can use the scripts as more of an "acceptance tests" system that will help me test from the UI level. Of course, my hope is that if I can do that via the NUnit custom harness, then it will be able to be reflected in my code coverage reports alongside of all my unit tests. I still feel like this is quite a ways into the future from now though (meaning, I won't worry about it until I cross that bridge since there's no shortage of tasks to be done in the meantime).
I have a confession though: I'm trying to not get too granular with my unit testing. I know some people have strong opinions on what level of granularity to unit test. For me, it just seems "wrong" to have one separate unit test per method in a class. I can't really put my thumb on why I feel that way yet. But having one test fixture per class, and one unit test per method (or I've seen even smaller in the past (meaning multiple unit tests per method)) just seems like it is missing the boat. By the time you get this detailed, it seems like you begin testing the functionality of the .NET Framework rather than focusing on the behavior of your class under test.
I've even started to think that maybe focusing on testing one class at a time might be too granular as well, but the jury's still out on that one :). If you can test all the nooks and crannies of your class at the module level, than why not do so as the unit tests can become much more clear to read (since they start asserting behaviors of the module as a whole). Enough of my ruminations for one post. I'm still largely a unit testing newbie, so I won't bore you with my not-yet-mature stream of consciousness.
So, what next? I believe I'll crank out the ConsoleController and test that. Once that is finished, it is on to the ConsoleView. I'm still not sure how I'm going to test that (if I'm going to test it at all). Once that is done, however, the Model/View/Controller for the Console will be finished and will be ready to integrate into the game. Maybe then I can "call it good" for this stage of the game and get started on replacing those articles that I never finished a LONG TIME AGO (although _not_ in a galaxy far far away (contrary to popular belief)).
Catch you on the flip side, space men :P. (I was going to say "filthy pig dogs" but I thought that some of you might get offended if you don't know where it comes from).
Late night inspiration! Sometimes I really love these kinds of moments. This one came to me as I was trying to get to sleep (and apparently my brain didn't want to let the problem go :)). One of the problems I discussed in an earlier update was that, for some reason, the Irrlicht .NET wrapper decided to implement all "interfaces" (ISceneManager, etc.) as classes, some of them not even containing default constructors. The heart burn this caused is that I'm not able to Mock and Unit Test my master TanksApplication class unless I go through all the trouble of taking all the Irrlicht "interfaces" and wrapping up my own interface-based facades around them. For this type of project, I didn't really want to go through all that hassle.
I guess something my brain saw during all my effort of getting Blender-exported .x files to work came to the forefront. Basically, I remember seeing when starting up the Irrlicht MeshViewer application that Irrlicht has actually implemented a "NullDriver" along with the other drivers (like Direct3D9, OpenGL, etc.). I tried it out in my application and it's pretty cool. It basically is a fully functional IrrlichtDevice but doesn't drive the graphics card. This will enable me to create a mock object that I can pass in and drive the TanksApplication with (by having the mock class be driven by the NullDriver and returning the actual Irrlicht classes rather than mocks themselves).
The "so-and-so" aspect of this is it's not necessarily a "true" mock object, but heck, it will work so that makes me happy right there. The other unfortunate side effect is that the unit tests in question will be tied to Irrlicht as well but that should be alright as making this application graphics-platform-independent is out of scope :).
I really get a kick out of some of these "a ha" moments :).
In other news, I have finished the unit tests around the GameEventParser class. All in all, I have increased code coverage from a dismal and depressing 15% to around 35% (still quite low, but a lot better than 15%). By the time I wrap the Console class up in unit tests (and the TanksApplication class after my late night realization above), I should be sitting above 50% which will put my mind more at ease with the state of the code base.
Now I'm back to trying to get to sleep (if my mind lets me), so I will chat with all y'all l8r (had to get at least one hackish expression in there ::grins::)
Peace out!
You know, it's interesting what kind of stuff you can find on the Microsoft Careers site (thanks for the link Joystiq). Direct Physics? Now that sounds interesting. If current market trends are any indication (like Ageia's PhysX Processor), this could be an interesting piece of news. Of course, with the fact that DirectPlay, DirectInput, DirectDraw, and others have all been deprecated or removed, it's interesting to think that Microsoft might be revamping DirectX by bringing in other technologies to it. With all the clues making it seem like Direct3D was the only viable DirectX-based technology left in the fray, I can't help but have my interest piqued by this job posting. And of course, with all the XNA Framework going on, I'm curious how this might fit into that as well. Regardless, I have a feeling that no matter what happens, we are going to hear exciting game development news out of the big M in the coming year or two.
I haven't been able to do much lately because I've been fighting off a cold (to the point where I've had to take time off from work (which I _hate_ doing)).
There hasn't been much progress writing code as I've been busy playing around with Blender. I've been working through tutorials and such to get up to speed with it (so that I can at least put _some_ of my own models in the game (no matter how crappy they may be)). The verdict so far? I like it. When working through tutorials, it really isn't that difficult to learn how to use and is a pretty powerful tool (let alone the fact that it is _free_ which I always love :)).
It hasn't been without its problems though. Mainly, .x file export is borked for me. I have tried using Blender 241 with Ben Omari's Exporter for 241, I've tried rolling back to 237 and using Mindbender's export script, I've messed with every exporter option in the book, and still no luck :(. I've used practically every tip and trick that I can find on the web dealing with this. You see, the problem isn't so much with the .x file, it is when I try to use the .x file in Irrlicht.
The problem is that the model is oriented wrong. When I load it in the DirectX Mesh Viewer, it looks exactly like it does in Blender. However, when I load it up in Irrlicht the orientation is all FUBAR. I understand the difference between the two coordinate systems (as Blender uses a different coordinate system than DirectX and Irrlicht do), and the exporters I use have options to "transform" the model. The steps I still have left to try: 1) install python 2.4 and make sure my PythonPath variable is set (perhaps parts of the export script aren't functional in Blender because of this), 2) rollback from Irrlicht 1.0 to the version I was using before, and 3) trying to fix the exporter script myself (after all, it is just Python code). For now though, I'm putting it on the back burner as I have many other things to do.
So, my foray into modeling, while fun, did contain its own share of hardships. Well it's not like I don't have enough code to write anyways, so I'll just go back to doing what I know I can do :).
I still need to wire up the unit tests for the GameEventParser (basically, "parses" GameEvents from a plain text string (serialization/deserialization)), and the ConsoleModel/ConsoleEntryLine. Usually I would write the unit tests before or with the functionality I'm writing but these classes were ports from a prior project, hence the lack of unit tests. And I'm determined to fix that this time around (you know what I just realized? I certainly use the phrase "this time around" a lot; man, time to get some more phrases to use :P).
I'll probably start coding up the unit tests tonight but won't finish them until tomorrow night or Wednesday evening. Because I have to work during the week (aka "A Day Job"), I probably won't get much done in the evenings. I'm planning that most time spent working on this project will likely be on the weekends. In other words, don't expect too many Tanks updates during the week.
Until next time, remember, don't wait up for me and I'll see you on the flip side :).
|