Monday, July 26, 2010

Three Projects... Four Projects... Five Projects!?!

Yes, well (conservatively) counting what I'm up to at RIM. The project I'm wrapping up is a particularly fun and rewarding one, creating a tool for providing detailed code coverage tracking for the various testing efforts within the OS Group. Sadly, the details aren't all that exciting. Mostly it's just processing gobs of similar data into an easily queried form. The majority of the work is in the logistics of collecting the data in a way that doesn't interfere with testing and manages to collect as much information is possible given the limitations of the testing environment. My other project(s) relate to some internal OS Group initiatives. I could tell you about them, but then I'd have to kill you ;)

So that's two...ish. Where's the other three? Well...

  1. Space Combat Sim
    Yup, that thing is still going. Adding bots, improving the graphics, cleaning the code up and generally learning as much about 3D networked games as possible.
  2. A shmup game developed from scratch for XNA on X-Box 360 and PC.
    Something simple for building a strong C# codebase that I can port to other projects. Goals here are making a programmable effects system and some decent GUI widgets.
  3. Another shmup, using FlatRedBall
    Why? Because screw you! That's why... Actually I figured I'd just start messing around with plugging tools together just since that's normally not the way I make games.

Actually, to go on a boring long monologue...

I have finished only a few game projects, mainly for school. That tends to be because I approach the subject by first building tools and such, then building the game using them. I end up having so much fun making the tools that the project devolves into adding new features and refining code that I lose focus on making the game. Then I get bored and start a new project.

Now, I'm a tools developer professionally I can finally spend all hours of the working day making all sorts of exciting tools for a moderately hardcore development environment. This means that I'm not getting quite the same buzz from making yet more tools at home. So... time to make some fugging games!

Later d00dz! I'll try to keep the interval to next post to less than a month this time.

Thursday, June 24, 2010

Some Inspiration

Lately I've been getting most of my coding jollies from my job as a tools developer at RIM. Mostly Python with a nice dose of C, SQL, and other stuff. Mainly fixing some reporting systems that go to external reports seen by management. Plus a dash of code janatorial work since nobody else seemed to be available/willing. After eight months doing solo work it's very nice to be working with a team again.

Anyway, that's not actually what I wanted to talk about. Today's just a shorty (I have a longer rant about myself coming later.) TIGSource recently posted a couple montages of a huge collection of free, indie games. I've played a few of them (Fraxy, Cave Story, Cho Ren Sha 68k, Prototype 2, Warning Forever, Clean Asia and one or two I can't recall... yea I'm a SHMUP fan) Holy hell there's some awesomeness.

Check it out!

Saturday, May 22, 2010

So, What Now?

Well, today I spent a TON of time writing up blogs that I've been meaning to finish for a long time now. Three of them in fact! The first on exporting from Blender to XNA, the second on how the demos for Space Combat Sim went, and the third is a postmortem. But, I haven't talked about what I'm doing now, have I?

The short answer is that I have a job. In fact, I started my job before my "good demo" which was on May 4th. I'm working as a testing tools developer for Research in Motion. Unless you've been living under a rock for the past few years you've probably heard of their flagship product. Before I started this blog I worked as an intern for RIM over a period of 16 months. I work for the Operating Systems group which is responsible for all of the hardware drivers etc. that make the BlackBerry phone work. The culture of the OS Group, relaxed, friendly and fairly close knit, is what motivated me to return to RIM after finishing school. I'm quite happy working somewhere that I can spend the day working on hard technical problems with minimal political friction then finish the day by hanging around the pub.

My job now is to maintain and improve tools for automatically testing the Blackberry OS. Obviously I can't go into specific but I will be able to come out with articles on scripting, automation, testing and testing tools in a general sense. On top of the occasional post about work I'll still continue my game development work which means, of coure, more posts on Space Combat Sim and other projects as well.

Cheers.

Monday, May 10, 2010

Space Combat Sim Postmortem

In the spirit of continually learning I'm going to do a postmortem of Space Combat Sim as a school project. Don't worry though, this doesn't mean the project is dead. But the priority now is on having fun with it again, instead of busting my ass getting it demo-ready.

I'm basing my postmortem on those typically found on Gamasutra. If you haven't read one do so, they're quite eye-opening.

What Went Right
1. Tight, focused scope
Game projects can be massively complex. Particularly when they're 3d action-oriented online ones :). Most of my early projects started out relatively simply but grew into complex behemoths due to "wouldn't it be cool if" syndrome. For example a simple game where you killed enemies before they could leave the screen evolved into a vertical shmup with procedurally generated levels.

For Space Combat Sim the scope was set in stone from the beginning. The project would be a multiplayer game combining elements of X-Wing, Quake 3 and Counterstrike. Tools were only to be developed for the game if they were absolutely necessary (ignoring content pipeline extensions only two tools were made, one for creating hit boxes and one for creating effects.)

