Search |
||||||||||||||
FlyingGuns: A Distributed Realtime Simulation Game
Thu, 2005-02-17
|
||||||||||||||
| 3D | There's Java3D, at least. |
| Network | This is what Java was made for. |
| Libraries |
|
| Deployment | Heard about WebStart? |
| Tools | NetBeans, Eclipse, profilers, archivers: programmer heaven. |
| Free | Yes! |
As mentioned above, we wanted to create more than a small game. The goal was an extendable, reusable framework for distributed, interactive, realtime simulation. Thus, we needed an architecture, forming the DRTS project. Here it is:

Figure 1. FlyingGuns architectural overview
The client consists of a number of modules, each dealing with certain task. They are tied together in the game package. A game plays within a scene, which is the other big unit in the client and represents the (static) 3D world. Thus, the scene is the module that interfaces with the 3D engine. The distributed nature is represented by the component called HeadQuarter, which is the networking backbone of the whole thing and maybe the most complex thing in play. Currently, the server is basically just forwarding network messages and maintaining the same HeadQuarter mechanics as that of the client.
The overall scenario and gameplay was chosen with the goal of creating a network game. Form follows function. A WW1 flight simulator seems to be ideal in many respects.
For offline play, many AI opponents can be added. They serve as reasonable targets to practice maneuvering, aiming, and shooting.
Before starting to create a 3D game, some basic decisions have to be made. The most fundamental choosing the right technologies; the right 3D technology in this case. When we started with FlyingGuns in 2002, there weren't too many options. There were just Java3D and GL4Java. GL4Java allows low-level OpenGL access, and thus the lowest overhead and maximum performance, at least at first glance. This holds true when talking about a spinning cube, but FlyingGuns needs a terrain, a sky, airplanes en masse, shadows, effects, sound, and so on and this requires:
Implementing each of these requires a lot of knowledge, time to work it out, and code. For a spare-time project, these features alone can eat up all of the time available. Java3D provides all of these things out of the box.
The 3D world for a flight simulator can be hierarchically arranged, and therefore matches the scenegraph approach of Java3D:

Figure 2. Structure of the FlyingGuns 3D world

Figure 3. Typical Java3D scenegraph layout
Java3D turned out to be quite fool-proofed and robust. The documentation and examples are sufficient and--since it's kind of a standard technology--there are many people around who can help. But Java3D also has its downsides; for instance, the sound system just does not work as expected (they took it out completely for the latest versions of Java3D), which took us a lot of time to work around. Second, it is extremely hard to make a Java3D application smooth! This is a not a matter of performance, but of frame-time coherence. Java3D has always been quick enough, but frame times vary unpredictably. Since smooth animation systems always rely on frame times being similar from one to the next, this turns out to be a serious problem.
Today, there are more choices, including the following:
These are all possible candidates for a rendering engine. FlyingGuns currently tries to abstract the rendering layer, making it possible to plug in any of these in the future.
HeadQuarter is the infrastructure, containing all relevant gaming information. This includes positions, types, and states. It is also responsible for sharing this information transparently over the net. The game itself isn't even aware of whether or not it plays on the network or is run as a completely standalone application. HeadQuarter provides a set of subsystems, each takes care of a certain facet of a game object. There is a subsystem that deals with spatial data alone; one that implements a registry-like system used for relationships and typing; and a properties subsystem that takes care of names, hitpoints, health, and so on. Applications write or read a subsystem's data by the means of its API. HeadQuarter then takes care that these changes are properly propagated so that other clients are notified.

Figure 4. HeadQuarter subsystems
This kind of subdivision allows us to implement different protocols and distribution schemes for different kinds of data. Additionally, it allows us to write special clients that do not need all of the data. This could include, for example, a small client showing a radar screen. This client would only use the spatial subsystem. In this way, the division into subsystems supports the distribution framework.
In order to keep the subsystems tied together, HeadQuarter has a very strong notion of identity. Everything in HeadQuarter has an identity. In contrast to other systems, which provide a "network session identity" (with createPlayer() returning an int), HeadQuarter identities are context-agnostic and can therefore be used for any purpose. This might include persistence or resource binding. So an identity can be just about anything appropriate to identify an object across JVM boundaries: a name, an ID, or even a SQL statement.
Internally, HeadQuarter relies on a messaging kernel named ObjectBus, which in turn is currently a thin layer on the Java NIO API introduced with 1.4. ObjectBus isn't completely covered by the subsystems but is open for application use as well. Event-like data ("player throws a grenade") that does not have to be maintained as a state ("player starts shooting with machine gun") is thought to be transmitted as bare ObjectBus messages.
The FlyingGuns project is now in a working state, meaning there is a playable prototype. The source is freely available from SourceForge and volunteers are deeply appreciated.
On top of the current to-do list is a better renderer abstraction, which will allow us to better isolate 3D code from the game and try out 3D engines other than Java3D. (Xith3D or jME would be the next candidates.) Have you seen CounterStrike and CounterStrike: Source? They're the same game, just with the graphics changed. That's the goal.
True gameplay needs to be added in order to turn the prototype into a game: missions, goals, rankings, different vehicles and weapons, etc. It doesn't sound that difficult, but the distributed nature of FlyingGuns sometimes makes it a challenge.
At no point was performance a real issue. I claim that today it is nearly impossible to perceive there is a garbage collector. It's just that Java3D turned out to be a bit unpredictable about the consequences of using its features; touch the wrong parameter, and the performance can break down. Networking has turned out to be the most challenging part.
It is very possible to write a true 3D action game in Java. The unique goals like high accessibility, living content, and network play make Java a first-class citizen among game-development systems. Plus, compared to the C++ games development we did, the time for debugging and hunting ugly bugs has been negligible.
The FlyingGuns home page
Distributed RealTime Simulation on SourceForge
The author's home page
Java3D
Serious gaming
StarFire Research 3DS loader

Figure 5. Involved in a dogfight

Figure 6. Many, many opponents
|
|