Shootin’ Off the Design


One of the games I recently added on the Unity Games page is a remake of a not-quite game that John and I did a few years back.  I thought I’d take some time to explain the design ideas and delve into where I’m taking it.  Click the image below to play with it in the Unity Web Player.

Asteroid being destroyed

Asteroid being destroyed

Background

The idea originated with John (also on this site) and where it came from is probably best left to a post from him.  For several years we worked on Crystalspace.  When we decided to quit, Shooter (later to be named Longshot as you’d see in the web player) was our foray into designing our own game engine (also another story…)  At the same time I was working my way through a Masters degree and taking a course in machine learning.  At about that same time I agreed to develop the AI for the game.  I realized I didn’t really feel like generating a long tree of if-then rules and had just learned about behavior cloning in class.  So I pushed John into helping me round it out for the class.  We added another ship and spent some time with networking and left it there to see whether this behavior cloning thing would work… but this behavior cloning thing is also going to be another story. :)

Original Design

I’ve seen so many of these games now that it’s hard to decide if anything in particular was innovative about what we were doing.  Perhaps some of it was at the time.  It’s a top down space shooter that includes asteroids.  Much has been written on the rite of passage that is cloning asteroids… everyone should do it at least once.  Of course, we couldn’t seem to get the asteroids physics to work as well as we liked so we dropped them.  But really there’s nothing new there.  For the sake of curiosity, I’ve uploaded the windows installer for the original here.

Where there was a sense of newness was in the design of the engine itself.  This design, it turns out, is described pretty handily as “System of Systems”.  It is an idea employed by the military for many simulation games and uses High Level Architecture (HLA) as the formalism.  The idea there is that each of these systems is developed by separate entities, but they can be brought together and easily coupled into large, more complex systems.  Our thinking at the time wasn’t quite so complex.  I simply wanted to see whether or not we could thread one loop of physics at a reasonable simulation rate and thread another loop of graphics at a separate rate and yet another loop for gameplay without strongly coupling any of them.  My thought was that graphics could run just fine at 30 frames per second and the only reason to run it higher was because if it were strongly coupled with the physics you’d want that at a higher rate.   We did run the physics at a higher rate of 100 hz (along with the input so it felt responsive).  Interestingly the gameplay was entirely event driven responding only to collision events.  This is where Unity’s design is so nice because in the same way all of the gameplay exists now in the collision code.