With the scope in hand I was able to set out a series of broad goals which defined how the game was to be built from the ground up. These broad goals were converted into a 24 page document describing all of the required features of the game (required for the course.) That was then turned into the detailed list of tasks that needed to be done to produce the game. Making the game was then simply a matter of finishing all of the tasks on the list. Since all time was spent exclusively on those broad goals the amount of wasted effort was minimized.

2. Continuous integration
Continuous integration means always having a working version of a project while it's being built. There may be missing features, and if it's a game it may look and play like crap, but it at least exists. One thing that always happens with software projects is scheduling issues. Feature creep, scope creep, unanticipated challenges or whatever, eventually something will cause a project to go off course. Having a working version means that even if the deadling is looming at least something is there for everyone to see.

In the case of Space Combat Sim, a lot could go wrong. I was challenging myself technically since I hadn't produced a 3D game before, nor had I produced a multiplayer game before. Except for a few occasions I succeeded in this goal. This was very helpful in keeping me from being too ambitious in coding features and forced me to break down overly lofty goals into more doable tasks.

3. Scrum-like scheduling
Space Combat Sim used a barebones version of Scrum, albeit with each cycle of development being much longer than specified. By dividing the project into sprints and assigning a set of real deliverables to be completed in each I was able to keep on task. The faculty's imposed limit of about 8 hours per deliverable also helped keep tasks from meandering and getting out of control.

What Went Wrong
1. Not enough time spent getting tools
The first four or five months of development time were spent building up the back-end code needed to support the first network session. A huge amount of that could have been saved if I spent that first month just looking at rendering engines and playing with them. No more shader development, effect tool development, etc. etc. in all about two months of work there. Sure, I'd still have to spend time on managing game objects and networking but that was kinda the point of the game. Instead I gave up after about two weeks of looking at tools, honestly, because it was boring.

2. Working solo
Especially in combination with making my own tools working solo made the game take a painfully long time to get done. It would have been quite nice if I could have focused more on object management, networking and gameplay while someone else took care of UI, loading, and other backend stuff. With only myself I generally had to focus on every task of game development which tended to result in polish getting short shrift.

The game's code is poorly documented in places, hacks abound and not all of the visuals that I wanted are in the game.

3. Continuous integration
Continuous integration has proven to be a double-edged sword. On one hand, having a working copy of Space Combat Sim all the time was motivating and helped reduce the impact of schedule slippage. On the other hand it made me midjudge whether a particular piece of the game's architecture was actually done or not. The area where this resulted in the most wasted time was in the game's startup sequence. The issue was that, while the game did indeed have space for its menus and loading sequence it wasn't really set up with its final usage in mind.

Having something that works, and having something that works correctly are different things. Continuous integration overall has been very useful, but at the same time it can cause one to do something that is expedient and fast rather than the correct solution suitable for the remainder of the project.

Conclusion
Overall I'd consider Space Combat Sim a modest success. I met my basic goal, which was to produce a multi-player combat game in space. My more lofty goals of having mission-oriented combat, style etc. weren't met due to time pressures though. The experience has definately been worth while and I learned a lot about actual project development through it.

Wednesday, May 5, 2010

Bad Demo, Good Demo

So, here's the final update about Space Combat Sim as a school project. I'll follow up with a postmortem and a bit about what I'm doing in the future.

Bad Demo
The first presentation was to faculty and some industry representatives (fortunately their thing seemed to be anything but games.) It was originally going to be in a classroom setting but moved to the lounge in the student life center due to the number of people attending. The lounge, which happened to have one, maybe two, network ports. Both which were in use by other equipment... sigh. Without being able to play with someone all I could do was crash into scenery. Not much of a demo.

I was able to re-show the project in a lab, with a proper network, but the damage was done. My kingdom for Fraps... and the time (and people) to use it effectively. The fact I didn't have a fallback in case of network failure was a pretty major oversight on my part. Still that last minute venue change was really frustrating.

The most frustrating issue though was the fact the most vocal representative was most interested in how a project was supposed to make money. The fact he seemed more impressed about a group wearing suits than their actual project (which was quite slick) was particularly rankling. Why in the fuck are superficial details such as what the presenter is wearing even considered relevant? Caring more about clothing than the product demonstrated is not something to be proud of!

The impression he left me is that I could have run a pre-rendered video (not a recording of the game) and made up some bullshit about online gaming being worth billions and not been called on the fact I didn't even present a product. That would have saved a couple months of effort... At least the other members of the panel were willing to ask some technical questions during all the presentations.

Good Demo
The second demonstration was at the technology program showcase for the college. This was a 3 hour affair where a large number of people in the various technology programs at the school got to show off their projects. This time a lot more time was given to setup, last time there was a token effort in setting up a router which didn't work at all when used for wired networking. The project was set up on two PCs and running with proper Live accounts. There was some pain as some old bugs managed to magically un-fix themselves, and I didn't actually have the passwords for the Live accounts that were set up for the demo, but that got worked out early on.

The big lifesaver was having Heather (from Slime Cat Blog) and her sister to demo playing the game while I could talk about what it was and how it worked. They would fly around, shoot at each other, be silly, laugh and generally have fun. This attracted a lot of attention from the various people attending the showcase. It also nicely showed what the project was without me having to go into crazy amounts of detail describing how it worked. I'm glad they were there because a lot of the people coming to see the project weren't gamers.

