# Best Practices For jME3 Developers

A collection of recommendations and expert tips. Feel free to add your own!

If you are a beginner, you should first read some articles about game development. We cannot cover all general tips here.

## Requirements Gathering

As a quick overview, answer yourself the following questions:

- Motivation
  - Sum up your game idea in one sentence. If you can't, it's too complicated.
  - Who's the target group? Why would they choose your game over the million others that exist?
- Game type
  - Point of view (camera)? What character(s) does the player control (if any)?
  - Time- or turn-based?
  - Genre, setting, background story? (If applicable)
- Gameplay
  - What is the start state, what is the end state?
  - What resources does the player manage? How are resources gained, transformed, spent? E.g. speed, gold, health, "points".
  - How does the player interact? I.e. rules, challenges, game mechanics.
  - What state is considered winning, and what losing?
- Media assets
  - Which media will you need? How will you get this content?
    models, terrains; materials, textures; audio, sound, music; video; spoken/written dialog; levels, quests, stories; AI scripts
- Interface
  - Can you achieve a high degree of input control? Even minor navigation and interaction glitches make the game unsolvable.
  - Clearly reflect current status, and changes in game states. E.g. health/damage.
  - Clearly reward good moves and discourage bad ones.

## Planning Development Milestones

1. Pre-Alpha
   1. Lay out the overall application flow using mock-ups or stock art. E.g. switching between intro screen / options screen / game screen.
   2. Get one typical level working. E.g. if it's a "Jump'n'Run", jumping and running must work before you can call it an Alpha.
2. Alpha
   1. Run internal tests, debug, optimize (issue tracker).
   2. Replace all mock-ups with first drafts of real media and levels.
   3. Feature Freeze: Avoid a bottomless pit of side effects causing new issues.
3. Beta
   1. Have external people review and "beta test" it (issue tracker).
   2. Even out the kinks in the code – don't add any more new features.
   3. Fill in all final content.
4. Gamma, Delta = Release Candidates
   1. Last chance to find a horrible bug.
5. Omega = Final Release

How you actually name or number these milestones is up to you. People use the words "milestone", Greek letters, version numbers, or combinations thereof.

Every milestone is made up of a development phase and a test phase. Here are some best practices:

## Development Phase

### Where to Start?

You have a list of features that you want in game, but which one do you implement first? You will keep adding features to a project that grows more and more complex, how can you minimize the amount of rewriting required?

1. Start with implementing the most complex game feature first – the one that imposes most constraints on the structure of your project (for instance, networking.)
2. Make sure the game's high-level frame (screen switching, networking, physics, loading/saving) is sound and solid before you implement low-level details of gameplay.
3. Only add one larger feature at a time. If there are complex interactions (such as "networking + physics"), start with a small test case ("one cube") and work your way up, don't start with a whole scene.
4. Test for side-effects on existing code before you add the next feature.

Acknowledge whether you want a feature because it is necessary for gameplay, or simply because "everyone else has it". Successful high-performance games are the ones where someone made smart decisions what to keep and what to drop.

- Example: Everybody wants "full physics, AI, post-rendering effects, and multi-player networking"… Make certain you truly understand what that requires (e.g. client-server synchonization)! Your goal should be to bring out the essence of your game idea, don't water down gameplay but attempting to make it "do everything, but better".

### Extend SimpleApplication

Typically, developers extend a custom class off of jME3's com.jme3.app.SimpleApplication (or even com.jme3.app.Application). For a racing game you would create a different base game class than for a space game or a shooter.

1. Create a generic game class for your custom game:
   1. Create a jME3-based project with all necessary JARs on the classpath.
   2. Create a class in this package that extends SimpleApplication, name it something like `my.company.MyBaseGame.java`.
   3. Implement all generic features that the game type needs in the MyBaseGame class. For example methods for loading and saving scenes, physics, networking and multi-player logon screen, switching to settings screen, etc.
   4. Include generic assets (company logo, reusable GUI elements in your company style, etc) in the MyBaseGame's assets directory.
2. Create your actual game, e.g. a shooter:
   1. Create another jME3-based project, and a new package for the game itself, e.g. `my.company.zombieshooter.MyGame.java`.
   2. Add MyBaseGame.jar to the classpath of MyGame.java.
   3. Make MyGame.java's main class extend MyBaseGame.
   4. The specific assets (scenes, models) of this game go into MyGame's own assets folder.
   5. Now implement this game's mechanics and levels – without having to worry about logon&settings screens and all the other features that you already dealt with in MyBaseGame.

### Controls and AppStates -- The Smart Way to Implement Game Logic