function OnTriggerStay (other : Collider) {
if (other.name != "Bullets" && GetComponent(FireBullet).remoteFire) {
if (other.GetComponent(LifeCycle) != null) {
other.GetComponent(LifeCycle).hitpoints -= 1;
}
var closestPoint = other.ClosestPointOnBounds(transform.position);
var sparkPos = (other.rigidbody.position + closestPoint) / 2;
var spark = Instantiate (prefab, sparkPos, Quaternion.identity);
var sparkForce = transform.position - sparkPos;
spark.GetComponent(ParticleAnimator).force = sparkForce;
Destroy (spark.GetComponent(ParticleRenderer),0.5);
Destroy (spark.GetComponent(ParticleAnimator),0.5);
Destroy (spark.GetComponent(ParticleEmitter),0.5);
Destroy (spark,0.5);
}

It’s not entirely true that it’s all in that script, but that is a majority of it.  Two of my favorite results to come out of that design were the fact that the game ran with almost no CPU usage despite maintaining responsiveness and that I could lower the graphics to 8 fps and still play the game just fine.  It was painfully strobed, but it was possible to see what was going on.  Due to this it would have been easy to scale the graphics however necessary to fit into whatever capability the system had while allowing the physics to operate however needed.  However, this innovation wasn’t really much related to how the game played.

What may have been most interesting to me was the “hovercraft” design.  Although the motif is ships flying out in space, I thought it would be more interesting to see them rock as though on water.  We had already decided on forcing the 3d physics engine to fit to the 2d plane, but since we were using 3d models and a fully 3d engine, I thought we might as well show it off.  In order to do so we’d have the ship lean forward when moving forward and lean further forward when going really fast.  When stopping it would rear back (almost like a horse).  And best of all, when an explosion would go off it should rock the ship.  It wasn’t until using Unity’s Detontation engine that the rocking effect came into it’s own.  You can see this when you blow up an asteroid and get close.

The way this rocking effect was modeled was to virtually attach a spring to the front, back, and sides and have this pull the ship back into the plane.  Then we could apply forces from thrusters or explosions which would offset the springs and ultimately either pull or balance them out.

function FixedUpdate () {
if (rigidbody.position.y != 0) {
rigidbody.AddForce (0, rigidbody.position.y * -restore.y, 0);
}
yoff = transform.localRotation * Vector3(1, 0, 0);
xoff = transform.localRotation * Vector3(0, 1, 0);
rigidbody.AddRelativeTorque(xoff.y * -restore.x, -yoff.y * -restore.z, 0);
}

One of the really amusing side effects that came out of this was that by timing a forward and reverse thrust, one could cause the ship to rock to higher and higher degrees until ultimately flipping over.

New Design

Enter Unity.  For some reason Unity is designed with me in mind.  I don’t know who read my mind and made everything I could have possibly wanted out of a game editor, but someone did.  Thanks! :)  The result you see here was built in 2 weekends taking all the assets from the old project and porting all the code necessary (not very much) into javascript.  All told, I think  I spent about 20 hours on it and most of that was on learning how to do the networking (something I never did get right for internet latency on the old version).

Although I haven’t yet brought back the behavior cloning, even with a second ship the game was pretty boring.   But I really like the idea of modifying ships and customizing.  I’m not a very good artist, and I don’t feel like making hundreds of ship models.  So instead, I plan to make a bunch of ship pieces and allow the user to put them together into different pieces.  Of course some of the obvious choices would be chassis size and style, engine power, weapon type etc.  But one of the more fun ones due to this wobbly control scheme is to allow various levels of restoration power based on the types of items added to the ship.  If you don’t mind wobbling a great deal perhaps you can load your ship with more weapons.  Or perhaps you want a tight control and will exchange that for less fire power.  I’m giddy with the options :)

Another gameplay element I’m toying with is one that used to come up when playing Magic the Gathering.  When you’d duel another player you were supposed to put a card out on the line.   Whoever won would get the other player’s card (as well as their own back, of course).  Well I haven’t quite decided how players get cards (or really ship components) yet, but I thought it would make for an interesting gambit that when you do duel somebody you can take a component from their collection if you beat them.

More interesting however is to bring the behavior cloning back into it.  Because the idea behind BC is to create a model of how you play, one could imagine building a fleet of ships and playing with each in order to build up a clone which plays a particular way.  This allows one player to virtually control an entire armada when fighting another player, not just one ship.  But the downside is that if a ship gets captured that clone could be taken (or maybe just copied).  If you’ve made a particularly effective opponent someone may be able to steal that and use it in their own fleet.  Reminds me again of Magic the Gathering.  I used to play exclusively blue.  I don’t remember the names of the spells exactly, but I think they were “Steal Creature” and “Clone Creature”.  I remember playing one guy who was quite proud when he brought out some very rare, very powerful monster onto the playing field to take me out.  I had a steal creature sitting in my hand waiting for just that to happen.  On my next turn before he was able to attack, I stole it to use on my side.  And on the turn after that I cloned it.  Now instead of him having one very rare and powerful creature he had none.  I had two.  He was very, very angry.  I beat him quickly and left just as quickly :)

Anyway, hopefully people won’t be nearly as upset at losing a clone in the wages of war.  It is after all just a clone, but it creates some very frightening possibilities for components!   Keep an eye on this space, I’ll  talk more about advances in the game as well as give some background on behavior cloning and how to make it work.

  1. No comments yet.
(will not be published)
*