By the way, if you're wondering how those photo****d textures turned out; here's a rendering of the three fighter types.


Not great but still decent for about 2-3 hours per ship I think.

Wednesday, April 28, 2010

Imporing blender models to XNA as FBX

This post was meant for release on April 28th. I've been very busy in May and hadn't had much chance to update until now. Sorry.


For Space Combat Sim I've been making game models using Blender. It's powerful, it's free and it's got an active development community churning out new versions regularly. Check it out.


Like most modelling programs Blender uses its own file format for model data. XNA projects can't read these files. You normally can only add .X and .FBX files to games using XNA (though there are ways of adding your own model file importers via content pipeline extensions.) Fortunately Blender provides exporters for both X and FBX. I chose FBX due to the readability of the format and the fact the exporter worked more consistently for me.


Exporting from Blender to XNA created two major issues for me. One was ensuring the right material shaders were used. That was handled by writing a simple custom content processor. I simply named materials using "shader-name" which worked nicely. The second issue was more annoying. Blender uses a different co-ordinate system from XNA.

Huh? All modelling programs express positions using three numbers representing the object's position on three axes called X, Y and Z. Each axis represents one direction an object can move. In XNA, the X axis goes left to right, the Y axis goes from upward and the Z axis goes out from the screen (backward in the game.) In Blender the Z axis goes upward and the Y axis goes into the screen.

The result is that if I export a model and use it in XNA as is, it faces downward. Obviously that's a problem. Fortunately XNA provides a nice simple solution.


Just rotate it!

As you can see here the content processor lets you specify a rotation to be applied to the model before it's used by the game. This takes care of things nicely.

To finish, here's a list of things to watch out for.

  • Scale. If you don't make your models size consistent with each other you'll need to deal with this in the content processor.
  • Shaders. By default the model processor in XNA will assign the model a basic shader to render it. Not much good for fancy lighting effects and such.
  • Orientation. I tended to model my ships facing along the negative Y axis keeping rotation simple. If your models aren't facing straight along an axis importing can be more painful

Wednesday, April 21, 2010

More Spit and Polish

The project demo is in just a few days now. So I'm going crazy with minor bug fixes and polishing to ensure the demo goes well. For example:


  • The game join menu doesn't crash when no games are available

  • The game join menu will poll for new games if none are available

  • Beam weapons now do damage when swept through other ships

  • All incomplete scenarios are have been disabled

  • Fighters have photo****ed textures instead of default test patterns

  • Minor damge model bugs fixed

  • Thrusters flicker slowly enough to be noticable

  • Sound effects fade correctly



Regarding the photo****: One thing I really wanted to do in this game was give the fighters a nice metallic look. Metal is shiny! But, if I add shininess to the game it gets choppy. Ugh. But I might have a solution. Rust! Patina! etc.

I want to avoid making the game a rusty-brown shitefest so I'm hoping to go for more of a tarnished silver/brass/bronze/copper look. If, later, I manage to get some decent shininess at decent speed I'll bring back the metal look I wanted originally.

Saturday, April 17, 2010

bAAAAAAttlezone

The final project for my game development course is roughly done now. Here's a screenshot for postarity.



The real nasty part was integrating physics into a real project for the first time. I used JigLibX at first but it had several problems. The most severe being a poor selection of constraints, no forcefield support built in, buggy/broken body de-activation and poor performance (especially on the X-Box). I ended up fixing the body de-activation by hacking in a simple iteration through all of the bodies in the system to do the deactivation. No, I'm not submitting this as a patch since it circumvents what should be a superior method... eventually. I doubt JigLibX is going to see much work however since I remember seeing a post from its author about the creation/release of a new .NET physics library.

Anyway, I ended up switching to BEPU physics instead. I very strongly reccommend this engine for both its performance, which was quite decent on PC in my project, and its ease of use. I found the integration of BEPU was very simple to carry out and that tasks such as creating composite bodies, constraints etc. was very simple. This is actually somewhat inspiring since I might be able to use this for a future project I've been meaining to do. Sadly, I still have performance issues on the X-Box 360 though the game is playable if I keep the number of objects low.

Spit and Polish

Not much to say about the last couple weeks of work. I've added some new visual effects to Space Combat Sim and completed the three different fighter types. At this point the game is somewhat demonstratable but still kinda unstable and needing significant testing to improve its balance. Here's a screenshot of the new effect I added to the game.



I've been making a lot of small tweaks to the game of late. My primary objective is to be ready for the project presentation which is coming alarmingly soon. After that I need to have an open demo at the school's Tech@Work event. The most noticable changes to the game are the addition of a semi-working server selection screen, and a lobby screen. These aren't all that interesting to talk about but they produced a spectacular number of bugs during development.

The other feature in the game is the menu background. Very minor when compared with stuff I talked about earlier but it has an amazing effect on how complete the game feels. All I did was randomly spawn objects (that look exactly the same as the ships but without all of the movement code) and have them move toward and past the camera.



