# 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
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?
- Multi-media assets
  - Which media will you need? How will you get this content?
    Models, terrains; materials, textures; noises, music, voices; video, cutscenes; spoken/written dialog; level maps, quests, story; 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

Use an
to outline what features you want and what components are needed.

1. Pre-Alpha
   1. Artwork: Test asset loading and saving with mock-ups and stock art.
   2. Lay out the overall application flow, i.e. switching between intro / options / game screen, etc.
   3. Get one typical level working. E.g. if the game is a "Jump'n'Run", jumping and running must work before you can announce Alpha.
2. Alpha Release
   1. Artwork: Replace all mock-ups with first drafts of real media and level maps.
   2. Run alpha tests, track bugs, debug, optimize.
   3. Declare
      before you announce Beta. This prevents a bottomless pit of new bugs.
3. Beta Release
   1. Artwork: Fill in the final media and level maps.
   2. Have external people review and "beta test" it (track bugs).
   3. Even out the kinks in code and gameplay – don't add any more new features.
4. Gamma, Delta = Release Candidates
   1. Test the heck out of it. Last chance to find a horrible bug.
5. Omega = Final Release

How you name or number these stages is fully up to you. Development teams use the word 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?

Many game developers dream of creating their very own "MMORPG with full-physics, AI, post-rendering effects, multi-player networking, procedurally generated maps, and customizable characters". So why aren't there tons of MMORPGs out there? Even for large experienced game producers, the creation of such a complex game is time-intensive and failure-prone. How familiar are you with multi-threading, persistance, optimization, client-server synchonization, …? Unless your answer is "very!", then start with a single-player desktop game, and work your way up – just as the pros did when they started.

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. Make sure the game's high-level frame (screen switching, networking, loading/saving) is sound and solid.
2. Start with implementing the most complex game feature first – the one that imposes most constraints on the structure of your project (for instance, networking, physics.)
3. Add only 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. Implement low-complexity details (audio and visual effects) last.
5. 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". 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". Successful high-performance games are the ones where someone made smart decisions what to keep and what to drop.

### Extend SimpleApplication

Extend your custom base class off of jME3's com.jme3.app.SimpleApplication. For all your games, you will want a customized basic framework: Methods for loading and saving scenes, screen switching (logon/start screen, options, game screen, etc), physics, networking, etc. Then you reuse (extend) your own generic game class when you create any specific game (a racing game, or a space game, a shooter, etc).

Follow these steps:

1. Create a generic library for your own "game development business":
   1. Create a jME3-based project MyBaseGame with all necessary JARs on the classpath.
   2. Create a class in this package and name it something like `my.company.MyBaseGame.java`.
      1. Make MyBaseGame extend com.jme3.app.SimpleApplication.
      2. Include generic assets (company logo, reusable GUI elements in your company style, etc) in the MyBaseGame's assets directory.
      3. Implement generic game features in the MyBaseGame class: GUI (start screen, highscore screen), screen switching and pausing, the in-game HUD, level loading, saving and loading games, AppSettings, the main() method, etc.
   3. Build the project. You get a JAR file, your custom MyBaseGame.jar.
2. Create your actual game, e.g. a zombie shooter:
   1. Create a second JME3-based project, MyZombieGame, with all necessary JME3 JARs on the classpath.
   2. Create a package for the game, e.g. `my.company.zombieshooter.MyZombieGame.java`.
   3. Add MyBaseGame.jar to the classpath of MyZombieGame. You can now re-use you custom generic game library.
      1. Make MyZombieGame.java extend your MyBaseGame class (which extends SimpleApplication).
         - MyZombieGame.java has no main() method because it uses the inherited main() method.
         - MyZombieGame.java makes super calls and overrides the SimpleApplication methods it inherited:

                   public void simpleInitApp() { super.simpleInitApp(); }
                   public void simpleUpdate(float tpf) { super.simpleUpdate(tpf); }
                   public void simpleRender(RenderManager rm) { super.simpleRender(rm); }

      2. Place the specific assets (scenes, models) of this game go into MyZombieGame's own assets folder.
      3. After the generic super calls, add the specific game code for this game. Now you can implement this specific game's mechanics and levels using controls and app states, without having to worry about logon&settings screens and all the other generic features that you already dealt with in MyBaseGame.

### The Smart Way to Add Custom Methods and Fields to Nodes

Game elements (Spatials such as Nodes and Geometrys) often carry custom fields and custom methods with them. For example, players have health, gold coins, an inventory, equipment, etc. You may have methods that modify the player state, such as addGold(), addHealth(), pickUpItem(), dropItem(), wieldItem(), etc.

Anti-Pattern: In Java it's possible that you extend the Node class to create a custom Node class. But be aware not to get trapped by the following anti-pattern: You might try to create different character nodes with `MyMobileNode extends Node` and then `MyNPC extends MyMobileNode`. Then you might continue creating subclasses such as `MyCityGuardNPC extends MyNPC` and `MyShopKeeperNPC extends MyNPC`. What do you do now if you need a MyShopKeeperNPC that also fights, do you write a whole new MyFightingShopKeeperNPC class? Inheritance does not help you here.

