I’ve threatened to write an Asteroids clone using an ES a few times now… so I finally did it this past few nights. It also turns out to be a pretty basic fully working example of using Lemur, too.
First, the code: https://jmonkeyplatform-contributions.googlecode.com/svn/trunk/zay-es/examples/AsteroidPanic/
Zay-ES doesn’t show up in the nice google code browser but you an check it out or browse it from that link at least.
Second, if you just want to skip right to running a prebuilt version:
https://jmonkeyplatform-contributions.googlecode.com/svn/trunk/zay-es/examples/AsteroidPanic/release/AsteroidPanic-Windows.zip
https://jmonkeyplatform-contributions.googlecode.com/svn/trunk/zay-es/examples/AsteroidPanic/release/AsteroidPanic-Linux.zip
https://jmonkeyplatform-contributions.googlecode.com/svn/trunk/zay-es/examples/AsteroidPanic/release/AsteroidPanic-MacOSX.zip
I’ve been slightly addicted to the game the past few days. Level 4 is the highest I’ve reached, personally.
Controls:
‘A’ ‘D’ - rotate left and right
‘W’ - thrust
space - fire
I have not implemented sound yet. I want to, but it wasn’t a requirement for a good example, really.
Third, what it looks like…
I went for a retro vector-style like the original arcade machine, ie: no pixels. Trickier to accomplish than one might think but here are some screen shots:
Main menu: (simple Lemur screen)
It’s good enough for a demo for sure.
And finally, the project details…
Easily half the classes are reusable boilerplate that could be used by almost any Zay-ES based game.
Main and MainMenuState are the main entry points.
SinglePlayerState implements the actual game state machine.
PanicHudState implements in-game HUD which is also used as a background to the main menu.
ShipControlState implements the ship controls.
ShipFunctions defines the Lemur InputMapper function IDs that the ShipControlState uses.
The other AppStates are general and do the work of marrying the ES to JME classes or implementing general systems like physics or collision detection.
Components: Decay, Mass, ModelType, Position, and Velocty are all game-independent. Just about any game “could” use these.
The CollisionShape component could be generalized but I went the easy route of just treating everything as a bounding sphere… so it’s kind of game specific at the moment.
The ModelState and CollisionStates are general but only because they accept a pluggable callback object that implements the game-specific parts of creating models and handling collisions respectively. (ModelFactory and ContactHandler).
I added class-level javadocs to all of the classes which hopefully helps explore a bit.
On the one hand, implementing an Asteroids clone using an ES was slightly overkill. On the other, it makes a good example (in my opinion) because it’s just about the simplest game possible to make and yet still has interesting things like physics systems, collisions, etc… I think there is very little that gets in the way of understanding how the game and the ES interact.
Also, if I choose to continue developing this game to add power-ups, shields, and so on then it will be truly simple to add them. And were I to have to rewrite a similarly simple game today, I could reuse most of these states and get the same work done in about 8 hours including sprites. So there is that.
Edit: corrected links to go with the (now) properly spelled zip names.