As your jME3-based application grows more advanced, you may find yourself putting more and more tests in the simpleUpdate() loop, and passing around lots of object references. Don't implement game behaviour by copying and pasting boilerplate code! It is a best practice to move game behaviour into classes of their own. In jME3 these classes are Controls and AppStates.

- Use Controls to implement the behaviour of types of game entities. A character control that defines how this type of Spatials moves, an animation control that plays animations in this type of Spatial's model, etc.
- Use AppStates to implement global game behaviour: A physics manager, a custom artificial intelligence manager, etc.
- Use the simpleUpdate() loop for the remaining "one-off" tests and interactions.

Both classes automatically hook into the main update loop. Instead of remote controlling game entities via simpleUpdate(), you define the desired behaviour in the update methods of custom Controls and AppStates. You then add Controls to Spatials, and AppStates to the application, and jME3 will automatically trigger the update methods. This cleans up your simpleUpdate() loop code considerably.

Learn more about Custom Controls and Application States.

### Optimize Application Performance

- Optimization
- Multithreading

### Use an Assets Folder

Put your assets into subfolders of your project's `assets` directory. This is the default path where the assetManager looks for files.

    jMonkeyProjects/Pong/assets/    # Store assets here
    jMonkeyProjects/Pong/build/     # jMP generates built classes here *
    jMonkeyProjects/Pong/build.xml  # Customize Ant build script here
    jMonkeyProjects/Pong/nbproject/ # jMP stores default build.xml and meta data *
    jMonkeyProjects/Pong/dist/      # jMP generates executables here *
    jMonkeyProjects/Pong/src/       # Store Java sources here
    jMonkeyProjects/Pong/test/      # Store test classes here (optional)
    (*) managed by jMonkeyPlatform, don't edit

- Agree on a file and directory naming scheme with the designers.
  - Are there assets (models, sound files, …) that will be used interchangeably? Then name or number them in a way so that the developer can swap the assets by swapping part of the path string.
  - Decide on naming standards for naming interactive parts of models (e.g. arms/legs in an animation).
- Structure the subfolders of `assets` in any way that suits the project – but stick with one system.
  - Either keep all Textures together with their Ogre meshes in the Model directory.
  - Or keep the Ogre meshes with their Textures in the Textures directory. (Recommended.)
- Place reusable Textures and Materials (the ones that you set programmatically) into the Textures and Materials directory, respectively.
- If different types of assets (materials, textures, models) belong together, create a parallel subdirectory structure for them: `Textures/vehicles/car/`, `Materials/vehicles/car/`, `Models/vehicles/car/`

Here is an example of a commonly used directory structure:

    jMonkeyProjects/Pong/assets/Interface/ # .font, .jpg, .png, .xml
    jMonkeyProjects/Pong/assets/MatDefs/   # .j3md
    jMonkeyProjects/Pong/assets/Materials/ # .j3m
    jMonkeyProjects/Pong/assets/Models/    # .j3o
    jMonkeyProjects/Pong/assets/Scenes/    # .j3o
    jMonkeyProjects/Pong/assets/Shaders/   # .vert, .frag
    jMonkeyProjects/Pong/assets/Sounds/    # .ogg, .wav
    jMonkeyProjects/Pong/assets/Textures/  # .mesh.xml+.material, .mtl+.obj, .jpg, .png

See also: Asset Packs

### Don't Mess With Geometric State

Here are some tips especially for users who already know jME2. Automatic handling of the Geometric State has improved in jME3, and it is now a best practice to not mess with it.

- Do not call updateGeometricState() on anything but the root node!
- Do not override or mess with updateGeometricState() at all.
- Do not use getLocalTranslation().set() to move a spatial, always use setLocalTranslation().

### Maintain Internal Documentation

It's unlikely you will be willing to fully document every class you write. You should at minimum javadoc all crucial methods/parameters in a meaningful way.

- Answer three questions for every crucial method/parameter:
  - What is this?
  - How does it solve its task? (e.g. algorithm used)
  - In which situation do I want to use this?
- Write down limits (e.g. min/max values) and defaults while you still remember.
- Is this optional or required? What are the alternatives?
- Treat javadoc as messages to your future self. "genNextVal() generates the next value" and "@param float factor A factor influencing the result" do not count as documentation.

### Use Version Control

Whether you work in a team or alone, keeping a version controlled repository of your code will help you roll-back buggy changes or recover that code that you or someone deleted and now is needed.