Also, extending a Node just to add custom fields to it is unneccesary, because you can store any custom Java objects in Spatials! This user data is accessible where ever the Spatial is accessible. Read the Spatial documentation to learn more about how to use the `setUserData()` method on Nodes and Geometries.

In short: Don't extend Node to implement game mechanics of your entities. Instead:

- Add Custom Controls to supply your Nodes with custom methods!
- Use ''setUserData()'' to add custom data fields to Spatials!

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

As your SimpleApplication-based game grows more advanced, you may find yourself putting more and more tests in the `simpleUpdate()` loop, passing around lots of object references, and your simpleInitApp() methods grows longer and longer….

Move game behaviour into reusable classes of their own. In jME3 these resuable classes are Controls and AppStates.

- Use Controls to implement the behaviour of types of game entities.
  - Controls add a type of behaviour to individual Spatials.
  - Each Spatial needs its own instance of the Control. One Spatial can be influenced by several Controls.
  - Use Controls to move code out of the `simpleUpdate()` loop.
  - Examples: An NPC Control that defines how types of enemy Spatials find their way around, a player Control an generic animation control that triggers animations in various types of 3D models, the RigidBodyControl (part of the physics integration), etc.
- Use AppStates to implement global game mechanics.
  - Use AppStates to move code out of the `simpleInitApp()` method.
  - Each AppState brings its own set of game states: You write code so that enabling and disabling an AppState activates and deactivates one particular set of class fields, GUI, spatials, input handlers, etc. This way you use AppStates to switch between e.g. an InGameState and a MainMenuState.
  - Examples: The integrated jBullet physics simulation, an overall artificial intelligence AppState that coordinates cooperating enemies, an in-game AppState that loads the scene and the HUD and activates the in-game input mappings, a main menu AppState that switches input handling (clicks are interpreted differently than in game) and displays buttons and lets the user open highscore and settings screens, etc.

Controls and AppStates can work together:

- An AppState can reach up to the application and get all Spatials that carry a specific Control, and use this information to perform some global action on them.
- Example: Individual physical spatials (carrying RigidBodyControls) that are steered by the overall physics simulation (BulletAppState).

Both Control and AppState automatically hook into the main update loop.

- Instead of remote controlling all game entities via code in the simpleUpdate() method, you define the desired behaviour in the update() methods inside your custom Controls and AppStates.
- Add Controls to Spatials, and AppStates to the application. jME3 automatically triggers their update() methods as part of the main update loop.
- This cleans up your main class considerably. In the ideal case, you abstract all interactions into Controls and AppStates, and your simpleInitApp() and simpleUpdate() could even end up being empty.

Read all about Custom Controls and Application States here.

### 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/MyGame/assets/    # Store assets in subfolders here!
    jMonkeyProjects/MyGame/build/     # SDK generates built classes here *
    jMonkeyProjects/MyGame/build.xml  # Customize Ant build script here
    jMonkeyProjects/MyGame/nbproject/ # SDK stores default build.xml and meta data *
    jMonkeyProjects/MyGame/dist/      # SDK generates executables here *
    jMonkeyProjects/MyGame/src/       # Store Java sources here
    jMonkeyProjects/MyGame/test/      # Store test classes here (optional)
    (*) managed by jMonkeyEngine SDK, don't edit

- Agree on a file and directory naming scheme with the graphic 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 for various file types:

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

See also: Asset Packs and Asset Manager.

### 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 the most 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? Is this part of a series of steps that are prerequistes?

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 File 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 old code that someone deleted and that is now needed again.

- Treat commit messages as messages to your future self. "Made some changes" is not a commit message.
- The jMonkeyEngine SDK 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
    ,
    ,
    ,
    , or
    .
    supports private projects.

### Convert Models to .j3o Format

From the beta on, convert all models and scenes (Ogre mesh and Wavefront and Blender) to jME3's binary .j3o format. Use the jMonkeyEngine SDK 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, in the .j3o file.
- 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.

See also: Model Loader and Viewer

## Debugging and Test Phase

### Test

Unit Tests (
) 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 individual game features such as loaders, content generators, effects. Run the test cases 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. It will always happen that there are hard-to-find bugs in the gameplay somewhere – but basic 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 QA list again, on every supported operating system, and systematically look for regressions or newly introduced 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, or 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 jMonkeyEngine SDK. 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(). The logger can be switched off with one line of code, whereas commenting out your println()s takes a while.

### Enhance Performance

You can add a Java Profiler to the jMonkeyEngine SDK 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

- Prepare a web page, advertise, etc
- Verify that all assets are up-to-date and converted to .j3o.
- Verify that your code loads the optimized .j3o files, and not the original model formats.
- 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 future customers can find you.
- 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 jMonkeyEngine SDK helps you with deployment (unless you used another IDE, then consult the IDE's documentation). Do you want to 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 jMonkeyEngine SDK 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.)
Android (.APK) | Game runs on Android devices | Android devices do not support post-procesor effects.

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

view online version