Monkey Zone: Multi-player Sample Project

MonkeyZone is an multi-player demo game provided by the jME core developer team.

This open-source demo:

  1. showcases one possible way to implement a game with jME3, and

  2. helps the jME team verify the jME3 API in terms of usability.

The game idea is based on “BattleZone” arcade game from the 1980s, a first-person shooter the with real-time strategy elements. The game was written using the jMonkeyEngine SDK, and it’s based off the BasicGame project template. It took us one week to create a playable pre-alpha, including networking. The project design follows best practices that make it possible to edit maps, vehicles, etc, in jMonkeyEngine SDK without having to change the code – This allows 3D graphic designers to contribute models more easily. (If you feel like contributing assets or working on parts of the game code, drop us a note!)

Implementation

MonkeyZone is a multi-player game with a physics simulation. Both, clients and server, run the physics simulation. The clients send input data from the player group to the server, where they control the entities, and also broadcast to the clients. Additionally, the server sends regular synchronization data for all objects in the game to prevent drifting. When a human user or an AI performs an action (presses a button), the actual logic is done on the server. The results are broadcast as data messages to the entities. When the entity is controlled by an AI, the actual AI code (that determines where the entity should move, and when it should perform an action) is executed on the client. _The way MonkeyZone is implemented is just one of the many possible ways to do a game like this in jME. Some things might be done more efficiently, some might be done in another way completely. MonkeyZone tries to do things the way that are most appropriate to implement the game at hand and it shows nicely how jME3 and the standard Java <abbr title="Application Programming Interface">API</abbr>++ can make game development easier and faster. Also note that the way MonkeyZone is designed is not scalable to a MMO style game, it will only work in a FPS style environment where the whole game world can be loaded at once._

Terminology

The game uses certain terms that might be familiar to you but maybe used in another way, so here’s a quick rundown on the terms being used.

  • Player – Logical human or AI player that can enter entities and generally act, only exists as PlayerData “database” with an id.

  • Entity – Spatial with UserData, a world object like character, vehicle, box or factory. The base form is defined only by a String pointing to the j3o which already has all userdata like hitpoints, speed etc.

  • User – Human player using a client

  • Player Group – Group of players that play together (e.g. one human player and one AI companion per client). For now that’s the same as client_id of human player for all AIControl’ed players originating from that client.

  • Client – Computer connected to server

Manager Classes

The WorldManager does the main work of organizing players, entities and the world and synchronizing them between the server and client. Both client and server use this class. Some other managers like ClientEffectsManager only exist on the client or server and manage e.g. effects display. The gameplay is largely controlled by the ServerGameManager which does gameplay logic on the server, combined with the actions issued by the AI and user on the client (see below) it implements the gameplay. It extensively uses the functions exposed by the WorldManager to perform actions and gather data. This is also the class where the actions of the players are actually executed on the server to determine the outcome (ray testing for shooting etc.).

Use of Controls

Controls are used extensively in MonkeyZone for many aspects of the game. When a player enters an entity, the Spatials Controls are configured based on the player that enters. For example when the human user enters an entity, Controls that update the user interface (DefaultHUDControl) or user input (UserInputControl) are added to the current entity Spatial.

…​As entity capabilities

Controls attached to Spatials are generally used like an “array of capabilities” that the entity possesses. So when an entity has a VehicleControl its expected to be a vehicle, when its got a CharacterControl its expected to be a character. Other Controls work completely on their own, like CharacterAnimControl which just uses the CharacterControl of the entity to check if the character is running, jumping etc. and then animates the entity if it has an AnimControl.

…​ to abstract

Furthermore there are special interfaces for Controls that allow abstraction of different Controls into one base interface. For example ManualControl and AutonomousControl are interfaces for controls that manage the movement of a spatial in a generalized way. This way AI code and e.g. the UserInputControl only have to check for a valid AutonomousControl or ManualControl on the spatial to control and move it. The details of the movement are handled by classes like ManualVehicleControl and AutonomousCharacterControl.

…​ for AI functions

A special Control called CommandControl handles the Commands that can be executed by user controlled players, see below.

Artificial Intelligence