- Treat commit messages as messages to your future self. "Made some changes" is not a commit message.
- The jMonkeyPlatform supports Subversion, Mercurial, and CVS.
  - If you don't know which to choose, Subversion is a good choice for starters.
  - You can get free project hosting space from various open-source dev portals like Sourceforge, Github, bitbucket or Google Code. Bitbucket support private projects.

### Convert Models to .j3o Format

From the beta on, convert all Ogre mesh models and scenes to the binary .j3o format. Use the jMonkeyPlatform for the conversion, and save the .j3o files into the Models directory.

- .j3o is an optimized format to store part of a jME3 scenegraph.
  It can contain an individual model or a whole scene. Optionally (using the jMonkeyEngine SceneComposer) you can include the model's physical properties, materials, lights, particle emitters, and audio nodes.
- If you kept the Ogre mesh together with the textures in the Textures directory during the conversion, the paths are recorded in a way so that you can move the .j3o to another directory, and it will still find its textures.
- The default Ant build script copies .j3o / .j3m files and other assets into the distributable JAR automatically.
- Important: Other model files however (.mesh.xml, .material, .obj, .mat) are not bundled automatically. You will get a runtime error that a resource was not found if you try to run the JAR with code referring to these files.

## Debugging and Test Phase

### Test

Unit Tests (Java Assertions) have a different status in 3D graphics development than in other types of software. You cannot write any assertions that automatically test whether the rendered image looks correct, or whether interactions are intuitive. Still you should create simple test cases for separate game features such as loaders, content generators, effects. Run them now and then to see whether they still work as intended – or whether they are affected by side effects. Keep the test classes in a test directory in the project, but don't include them in the distribution.

Quality Assurance (QA) means maintaining a clear list of steps that must always work, and checking them. There can be bugs in software, but tasks such as installing and de-installing, saving and loading, starting/pausing/quitting the game, must work, no excuse. After every milestone, you go through the list again, on every supported operating system, and systematically look for regressions or bugs.

Alpha and Beta Testing means that you ask someone to try to install and run your game. It should be a real user situation, where they are left to figure it out by themselves (you only can include the usual read-me and help docs). Provide the testers with an easy method to report back descriptions of their problems, e.g. why they gave up. Evaluate whether these problems are exceptions or must be fixed for the game to be playable.

### Debug

A Java Debugger is included in the jMonkeyPlatform. It allows you to set a break point in your code near the point where an exception happens. Then you step through the execution line by line and watch object and variable states to detect where the bug starts.

Use the Logger to print status messages during the development and debugging phase, instead of System.out.println().

### Enhance Performance

A Java Profiler can be added to the jMonkeyPlatform via Tools → Plugins → Available. The profiler presents statistics on the lifecycle of methods and objects. Performance problems may be caused by just a few methods that take long, or are called too often. If object creation and garbage collection counts keep increasing, you are looking at a memory leak.

## Release Phase

Pre-Release To-Do List

- Verify that all assets are up-to-date and converted to .j3o.
- Prepare licenses of assets that you use for inclusion (you did obtain permission to use them, right…?)
- Switch off fine logging output.
- Prepare promotional art: Cool screenshots (in thumbnail, square, vertical, horizontal, and fullscreen formats) and video clips. Include name, contact info, slogan, etc so customers can find you.
- Prepare a web page, start getting advertisment slots, etc
- Prepare a readme.txt file, or installation guide, or handbook – if applicable.
- Get a certificate if it is required for your distribution method (see below).
- Specify a classification rating.
- …

Distributable Executable

The SDK can help you with deployment. Do you release your game as WebStart, Desktop JAR, or Applet? Each has its pros and cons.

Distribution | Pros | Cons
--- | --- | ---
Desktop Launcher (.EXE, .app, .jar+.sh) | This is the standard way of distributing desktop applications. The jMonkeyPlatform can be configured to automatically create zipped launchers for each operating system. | You need to offer three separate, platform-dependent downloads.
Desktop Application (.JAR) | Platform independent desktop application. | User must have Java configured to run JARs when they are opened; or user must know how to run JARs from command line; or you must provide a custom JAR wrapper.
Web Start (.JNLP) | The user accesses a URL, saves the game as one executable file. Easy process, no installer required. You can allow the game to be played offline. | Users need network connection to install the game. Downloading bigger games takes a while as opposed to running them from a CD.
Browser Applet (.HTML+.JAR) | Easy to access and play game via most web browsers. Userfriendly solution for quick small games. | Game only runs in the browser. Game or settings cannot be saved to disk. Some restrictions in default camera navigation (jME cannot capture mouse.)

Which ever method you choose, a Java-Application works on the three main operating systems: Windows, Mac OS, Linux.

view online version