Much better than plain old CornflowerBlue eh?

Monday, March 22, 2010

Here's that screenshot

A slightly less than pretty picture of more than one person in the game. I just got the first proper ship type added today.


BANZAI!!!1one

Saturday, March 20, 2010

Slightly late. Slightly different.

So I show up to school on Friday, slightly bleary from a late night, ready to get cracking on the testing the game and... pretty much nobody shows up. In fact, those who did show up were far too busy to help out with testing. The screenshots I promised on Thursday were supposed to be from some multiplayer testing but that didn't work out.

Today I added point lights to the game. These are nice for lights which come from a location and affect a specific, limited area. Great for more dramatic explosions, shooting and so on. Here's a pic


Lighting in Space Combat Sim is done using some fairly simple math. One topic covered in high-school geometry was the dot product. The dot product is a scalar product of two vectors. One property of a dot product is that, when it's produced from two unit vectors, its value is equal to the cosine of the angle between the vectors.

Why is that useful? Try shining a flashlight on a marble, or ball bearing, or basketball (anything round will do.) Notice that the brightest parts are those that face the light. As the surface of the ball faces away from the light it darkens. If you remember that old high-school math cosine is one for an angle of zero and zero for an angle of ninety degrees.

Cool. But this still doesn't say how light or dark a surface is... We need one more piece of data. The surface normal. This is a unit vector points straight off of the surface being lit. Let's express the direction of some infinitely far away light source with another vector. Remember what I said in the previous paragraph? The dot product of the two vectors is one if the surface is facing the light perfectly and zero if it isn't facing the light at all. Cool, eh?

This is the shader code for a directional light. It's a nice stand-in for some sunlight. Notice there's a little bit of extra work here so that it can render eight lights at a time.


float4 outputColor = float4(0, 0, 0, 0);
for(int i = 0; i < GlobalLightCount; i++)
{
float LightFactor = dot( GlobalLights[i].Vector, input.WorldNormal );
float4 color = GlobalLights[i].Color * LightFactor;
outputColor += color;
}
outputColor.a = 1;
return saturate( outputColor ) * tex2D( DiffuseSampler, input.TextureCoord );


Now to extend this to point lights.

Point lights are a little different in that they have a definate location and a limited range. Both of these are fairly easy to deal with. Instead of specifying the direction of the light explicitly we calculate it by finding a unit vector that points from the light source to the object being lit. Cake.

The range limitation can also be made quite simple if we don't care about being 100% realistic.
Get distance between the light and the object being lit.
Divide that distance by the radius of the light.
Clamp the value to a range between zero and one
Subtract the value from one

This gives an additional value that we use to adjust the light's intensity based on distance. Here's the resulting HLSL shader code
float3 lightVector = GlobalLights[7].Vector - input.WorldPosition;
float lightDist = length( GlobalLights[7].Vector - input.WorldPosition );
float3 directionToLight = lightVector / lightDist;

// falloff light intensity linearly between alpha*radius and radius
float baseIntensity = 1 - saturate( lightDist / GlobalLights[0].Radius );
float diffuseIntensity = saturate( dot( directionToLight, input.WorldNormal ) );
outputColor += GlobalLights[7].Color * baseIntensity * diffuseIntensity;

outputColor.a = 1;
return saturate( outputColor ) * tex2D( DiffuseSampler, input.TextureCoord );



Thursday, March 18, 2010

First killin's

All this week I've had the chance to test out and refine the network code of Space Combat Sim. I've also managed to get some of the guys from class to play the game and hash out bugs and glitches. Currently I've only been able to run small test sessions with four players but that's been enough to get a flurry of random bugs that needed fixing.

Here's an abridged list of SVN commits I've made since my last blog to give you an idea of the number of fixes and tweaks being done. They're in order from newest (yesterday night) to oldest.

  • Got the game closing down nicely now.
  • Mostly working game exit sequence... still doesn't unload DynamicTextures yet.
  • Precess rotation axes when in strafe mode.
  • Kill beams when its parent dies.
  • Fix wrong thrusters becoming visible.
  • Clean up ALL references to a leaving player (fix crash on join after a player quits)
  • Proper fix for weapon toggle not working on remotes
  • Minor improvement to weapon switching from remote
  • Fix scaling in billboard shader
  • Add state items for targeting, and thrust
  • Recursively update scene nodes as well as entities. (FIXED THE GLITCH)
  • Another attempt to fix off-by-one graphical glitch. Didn't work.
  • Ensure that entities on host will still receive remote input properly.
  • Don't collect input if using a remote controller
  • Implement bandwidth usage tracking and some measures to reduce usage
  • First stab at fixing crash on >2 players at once in game.
  • Fix wrong name in kill news item
  • Fix bug where more than one join attempt would cause a crash
  • Assign gamertag to player slot when initializing on remote.
  • Remember to dequeue pending notifications after sending them.
  • Finish up host side of sending player notifications
  • Implement remote side and part of host side of player notification packet.
  • Don't actively produce score updates unless hosting the game.
  • Fix kill detection bug.
  • First stab at fixing weird off-by-one-frame glitch.
  • Fix stack overflow in resolving entity creations.
  • First stab at queuing creations that arrive out of order.
  • Fix up absurd level of brightness.
  • Fix impossible to see through HUD
  • First shot at multipass lighting. Tested with single light
  • CoalesceDeadEntities called in response to entity destruction packet
  • Add weapon states to data to be sent.
  • Make sure criteria for StateItems being sent are updated.
  • Adjust send criteria to keep bandwidth more sane and keep lag down