MonkeyZone includes simple AI functions based on a command queue.

Commands

To implement autonomous AI players MonkeyZone uses a system of Commands that are managed by a CommandControl that is attached to each AI player entity controlled by the user. This CommandControl manages a list of Commands that are executed based on priority. For example there’s a MoveCommand, a FollowCommand and an AttackCommand, Commands can however implement more complete behavior than that, e.g. the complete logic for a scavenging entity.

  • Press the WASD keys and use the mouse to move

  • press space to jump

  • Aim and click to shoot

  • Type 1 to select the first Ogre

    • Aim at the floor and press F1 to tell it where to go.

    • Aim at a target and press F2 to tell it who to follow.

    • Aim at the car and press F3 to make it drive the car.

    • Aim at a target and press F4 to tell it who to attack.

    • Walk close to the car and press enter to drive the car.

Triggers

The SphereTrigger is a TriggerControl that is also attached to each AI players current entity. It consists of a GhostControl that checks the overlapping entities around the entity its attached to. It can be assigned a command that is checked with every entity entering the SphereTrigger and executed if applicable (e.g. normal “attack enemy” mode).

For each map a navigation mesh is generated that allows the entities to navigate the terrain. Autonomous entities automatically get a NavigationControl based on the current map. The AutonomousControl implementations automatically recognize the NavigationControl attached to the Spatial and use it for navigation. The NavMeshNavigationControl implementation contains a reference to the levels NavMesh and implements a navigation algorithm similar to the A* algorithm.

Networking

Networking is realized in the PhysicsSyncManager which we hope to extend to a state where it can serve as a general sync system for physics based network games. The sync manager basically puts a timestamp on every message sent from the server and then buffers all arriving messages on the client within a certain time window. This allows to compensate for messages arriving too soon or too late within the constraints of the buffer, a future version might step the clients physics space different to compensate for network delays without “snapping”.

Use of jMonkeyEngine SDK tools

All assets used in the game, like entity models and loaded maps can be preconfigured and edited using the jMonkeyEngine SDK. For example, to add a new vehicle type, a vehicle is created in the jMonkeyEngine SDK vehicle editor and UserData like Speed, HitPoints etc. is applied directly in the editor. When the model is loaded in the game it is automatically configured based on these settings, the same accounts for maps that are loaded, special Nodes that mark e.g. player start locations are recognized automatically etc.

UserData

Entities (Nodes and Geometries) that are loaded from disk have certain UserData like HitPoints, Speed etc. that is used to configure the entity at runtime. The jMonkeyEngine SDK allows adding and editing this UserData, so entity properties are editable visually.

Physics

VehicleControls, CharacterControls and RigidBodyControls with mesh collision shape for terrain and objects are generated in the jMonkeyEngine SDK and saved in the entity j3o file. When an entity is loaded, the type of entity is identified based on the available controls and UserData and it is configured accordingly.

API Info

Designer Infos

Editable UserData of entity Spatials:

  • (float) HitPoints

  • (float) MaxHitPoints

  • (float) Speed

Entity Spatial marking Node names:

  • AimNode

  • CameraAttachment

  • ShootAttachment

Level Spatial marking Node names:

  • StartPoint

  • PowerSource

  • MetalField

Developer Infos

Programmatic UserData of entities:

  • (long) entity_id

  • (int) group_id

  • (long) player_id

Programmatic PlayerData:

  • (long) id

  • (int) group_id

  • (long) entity_id

  • (long) character_entity_id

The Future

Have a look at the code and feel free to ask about it, if you want any new features, you are free to implement them. ;) MonkeyZone is hosted at GitHub, where you can clone the project via git:

  1. Fork the project via the GitHub interface.

  2. Clone the project from the SDK or any editor.

  3. Run the server first (com.jme3.monkeyzone.ServerMain), and then a client (com.jme3.monkeyzone.ClientMain).

Troubleshooting

  1. After download, errors could appear because jme3tools.navmesh.util\NavMeshGenerator.java import com.jme3.terrain.Terrain is not known, you should correct this by setting Project Properties > Libraries > Add Library > jme3-libraries-terrain