OgreDotNet was recently pointed out to me by a friend and co-worker. I don't know have I missed it in the past, but I see it's there now which is the important part :). With the lack of mature, open-source 3d graphics engines for managed code out there right now*, I'm glad to see this come to fruition.
Since Ogre3d is already object-oriented, you can't tell from the code of OgreDotNet that it is simply a set of bindings down into the C++ libraries of Ogre3d :). Not only that, but it appears the forum is fairly active and alive (and that's the OgreDotNet forum I'm talking about (since the regular ol' Ogre forum is _very_ much alive)).
In the future (aka after I finish Spaceballs and perhaps another game or two), I will probably end up using this for my first 3d game I do (and possibly all the other 3d games I do after that). I really want to just break down and start playing around with it now, but I'm sure my competition in this contest would like for me to do exactly that. SOOOO, perhaps once Spaceballs is finished I can start playing around OgreDotNet.
Until then, make sure you check it out :).
http://www.ogre3d.org/wiki/index.php/OgreDotNet
* Axiom priorly being sucked up into RealmForge (I know the source forge project has started up again, but it _just_ started up again seriously, in my opinion), RealmForge now being "deprecated" of sorts, and the other options like Irrlicht.NET and Haddd not being as mature and supported as Ogre (again, just my opinion)
I didn't quite get around to implementing the lives functionality tonight. However, I did do some general cleanup and "paved the road" for me to easily drop in the code for respawning and multiple lives tomorrow.
One of the refactorings I did was to take what I was calling "States" before and change them to "Screens". Really, they were screens. As I needed to start adding states to the gameplay itself (like PlayingState, LostLifeState, etc.), I didn't want to go down the road of making a hierarchical state manager because I felt it would muddle up what was really being done under the hood. I felt that separating out Screens from States would lead to a much more clean implementation.
Rather than states being things like MenuState, PlayState, RecapState, and HighScoreState, those are now MenuScreen, PlayScreen, RecapScreen, and HighScoreScreen. In my mind, that makes it much more clear what they are actually doing. States are now concepts like ReadyToPlayState, PlayingState, LostLifeState, PowerUpState, GameOverState, etc. Once again, I am happy about this change as I am really liking the separation between "Screens" and "States" rather than hacking both concepts into one. The code is not only cleaner, but it will also be much more clear where the functionality I'm about to implement goes. For instance, the multiple lives functionality will simply be transitions from PlayingState to LostLifeState and back to PlayingState. If I add the "countdown" at the beginning of the game (think "Starting in 3... 2... 1.... GO!"), it will simply be starting with ReadyToPlayState and transitioning to PlayingState when appropriate. This will also help break out the code into more manageable chunks as well (which I always like).
On an aside, I think I use Source Control much more than I originally thought. It's only day 20, and I'm already up to revision 61 in SVN (61 commits). Better safe than sorry, I suppose :).
I still don't have any comments to make on Visual C# Express. I still haven't really noticed the difference all that much for my hobbyist development. Anyone out there that wants to get into C# development should _totally_ download Visual C# Express and use that. Besides, you can't beat the price of FREE :). The one thing that I can say is that, in my opinion, the Express products are better than the other free IDEs that are out there today. Usually, you get what you pay for (meaning free can suck tremendously), but not with the Express editions.
That's it for this update. For tomorrow night, I'm going to shoot for implementing multiple lives (a.k.a. LostLifeState) and hopefully get around to implementing the ReadyToPlayState as well to add the countdown to play time. Those shouldn't take too long (hence the reason I'm hoping I can get both of them done tomorrow night). Until then, I'll see you on the flip side :).
Not much functionality change tonight. Nope, tonight was mostly bug squashing night.
The first bug I squashed was around spawn point generation. Sometimes, a spawn point would be generated that would cause a Spaceball to be spawned within a wall. This was due to the spawn point generation algorithm not taking into account the size of the entity is was generating a spawn point for. That was an easy fix :).
The next bug I squashed was around the ball-reflection logic I had to bounce Spaceballs off of the walls when they hit. Unfortunately, it didn't take into account whether the code had already flipped the velocity vector based on a prior collision with the wall (i.e. a collision from the frame before (meaning, it is _still_ stuck in the same wall since not enough time has passed to clear the wall)). This was causing Spaceballs to become "caught" in a wall or to pass right through it. This was also an easy fix. I basically added logic to not only check for the collision, but to also check whether the Spaceball was still headed in the "wrong" direction before correcting its velocity.
The last thing I implemented was more around missing code. When implementing the game loop originally, I had forgot to add the ability for a game to be "paused". This meant that if the form lost focus (like navigating away to a different window), that the game would still run in the background. Oops :). That was also an easy fix, so it behaves properly.
Fixing the game pausing functionality exposed another bug, though (don't you love when that happens?). My EnemyEmitter class that was spawning new enemies on a frequent basis was checking a DateTime field from the last time it spawned to DateTime.Now to verify whether it needed to spawn a new enemy. This meant that the second a new enemy was spawned, I could make the window lose focus, wait several seconds, give the window focus again and a new enemy was spawned right away. Bad Jason! I should know not to check against *real world* elapsed time. I changed the code to record how much time had elapsed *in game* since the last spawn (by adding up the elapsed time through each "Update" call to the Emitter) and Poof! Bug fixed :). Once again, easy fix.
That's about it for tonight. Hopefully tomorrow night I can implement the lives system (i.e. giving you three lives rather than the game being over the first time you get hit). I was really hoping to do that tonight, but I guess it just wasn't in the cards :). Once I do that (which will include some refactoring to add "spawning" of ships themselves and fixing an annoying spawning issue I currently have), I will truly move on to implementing some of the various other Spaceballs I have in mind. Then the true fun begins (not that it hasn't been fun up to this point :)).
Well, I was able to squeeze in _some_ coding time last night and this morning. The update to Managed DirectX is all finished. It's kind of nice to see FPS should up from 90 fps to around 550 :).
All in all, it took about three hours to upgrade from GDI+ to Managed DirectX. Boy am I glad that I wrote the infrastructure the way I did. After a quick refactoring (making it so the IGraphicsService implementation rendered the Sprite rather than the Sprite itself), all I had to do was implement a new Direct3dGraphicsService and change the ServiceLocator to use an instance of that instead of the GdiGraphicsService it was using before. Viola! I'm now in Managed DirectX land. I love when to make a change like that, all you have to do is add another class rather than comprehensively changing your existing code.
Unfortunately, I'm still at the hotel in Seattle so I can't commit my changes to my Subversion repository yet (boy does that feel weird; I guess I'm used to committing often when I make small functional changes).
Now I believe I'm in a position to sustain for the long haul (as in, the system can grow to handle a particle engine and the like rather than having to find clever ways around the fact that GDI+ is not hardware accelerated).
So, what are the next steps?
1) Resolve a bug around Spaceball creation (sometimes the Spaceballs are created in the walls). This should be easy as it is simply limited the spawn area by the dimensions of the Spaceball being created.
2) Add "lives" to game. You will start out with three lives and the game will be over when you have no lives yet (currently, you only really have one life). I will probably re-implement my TaskMaster here to handle delayed spawning.
3) Create "invisible time" for two seconds when a new Spaceball is spawned. Currently, if a Spaceball just happens to spawn where you are: BLAMO! Game over. Just a little annoying, to say the least. I want to fix this.
Once those are done, I figure I will either "beautify" the Menu screen, or I will start adding in more enemies and gameplay mechanics (like Ship power-ups and such). Currently, I'm leaning towards adding some more gameplay mechanics as I would rather get those down and fleshed out before making the various screens look good (which I can always do at the end). Basically, I want to prevent myself from spending so much time make it look pretty that the gameplay suffers.
DirectX Rant #1 - The errors. They're horrible. If I accidentally try to Draw a Sprite before calling Begin(), please just tell me that "Begin must be called first" or something like that. Whoever thought that "<INSERT MAGIC NUMBER HERE> D3DERR_INVALIDCALL" is a useful error should be SHOT on sight.
Visual C# Express Thoughts - I agree with George, here. In this case, no news is good news. I work with Visual Studio at work and the fact is that I have hardly noticed that I'm _not_ working with it at home. The only difference for me is that I'm missing ReSharper, but that is _only_ because I've been too lazy to install it yet :). You gotta love a quality IDE that doesn't get in your way and has so much functionality to it!
I was recently contacted by Allan Hoffman (the "tech jobs expert" for Monster.com) about some quick thoughts and tips I had on how to have a successful technical blog (which alone is a shock to me as I wouldn't even start to think of my blog as "successful", but to each his own I suppose :)). I thought I would reprint my response here (with permission, of course). I hope you enjoy :).
Obviously, these are just my opinions so you can take them with a grain of salt if you wish (at your own peril, I might add :P). Feel free to add your own as well. I know many of other more capable bloggers have already talked about this, so I'm merely sharing my own experiences as a blog reader myself.
--------
What are the ingredients for a good technical blog? In my opinion, the recipe is pretty simple: accurate technical information + personality + reliability (at least semi-frequent posts) = good technical blog. I have certainly suffered from time to time on the reliability aspect. And I believe that at certain points in the history of my blog, infrequent posting has actually caused me to lose readers. Personality is an aspect that I still am feeling my way through. At times I feel I become too personal and lack the amount of technical information that people desire. At other times, I had tried to be so technical that my personality had stopped showing through. It's definitely a balancing act.
Here are some quick tips that I could think of:
Tip A / B. Have Something To Say / Be Unique. It seems like nearly everyone has a blog these days. Even in the technical world there seems to be an over-abundance of blogs that exist now. There is an incredible amount of noise that exists that people have to sort through in order to get to the juicy stuff. Let's face it, you want to have one of the blogs that gets noticed. You don't want to simply be adding to the noise. In this vein, make sure that you have something to say. A quick way to get a reader to hit the "unsubscribe" button is to write many "check out this link" posts. And whatever you do, don't simply post to apologize for not posting. With how much noise that exists out there in the "blogosphere", if you're not adding signal, you're out of my aggregator.
Another way to add signal? Be unique. Even if you're not always technical, there is a good reason that blogs like http://www.neopoleon.com are becoming extremely popular (dare I say, near cult-like). If you are unique, you give your readers the opportunity to look past some of your shortcomings (and face it, we all have them). Not only that, but maybe you'll make people laugh in the process (which is always a good thing in my book).
Tip C. Blog About Something You Enjoy. You have to enjoy what you are blogging about, it's as simple as that. If you don't, it will feel forced and your readers will notice. If you would like people to enjoy reading your blog, you should enjoy writing it! When reading blogs I believe people don't want to feel like they are reading a text book. Which leads to Tip D.
Tip D. Let Your Personality Show. One of the major advantages of blogs is that they can be a uniquely personal communication medium. When reading your blog, let people know who you are. I've noticed recently that the majority of blogs in my RSS aggregator are from people who let their personality show. I enjoy the fact that while reading a person's blog I get the unique opportunity of getting to know them a little bit. So, remember to be yourself while blogging.
I haven't done any coding recently as I've been getting ready for the gig I just had tonight in Seattle. I'm now checked in to the (crappy) hotel (the room is about as big as my left thigh). Luckily, they have wireless, so I'm able to at least give this update.
I realized yesterday that to take this game where I want to take it, I really need to upgrade to Managed DirectX to leverage the hardware acceleration (especially once I get into implementing my particle engine/system). So, as soon as I get back, I will be upgrading the game from GDI+ to Managed DirectX. Luckily, this conversion shouldn't take too long as I simply need to add a new Direct3dGraphicsService class and change my application to use that.
Actually, that's not entirely true. I also need to change some of my game logic. This is because GDI+ expects the origin to be in the upper left corner, while the way I will be setting up my camera in MDX will expect the origin to be in the _lower_ left corner. That should be pretty easy to fix though.
Perhaps if I really start using MDX, it will allow Andy to start giving some blogging love to it :) (don't forget Andy that George is also using Managed DirectX for the contest).
Anyways, back to reading the AI book I picked up the other day.
You may not get another Spaceballs update until Monday or Tuesday night. Sorry :).
|