After all the pain of February this switch from hacking and designing to steady bug fixing and feature creation is a very welcome change of pace. My most satisfying fix was to finally get rid of a bunch of annoying graphical glitches that occured when players would be killed and/or respawned. Their causes are rather boring so I'm not going to bother with any details.

Screenshots coming tomorrow. I might also talk about how to create a simple radar display.

AAAAAA 'Splosions!

AAAAAAZone is proceeding nicely. The first project milestone is due tomorrow and what's left to do is implementing enemy AI, which is fun, and force feedback on the gamepad.


I'm currently using JigLibX to provide physics and collision detection in the game. This is working quite well right now though the lack of documentation is rather irritating. The biggest issue currently is the amount of jittering that occurs with the tank's suspension. That's going to be a pain to work out but that's for later... What's more important is EXPLOSIONS!


Yes, EXPLOSIONS! the staple of Michael Bay. They're really simple too. What I do is apply a force to any object within a certain distance of the EXPLOSION!'s position. The force gets weaker as the distance from the EXPLOSION! increases. This is great for sending tanks flying around when shooting them.


The other trick is applying blast damage. If an EXPLOSION! force is applied to a tank then the tank will take damage. The more force the more damage. Once enough damage is done all of the tank's parts, wheels, axels, guns and such, are detached from eachother.

Wednesday, March 10, 2010

Space Combat Multiplayer

Debugging network code for XNA is a huge pain in the arse! Typically when I'm bug hunting I'll place a breakpoint where I roughly think a bug is taking effect, look at the state of any relavent data, then step through the code until the bug manifests. This doesn't work in XNA. If you leave one player or the other player in the debugger for more than about ten seconds their network connection will drop. This means that I have to then reset the game and re-join the session. It gets quite frustrating spending an hour on a simple one line logic error with about ten minutes of that hour being spent actually debugging with the rest being hitting a breakpoint, checking variables for a few second and having the connection drop requiring yet another restart.

But it was worth it. After much pain multiplayer is now working. I got to show it off to the prof' this Monday. It's still buggy as hell but man, it's satisfying to be able to finally fly around and shoot other people. Even if getting a kill means crashing the program immidiately afterward.

As promised I'm going to talk about how I've implemented multiplayer so far.

The game uses a basic client/server architecture. Whoever starts the game acts as the server and has final say on stuff like where players are and who scored what kills. All other players are clients and passively receive data from the server. The only data sent to the server by the clients are an initial "I'm ready to receive data" signal and player input. The data sent to the players dictates stuff like what direction they're facing and how fast they're going.

There is a bit of hairyness here however. The client needs to know stuff like what graphics to use to display the game. If you remember my earlier entry on multiplayer, XNA allows a game session to have properties, in the form of integers, associated with it. By associating a particular play scenario with a number the client can find out what to load immidiately by checking the properties of the session he's joining.

The whole sequence of joining an active game goes like this

  • The client player chooses a server to join
  • The server notices the new client and creates an object to track what is to be sent to him
  • The client grabs the scenario number from the server's session properties
  • The client then runs the normal load sequence
  • After loading concludes the client tells the server it's ready to receive data
  • In response, the server sends the client basic information on all players (their score, team, assigned spawn points and so on)
  • At this point the client can begin playing. Normally they're waiting to spawn.

Wait... there's no state data sent yet. In fact, if nothing else were sent the player would see nothing except for some background scenery. The magic occurs in the object the server creates to track the data sent to the client.

Each client tracking object has a list of game entities which matter to the clients. The tracking object allows the server to know stuff like whether the client has been informed that the entity exists (or has ceased to exist) and if any state updates are pending. The server sends entity creation data first, updates second and entity destruction data last. The server can also check for certain combinations (e.g. neither creation nor destruction have been sent but both are pending) to save on bandwidth. In the case of the previous example the server would give up on sending either to the client since creation and destruction effectively cancel eachother out.

State updates are a little more complicated than creation and destruction of entities. These are managed by a class called StateItemCollection. StateItems are objects which describe stuff like an entity's position, movement, damage and so on. When some significant change occurs, say the player suddenly accelerates, the associated StateItem flags that interested players should be notified of the change. The client tracking object queries each entity's StateItemCollection for this flag. If any StateItem's flag is set then the server queues up an update for the client. Once the server has queued the update for all relavent players it clears the flag.

There are a couple advantages to using this flagging method. One is that I can allow the server to choose which players receive the state updates. This allows for the server to throttle itself if it's sending too much data, or to skip sending state data that isn't relavent to a particular player. Other advantages lie in the ability to compensate for lag and in merging updates by having later updates replace earlier updates if neither have been sent.

