Wednesday, April 1, 2009

Finding A Way To Make Things Fall Down

I'm all for leveraging any engines or libraries that are available to simplicity a task. The only good reason to re-invent the wheel is if you have very specific needs that aren't met well by whats available, or if you need a high degree of optimization that isn't provided by a general case system, or if you have the desire and the available time to learn to do it yourself. For this game I want realistic feeling physics, I want the players steam powered hover ship to move and react in realistic ways (that sounds contradictory doesn't it?), I want to be able to knock things over and have things explode in satisfying ways, and all that means a decent and fairly robust physics engine. That's not something I have the time to really build myself, and I'm sure there are a number 0f free or reasonably cheap ones available in th community for C# by now.

My requirements are:
Available source (I'm going to want changes and special cases)
3D focused, 2D will not work for this
Rectangle and Sphere primitives at minimum
Mesh collision detection
Joints: spring joints and joint limiters a bonus
At least minimal surface friction

Googling around I've found there really isn't that much in the way of physics engines for C# yet. A number of 2D libraries seem fairly well along but the 3D realm is pretty limited. Fortunately the JigLibX library, a C# translation of the C JigLib appears to fit my bill almost perfectly. There doesn't appear to be native support for Spring constraints however the Car object in the demo is doing pretty much exactly what I need and a look through the sample applications code is encouraging. I'll import this into my project and see how it goes.

Now to get something on the screen. I've built and textured a simple sample ship (really a fancy cube) in an older version of 3DS Max, exported it as .fbx, copied it and it's texture over to my Content folder and imported the model into my project. Now I need to make a class that will represent this shape.

Hmmm. There appears to be two objects in the Spacewar game that represent something in the game and hold position information. There are SceneItems which can be added to, and are managed by, Screen instances and there are Shapes which are given to SceneItems. I'm not entirely sure what this duplicity is for, why you would create a SceneItem, then create a Shape, then give the Shape to the SceneItem and the SceneItem to the Screen instance. Apon inspection it seems the SceneItem derived classes are responsible for the behavior of game objects, how they move and how they collide with one another, while the Shape derived classes describe what gets drawn on screen. This division would allow you to have game objects that look different but behave the same, such as multiple types of asteroids. The problem I see with this is that most objects in a game that look different also behave at least slightly different. The collision bounds for asteroids should be different based on the shape of the asteroid for example, and different sized asteroids would react differently to a collision. I can see this leading to a situation where you have an AlienSceneItem class that has huge switch statements (or if-else chains) that change the behaviors based on what Shape it's loaded with, creating a Gordian Knot of logic that would be far better served by breaking it out into separate classes. I'll leave it this way now, but if I end up with just about a one to one ratio of SceneItems and Shapes I'll collapse them into one base class.

So I've made my PlayerShipModelShape and my PlayerShipSceneItem, I initialize them at the start of my PlayerScreen and put the Shape in the SceneItem and the SceneItem in the Screen so everything is getting Update and Draw calls as should be. Now I just want to see it on the screen. Alas, the shader is unhappy. The shader for Spacewars is more advanced then I need it to be right now, it's got 14 parameters and while most of them are pretty obvious (world, worldViewProjection, viewPosition, etc. etc.) I don't really want to spend the time to load up all it's textures and set it's params just right when I'm going to have to write my own shader later anyway. I'm not ready for that now, certainly.

I rip out the Spacewar shader and all of it's params and copy some BasicShader using code from somewhere and low and behold nothing shows. Double check the camera location and the ship location... ah, the default Spacewar camera is at z = 500 units, but my ship is 1.5 units across, my ship is there, it's just smaller than a pixel right now. Everything in the Spacewar universe must be much bigger than my ship. I move the camera to 5 units and there's my ship, nice and textured and everything.

Next: Fun With Physics, and Which Way is Up???

No comments:

Post a Comment