Development of a 3D Multiplayer Racing Game

Developing 3D action games doesn't involve just a single API, but a combination of some of the most demanding parts of Java. Evangelos Pournaras offers an overview of one such project, a 3D racing game that uses JOGL, JOAL, and java.nio.

Introduction

Racing games are one of the most popular categories of games and their development has always been a challenge to the game programmer, due to their demands in computer resources and fast networks. Most commercial games have been developed in C++, which is a mature programming language used by experienced programmers in the industry. However, network development, mobile gadgets, and hardware development have highlighted the need for a dynamic, continuously developed, portable, and object-oriented programming language for game development. Java seems to have these characteristics and sometimes can be faster than C++[2]. The traditional game industry can also gain from Java. New game consoles[3] are based on network services and there are thoughts of establishing Java as a mainstream technology in game development in the future.

This article describes work that was carried out as part of an undergraduate thesis. It includes the development of a 3D multiplayer racing game, JautOGL, using Java 1.4's new I/O APIs[4] for networking, JOGL[5] (Java OpenGL) for graphics, and JOAL[6] (Java OpenAL) for sound. Its supported functions and architecture are described below, together with some important and interesting details of the classes, which are illustrated too. Finally, the discussion of future developments and improvements that can be applied to JautOGL concludes the article. Figures 1 to 4 show some print screens of the game.

Figure 1. JautOGL logo

Figure 2. Far camera view

Figure 3. Normal camera view

Figure 4. Driver camera view

Supported Functions

JautOGL is a game engine with some fundamental characteristics and functions that can give a direct visual output and can be a basis for testing, experimentation, and future extensions. Both the number and the development depth of these functions are closely related to the length of development time.

The game engine supports the Full Screen Exclusive Mode (FSEM)[7] system of Java SE 1.4 and 1.5. Thus, JautOGL runs in full screen and incorporates a special class that embeds various functions, which manage issues related to graphics, resolution, color bit depth, screen updates, and window management. Anti-flickering and anti-tearing functions have also been created; they improve animation and synchronize the number of the screen updates with the number of the frames per second that the pipeline produces.

As far as interactivity, JautOGL listens to mouse and keyboard events. The classes that implement these functions can create interactivity patterns in order for a player to set and define the buttons of his preference, which he will use to play the game. The implementation of these two functions is based on the approach of David Brackeen, author of Developing Games in Java[8].

During the development of JautOGL, a very serious problem was encountered with the animation thread. The game did not seem to run normally, and the reason for this malfunction appeared to be related to the animation threads and the process of multitasking. CPU usage reached 100 percent. The problem was known to the java.net community[9] and the solution of the class FPSAnimator was applied to JautOGL.

The engine uses a parser of Wavefront format files in order to load 3D models. The Wavefront format specification[10] defines two types of files. The .obj files describe the geometry and the .mtl files include information about the materials and lights, which are connected with the geometry of the .obj files. The specification defines many complex geometrical characteristics and shapes. Some of them include Bezier curves, B-splines, Taylor polynomial curves, and various surfaces. The parsers of JautOGL are focused on the basics in order to reduce programming complexity and mathematical calculations that OpenGL easily does through its functions. The 3D models of the cars have been produced using 3D Studio Max 8[11], which exports the models and creates the Wavefront format files.

Furthermore, JautOGL loads textures and images and applies them in geometry. The classes include a range of methods that manage the textures and apply techniques like mipmapping.

By using OpenAL for the sound engine of JautOGL, the game gains a 3D sound system that plays the different car sounds dynamically into the 3D environment and gives the opportunity for many different future developments.

The movement of the car is based on the interactivity of the user. The cars can be moved in any direction and different camera modes can be chosen.

Last but not least, JautOGL is a multiplayer game, and is based on the client-server model. The new I/O interface[4] of Java offers a non-blocking mode in the communication, which is based on channels and the UDP protocol for fast datagram packet transfers.

Architecture and Analytical Description

JautOGL consists of 22 classes and approximately 5000 lines of code. The classes are developed to serve the supported functions that are described above by using the object-oriented technology of Java, the JOGL and JOAL APIs for graphics and sound respectively, and the new I/O interface for the networking.

The architecture of JautOGL can be expressed by its UML class diagram, which reveals the connections, relationships, attributes, and operations of the JautOGL classes. The attributes also include the objects for two reasons. Firstly, since string is an object of the class String and not a primitive type, I have included it in my UML diagram as an attribute. Secondly, the objects support and explain the relationships, which are depicted by the different types of arrows according to UML specification. Figure 5 illustrates the UML class diagram of JautOGL.

The classes and the functions of JautOGL are based on some programming features of the technologies that are used for the development. Focusing on the graphics and the display of the game, there are issues which are related to 3D model loading, full screen exclusive mode, and others regarding embedding and using the procedural OpenGL in the Java object-oriented programming language. OpenglCore implements a GLEventListener and has two important methods. The init() is executed only once, and does initial calculations, whereas the display() represents the main state/thread of the application, with each execution resulting in a frame for display. ScreenManager creates an instance of GLCanvas, which will embed the content of the OpenglCore instance.