I'll leave you with this screenshot of one (poorly lit) player shooting grey bullets. Notice I have some (glitched) lighting working now :)

Friday, March 5, 2010

Another Project

I haven't decided how much I'll talk about this one but it is fun. For our Game Development course in my program (Software Engineering at Conestoga College) we have to make a clone of Battlezone using XNA.

The prof has given a decent amount of leeway in the project to have some fun with it. So, finally I have a chance to try out a physics engine without trying to shoehorn it into a partially completed project.

I'll probably just update in shorter posts like this one for Battlezone (for now titled AAAAAA Zone due to a naming theme I've been using for the other projects in the Gamedev course)

Cheers!

Networking Remark

Preview of my next entry:
Debugging network code in XNA Game Studio 3.1 sucks. I spent way more time than I care to think about restarting my game due to stupidity that has nothing to do with actual bugs in the game.

Saturday, February 20, 2010

Particles - Part Deux - The Sequel

The Movie - The Game - The... I'll stop now.

It's been another long hiatus since my last entry where I discussed a bunch of semi-boring crap about how stuff gets loaded in Space Combat Sim. Last week (that is the week ending on the 13th) I worked out the protocol for sending the initial game state from one player to another. That part is running somewhat nicely though I've got a bunch of other broken crap to fix before I can really give the details of what I'm doing.

This week, as you may guess, I'm going to talk about particle effects! Yay! Celebration!!! Peanut butter!

Ahem. Last part I discussed some basic theory on particle effects and had a pretty screenshot from an old project. Now I was hoping to talk about a clever method I had devised for making really versatile effects with relatively little shader code and some HLSL snippets. The idea was to store positional, colour and scaling data in the form of textures. Unfortunately this method turned out to be less than workable.

The idea originated when I was mulling over using cubics, or higher order functions to define the movement and other functions for particles. I figured this would result in a great deal of operations since the function would have to be completely integrated every time a particle gets rendered. At some point I began thinking about such functions in relation to producing complex colour gradients that the particles would run through as they did their thing. I got the idea that if I used a texture I could get a great deal of versatility. By using one texture co-ordinate to represent time and using a random value for the second I could have a particle effect with tens or hundreds of subtly different colour gradients with the hardware doing all of the hard interpolation work practically for free.

After a little more thought I figured this could be applied to particle positioning. Much in the way a normal map texture's colours represent vectors instead of actual colours I could have a texture whose colours represent a position in space. Depending on implementation this might add expense in the form of providing a normal, tangent and binormal to individual points sprites. Lots of floats but makes for very simple math in aiming a particle effect in a particular direction.

So, where did this go wrong? A few places. The first, and biggest, was that doing texture lookups in the vertex shader (which is where effects are applied to points sent to the graphics hardware) is apparently unsupported. If anyone knows a way of doing texture lookups in the vertex shader PLEASE TELL ME. This wasn't enough to prevent me from using the texture to provide fancy colour gradients however. Instead of looking up the colour in the vertex shader I'd simply pass the co-ordinates (time, and a random value) on to the pixel shader. So, it's not a complete loss.

I have yet to implement the gradient texture due to some stupidity on my part (I used a texture co-ordinate at first which the hardware happily interpolated for me utterly destroying my lookup values.) I can probably salvage it by passing the lookup in a colour semantic since those aren't interpolated. For now I am lerping between a randomly selected starting and ending colour.

What I have now is basically a stripped down version of Microsoft's Particle3D sample which I'm mutating into a setup that meets my needs. I'll leave you with a screenshot of my particle effect editor tool to finish.

Monday, February 1, 2010

Loading and Networking

Soo... here's the blog I promised yesterday.

I'm not going to bother too much with background information in this entry. The main purpose of the loading sequence (aside from loading, obviously) is to separate the data needed for the player to set up a game (menu text and such) from the data needed to run the game. It also is meant to separate the initial synchronization sequence for players joining the game from the game's proper so the user need not deal with glitches as much.

In order to simplify content development I made the load sequence as intellegent as possible. When a player chooses a scenario (or a server to join) the game uses a custom content processor to read up data on stuff like team objectives, scoring, spawn points and such. Spawn points are defined such that they always spawn the same type of object. The object type is defined by an entity group type file, the custom content I'm writing about in my Custom Content Processor series, which is referenced in the spawn point. All of the scenario content data is wrapped in a single class.

With the scenario content loaded the game starts the loading sequence. First a function called GetDependentAssets, a member of the scenario content class, is called. This builds a set of all unique assets referenced by the scenario file. This set lives in the aptly named AssetCollection class.

Now, this initial list isn't the whole story. Entity groups in particular depend on other assets to render them in the game world. But I don't need to worry about that before loading assets because of some very simple magic built into the load function for entity Asset instances in AssetCollection. An Asset's Load method has access to the AssetCollection's Add function. If an asset in the collection depends on another asset it simply calls the Add function which will append the dependency to the AssetCollection if it's not already there.