A simplified version of the OpenglCore, which creates the scene and the graphical content, is illustrated below:

ScreenManager is responsible for the screen display. It contains the setFullScreen() method, which creates the OpenGL canvas with the graphical content of the OpenglCore instance. The canvas is added to a JFrame instance. Furthermore, this method starts the animation by using the methods of FPSnimator, which extends the Animator class. It fixes a bug[9] in NVidia's drivers (80174) which results in prevention of multithreaded access to the context.

Another important issue related to the screen display is the definition of the display mode. This includes the screen resolution, the color bit depth, and the refresh rate of the game. Depending on the approach followed, the programmer can choose the settings, or let the gamer choose through a graphical interface, or even develop code to automatically choose the best compatible display mode according to the graphics device. Some code that can support the last approach is illustrated below:

The JautOGL game engine includes parsers that load the 3D models by reading the information of the Wavefront format files. There are two classes responsible for this game element: GLModel and MtlLoader. Each one loads the information from the .obj and .mtl files, respectively. The files are read line by line and the parser looks for an identifier at the beginning of each line. For example, the format v x y z loads a vertex at the (x,y,z) coordinates of the 3D environment, while vn x y z loads a vertex normal at the (x,y,z). The .mtl files contain information about the ambient, diffuse, and specular lighting. JautOGL loads each one in an ArrayList or in multidimensional arrays. The splitting and the identification of the these strings relies on the StringTokenizer class and the methods trim(), startsWith(), and charAt(). As soon as JautOGL has stored all the information in array lists, it must then be transferred to the OpenGL pipeline. The information is loaded by using display lists (glGenLists()), which are an efficient and flexible way to retrieve such data. An example of simplified code of the class GLModel follows:

Interactivity in JautOGL is based on the GameInteractivity and InputManager classes. The first one maps possible events. The second gives the ability to the programmer to create interactivity patterns. This means that players could configure the buttons of their preference through a graphical interface. JautOGL uses these classes to define buttons for the car driving, the camera view changes, and the exit action:

Then the main game thread checks for interactivity events coming from the player:

if(accelerator.isPressed()&&turn_left.isPressed()){//car is turning left //define an angle for the turning movement_angle+=Math.PI/18;

//calculation of the new positions car1_z=car1_z+(float)Math.sin(movement_angle)*(float)0.2; car1_x=car1_x-(float)Math.cos(movement_angle)*(float)0.2; z_eye=car1_z-(float)Math.sin(Math.PI-movement_angle)*(float)dist_cam_car; x_eye=car1_x-(float)Math.cos(Math.PI-movement_angle)*(float)dist_cam_car; z_at=z_eye+(float)Math.sin(Math.PI-movement_angle)*(float)24.0; x_at=x_eye+(float)Math.cos(Math.PI-movement_angle)*(float)24.0; //NOTE: It is better for higher efficiency to avoid trigonometric methods //movements maps is a better solution}

The sound part of the engine, the class OpenalCore, defines the characteristics of the listener and the sound sources according to OpenAL philosophy on 3D sound[13]. These include position, orientation, and velocity. The sounds are loaded in byte buffers. Their size is limited by JVM and this results in a problem when loading large sound files (such as music tracks). The problem can be solved either by using data streams, which store limited data in byte buffers, or by configuring the limit of JVM. The first way is suggested.

The multiplayer mode of JautOGL is based on the client-server model and the UDP protocol for fast data transfers. The NIOClient and NIOServer classes form the networking part of the engine. New I/0 interface[4] offers non-blocking communication, which is fundamental in realtime applications and fast-action games like JautOGL. Reading and writing can take place by using only one thread. Generally, racing games need fast transfers, and game servers of such demanding games (high bandwidth, low latency) run the risk of being unable to respond to requests. The client and server communicate over channels that transfer data by using the read() and write() methods. The mechanism that controls reading and writing data over non-blocking mode is in Selector and SelectionKey. At the beginning, the server accepts one datagram packet/identifier from every player/client in order to save their address and establish the communication. These packets are sent when the init() method of the OpenglCore class is executed. Then the server is ready to do its main task by entering the main loop of execution.

There are many aspects of the game that can be discussed and analyzed further. The code, together with the UML class diagram, can reveal the correlations between the different elements of the game.

Conclusion

This article has described the development of a 3D multiplayer racing game developed in Java using the new I/O interface[4] for networking, along with the JOGL[5] and JOAL[6] APIs. JautOGL's technologies seem to make an interesting solution for games development. Although there is difficulty in object-oriented expression between Java and the procedural OpenGL and OpenAL, well written applications and deep knowledge of the technologies can overcome the difficulties. JautOGL can be improved and integrated. Some ideas include a better sound engine with Doppler effect simulation (which OpenAL supports)[14], more interactivity systems support[15], a collision detection system, artificial intelligence, a game protocol for better networking management, and other functions. Java is already the main technology in mobile computing, and with the extension in game consoles, Java can be evolved to become the leading technology in the game programming industry.