This provides two advantages. First, I can rapidly develop scenarios since I don't have to alter the game's code to ensure all assets referenced by the scenario get loaded, second I have a very clean way of providing feedback to the user of how long the loading sequence will take. As I implied earlier each asset is loaded with an individual Load call. Once the load sequence runs out of assets that require a Load call the basic sequence is done.

Now what?
Well, if this is the player hosting the game we're good to go. Fire up the network session and let the player play. But if the player is joining an existing game the situation is a bit more hirsute.

Why? Because, as a joining player I know nothing about the game other than a few simple properties which can be expressed in a small set of 32 bit signed integers. Obviously this isn't much of use, especially since these properties don't really change after starting a game. (As far as I know anyway) I decided that I'll pack the initial scenario selection and its custom scoring/timing/whatever settings. This is enough for the joining player to run the load sequence above without further communication with the game's host.

After the load though there's a LOT the player needs to know before they can participate in a meaningful manner.
  • What team is the player on
  • Where/when will they spawn and as what
  • Who's on the other team(s)
  • What's the score, how much time is left etc.
  • What objects exist in the game, where are they, what do they look like
  • What objects belong to what players

So, this is where I am now. It's a fun problem to solve and I have a basic protocol thought up but it has yet to be tested. I'll update on it once I've had a chance to test things.

Later doodz

Sunday, January 31, 2010

Don't Worry, I'm Still Here

Sorry about missing last week.
I'm busy as hell working at the final (though it will probably change still at this stage) game startup sequence. I've got things working nicely now and will have a more detailed update soon. The load sequence is somewhat interesting and I think worthy of a couple paragraphs on this humble blog... later.

I'm also busy with revamping, and hopefully near-finalizing, the network protocol for the game. I'm giving particular attention to the sequence of events and data transfers that occurs when a player first joins the game.

If you remember in a previous entry I mentioned how this was the most time-consuming part of an earlier sprint. Given some further (and much briefer thought) I've created a much improved process and am throwing away pretty much all of my old network code in favour of a new solution which should support all of the events that may occur in the final game. All of this I'll write about, in more detail, tomorrow.

Off topic for a second...
I was visiting my parents earlier today for some delicious chicken and potatoes. I also got to see a bit of my brother's new score in gaming. He's picked up a copy of X3: Terran Conflict. This was a game that I've been moderately interested in acquiring myself. Unfortunately I only got to see a bit of a tutorial mission which was mildly, but irritatingly, broken. My brother was piloting an unarmed freight ship but the instructor, inexplicably, was telling him to blow up debris containers despite being unarmed. Needless to say he had to abort the tutorial at this point... going without any remaining information that could have been provided.

I hung around for a few more minutes. What I saw implied a large, freeform game universe. I'm strongly reminded of EVE Online, Freelancer and/or (what I've heard of) Privateer. Sadly, I didn't get to see much more since my brother seemed more interested in reading about bread factories than exploring the world.

However, based on what I've seen I'll definately look to pick up a copy for myself some time. The best part is I don't have to worry about Starforce, SecurROM (sp?) or any other bullshit DRM. I can either get it through Steam or pick up a DRM-free box somewhere. Even if the game turns out to be less cool than I'm thinking it will I'll still be more than happy to support a developer who's willing to not include pseudo-malware in their products.

Saturday, January 16, 2010

Non-Trivial Custom ContentProcessor - Part 3

So today I'm writing another exciting edition on how I built my custom ContentProcessor for loading game objects. If you've just started reading this series you might want to check out the Introduction, Part 1 and Part 2 first.

When I left off in Part 2 I provided a snippet of code to convert an XML document tree into a set of custom class instances which the game can work with easily. These classes describe how to create a group of in-game entities that make up a starship or other object. However the game makes some assumptions about the data these classes contain which can (and must) be verified by the ContentProcessor.

  • The group has a root entity. Its parent entity is undefined
  • There is only one root entity
  • Entities within the group are only related to eachother, not other groups
  • Entity properties are valid (notice valid here isn't defined yet, stay tuned :)

If we don't ensure these assumptions are valid then Space Combat Sim will crash when using the processed content. So, the next step that happens is validation and occurs immidiately after all the repeated process shown in Part 2 is finished.

bool foundParentEntity, foundTopEntity = false;
foreach (Entity entity in Entities)
{
if (entity.ParentName == "")
{
foundTopEntity = true;
continue;
}

foundParentEntity = false;
foreach (Entity parent in Entities)
{
if (parent.Name == entity.ParentName)
{
foundParentEntity = true;
break;
}
}

if (!foundParentEntity)
{
throw new ContentLoadException("Entity " + entity.Name + " references non-existant parent " + entity.ParentName);
}
}

if (!foundTopEntity)
{
throw new ContentLoadException("Group has no top-level (blank parent) entity!");
}

So, what does this mess do? It verifies that two of the four conditions are true. The outer loop's main purpose is to locate and flag that there is one root entity in the group. The inner loop ensures that every entity (besides the root) has a parent. After the loops is a check to verify that the root was indeed found.

Astute readers might notice a bug in the code above. Circular relationships, e.g. entity A is a child of entity B which is a child of entity A, are not prevented by this procedure. There are a couple ways of dealing with this. The simplest, and most evil, would be to recusively search for the root entity from a given entity. This causes a circular relationship to blow the stack and throw an exception. This can be prevented by making the recursive algorithm build a list of each entity visited as we go up toward the root. If an entity appears in the list more than once then a circular relationship exists. There are also non-recursive ways of doing the same thing which I'll leave as an exercize for the reader.

I decided to omit this step from the game since such errors are rare and are caught in the entity creation tool which you can see in my article on collision detection. Currently by crashing horribly, I'll fix that in the future.

Another apparent bug is the lack of testing for non-unique names and for multiple roots. These are both handled earlier. If you remember Part 2 the last part of loading an individual entity block from XML was a call to AddChildEntity.

foreach (Entity entity in Entities)
{
if (entity.ParentName.Length == 0 && parentName.Length == 0)
{
throw new ContentLoadException("Multiple top level (blank parent) entities found!");
}
if (entity.Name == name)
{
throw new ContentLoadException("Multiple instances of " + name + " found!");
}
if (entity.Name.Trim().Length == 0)
{
throw new ContentLoadException("Found nameless/whitespace named entity!");
}
}

The actual adding part has been omitted since it isn't that interesting.

With all of this taken care of we still have one item left to validate. The entity's creation parameters. In fact, I have yet to show you how they're loaded. In fact, this is because the main tradeoff is made for thoroughness of validation versus speed and flexibility of coding is made here.

Entities represent a wide range of object types in the game with wildly different rules. Simple objects include stuff such as hull sections which can do little besides be blown up. Others, such as weapons, are much more complex. Parameters are needed to define stuff like timing, positions, orientations and references to other game data. What's worse is that, at the time I was coding this loader, many properties had yet to be determined, stuff like sound effects and so on.

With all of that in mind I decided to err on the side of flexibility. The loader will accept all parameters and ensure that the XML data is valid for the type that is being used to fill the parameter. It will not check if the parameter is used by the game and also won't check if the parameter's type is what is needed by the game. I'll show you how I implemented this validation without adding an excess of validation code to the game itself in Part 4.

Saturday, January 9, 2010

Particle Systems - Part 1

The Basics

One of the most fundamental visual effects in games is the particle system. At their simplest a particle system is a collection of objects which can each be described with a single vector quantity. Their position.

Even these incredibly simple particles can be moderately versatile producing effects such as clouds, fog, plants and so on. Where particles really shine though is when they're allowed to change appearance over time. The simplest way of doing this is adding one more vector quantity to each particle's description, the particle's velocity. Once each frame we add the particle's velocity to its posision then draw it. This allows particles to simulate simple explosions, fires, smoke, bullets, sparks and so on. As well as clouds, fog and so on...

How? Just change the values that are assigned to position and velocity when the particles are created.

Photobucket

Several simple particle systems. From a previous game project of mine

In this example the blue bullets all launch from the same position but are assigned velocities that cause them to spray outward. The explosions are similar but the velocities point in all directions rather than just to the right. The smoke in the middle appars to drift behind the flame by being created slightly later and given a slower speed. This particular example has a few other variables for particles, namely colour and scale. This saves on art production since a the same clouds can be used for both smoke and fireballs.

For Space Combat Sim

Relatively modern 3D hardware supports drawing particles quickly via what is known as point sprites. Instead of drawing a particle using a billboard, which requires four vertices, each particle only requires one vertex. This is great since we can pump out more particles with less data going between main memory and video memory. However this only gets us as far as drawing the very simple particles I mentioned in the beginning. What's worse is as we add variables to particles we increase the amount of data that needs to be sent to the graphics hardware quite rapidly. This gets even worse when varying a particle's properties over time... at least if we do it all on the CPU.

Besides the CPU computers and game consoles also come with another extremely powerful processor capable of chugging through obscene numbers of operations rapidly, the GPU, on the video hardware. This requires some rethinking of how we do some operations like repositioning particles since programming on a GPU is quite different from a general purpose CPU. The GPU is amazingly fast at doing floating point math and vector operations BUT it adds the caveat that changing input data (i.e. changing the vertices that have been passed from the CPU) isn't feasible. I won't go into a huge explanation why but this will help. The gist of it is that vertices are processed in something like a water pipe. Data can only flow in one direction. You can change it as it flows from one process to another but you can't reverse the flow. (there are ways around this but they're painful and I'm not going to go into them)

So we can't apply velocity to a particle by simply adding to its position repeatedly. What can we do? If you remember your kinematic equations an object's position can be expressed in relation to time with the equasion Pt = P0+V*t

Getting the initial position (P0) of a particle to the GPU is easy since that's simply the vertex position for the point sprite. Getting the time and velocity to the GPU are fairly simple but generally require a bit more thought since this is where the particle systems can be made extremely fast and flexible at the same time. I'll leave that for next time however since this entry is already getting rather long.