Table of Contents

Zathras' Beginners FAQ

These are questions I have as a beginner, and the (current) answers I found. Status: I'm updating this to JME 2.0.


What is the jMonkeyEngine, why should I want to learn this?

The jMonkeyEngine project is for people who want to write 3-D computer games of their own. As an example, watch this movie of a 3-D game created with jme. You can learn how to write games like that! :) It's tough but worth it.

  • What is Java? The programming language Java allows you to write a game once, and run it 'everywhere' (that is: Windows, Mac OS, Linux). The Java Development Kit (JDK) contains tools to create general parts of applications, such as the application window, menus, data types, reading and writing files, input control.
  • What is the jMonkeyEngine framework? jME is a 3-D game engine. This framework extends the general development kit and adds special methods and objects for the development of 3-dimensional games. JME provides you with a 3-D scene graph, a main event loop, a camera view, methods for loading 3-D models and animations, 3-D audio, input control (keyboard, mouse, etc), collision detection, cool special effects (water, fire, particle swarms, cloth, etc), and more. See also complete_features_list and this jme review.
  • What is jME Physics? The optional jME Physics framework adds dynamics (gravity, momentum, friction, etc) to 3-D objects. You will use a Physics engine if you are developing dynamic games like pinball, pool, pong, car racing.


What you need (in this order)

  1. Java SE (standard edition)
  2. jMonkeyEngine
  3. Design and write your game!


What Files Do I Need to Get Started? (Checklist)

You needWhat for?From Where?
Java Development Kit (JDK)Tools to develop your project. Includes Java compiler, runtime, and more.sun.com
Build Tools: Ant or Maven, JUnitTools to automate clean/build/test/run cycleapache.org, junit.org
File version control: SubversionUtility to download latest version of JME sources tigris.org
Any 3-D mesh editorTool to create 3-D modelsSee below…
(LWJGL Java Game Library)OpenGL for 3D graphics, OpenAL for 3D sound(Included in JME)
(Jogg, Jorbis)Libraries for Ogg Vorbis sound(Included in JME)
jME sources and librariesThe 3-D Game Enginejmonkeyengine.com
Optional: The jME physics engine3-D game physicsjmephysics


Tip: Using an integrated development (IDE) environment is optional, but recommended. An IDE is a developer utility that integrates all your development tools (compiler, build tools, file version control, debugger, profiler, editor, documentation, etc) into one graphical interface and spares you some of the complications of the commandline. See also: All Netbeans Tutorials.


What is the Full List of Libraries?

Download jME_2.0_Complete and jME_2.0_Distribution


The jMonkeyEngine (jME_2.0_Distribution) These are all bundled in jME_2.0_Complete/jME_2.0.jar !

jme.jar             jme-effects.jar     jme-swt.jar
jme-audio.jar       jme-font.jar        jme-terrain.jar
jme-awt.jar         jme-gamestates.jar  jme-xml.jar
jme-collada.jar     jme-model.jar       jme-editors.jar     jme-scene.jar       


Third-party JAR libraries (jME_2.0_Complete/lib/)

gluegen-rt.jar      junit_4 swt.jar     jinput.jar
lwjgl.jar	    lwjgl_util.jar      lwjgl_util_applet.jar
jogl.jar            jorbis-0.0.17.jar	


Third-party native libraries (jME_2.0_Complete/lib/natives/)

OpenAL32.dll    openal.dylib          libopenal.so        libopenal64.so
lwjgl.dll       liblwjgl.jnilib       liblwjgl.so         liblwjgl64.so
odejava.dll     libodejava.jnilib     libodejava.so       libodejava64.so
jinput-dx8.dll  libjinput-osx.jnilib  libjinput-linux.so  libjinput-linux64.so	
jinput-raw.dll


What File Goes Where?

  • Create directories MyGame, MyGame/lib/ and MyGame/lib/natives/.
  • Build your game and put the file MyGame.jar in the directory MyGame.
  • Put all JAR files (bundled jME_2.0.jar plus third-party) in the directory called MyGame/lib/. (Otherwise you get a NoClassDefFoundError for jME classes.)
  • Put all third-party native libraries in the directory MyGame/lib/natives/. The directory of native libraries needs to be on your project's java.library.path! (Otherwise you'll get UnsatisfiedLinkError: no lwjgl in java.library.path)


This allows the Java Virtual Machine to find libraries when running the game like this:

  • java -jar -Xmx256m -Djava.library.path=“lib/natives” MyGame.jar


See also: getting_started, jme_maven_setup, packaging_and_deploying_jme_applications.


Troubleshooting: How to Fix Classpath / Java Library Path Issues?

What is the Java Classpath? For platform-independent Java Classes

  • JAR files containing Java classes, and sometimes resources (images, models, sound, etc)


What is the Java Library Path? For platform-dependent native dynamic libraries

  • Windows: .dll files
  • Linux: .so files
  • Mac: .jnilib and .dylib files
  • (Sometimes JARs)

jME won't work without those files in place, period.

Some troubleshooting tips for very common errors and warnings: (Don't worry, we all get these!)


java.lang.UnsatisfiedLinkError: no lwjgl in java.library.path

What does it mean? You are missing important native dynamic libraries (files like lwjgl.dll and many more) on the java.library.path.

First determine where the problem starts, is it in the IDE, in your app, the location of the libraries, your path settings?

Library Paths?

If yes, then:

  • Change into the directory where your application's JAR was created, and start the game from the command line
  • Example: java -jar -Xmx256m -Djava.library.path=“lib/natives” MyGame.jar

Typos? If your game can be started from the command line, you at least know that your Java game works, and your libraries are correctly set up. If this does not work, first make sure you have the libraries and paths right. (This HAS to work.)

  • Check all paths for typos, or weird quotation marks (very common source of error).

Do you use an IDE? If the game starts, but not from your IDE, configure the java library path in the project's Run settings as -Djava.library.path=“lib/natives” . (See individual IDE documentation for details.)

Another workaround… If the above doesn't work, move all native libraries from the lib/natives/ directory right next to your game's JAR. This may work because the java library path is set by default to search the libraries in the current working directory.

  • Advantage: This solution is easy and portable.
  • Disadvantage: It clutters the directory with a mess of files ;)

For Linuxers You can also add all the native libraries to the environment variable LD_LIBRARY_PATH. This is possible, but not generally recommended.

  • Disadvantage: Not exactly user-friendly, typing and exporting the paths is annoying and error-prone, solution is not portable.


NoClassDefFoundError

Which Java class does it say is missing?

  • Is it one of jME's classes, like BaseGame, SimpleGame? Then check whether all jME JARs are there, and on your classpath, as described above.
  • Is a third-party library reported missing (JUnit, Swing App Framework, Ogg Vorbis)? Then it's not jME's fault. Check the third-party's set-up instructions. Their JARs are missing on your classpath.
  • Is it one of your custom classes that's not found, like Main, or MyGame, etc? Check for typos in packages or classes. Maybe wrong working directory or wrong package? Also not jME's fault.


Application runs fine on one operating system but not on another?

Clearly missing or mislinked native libraries necessary for this operating system.


Just for fun: Some debugging code to check paths. PS: You cannot use this to set the environment variables, you can only read them after the fact!

System.out.println("java.library.path = " + System.getProperty("java.library.path"));
System.out.println("java.ext.dirs = " + System.getProperty("java.ext.dirs"));
System.out.println("java.class.path = " + System.getProperty("java.class.path"));


Where do I get Help, Documentation and Sample Code?

  • Run the jme project or jME_2.0.jar to get a TestChooser with sample applications!
    cd jME_2.0_Complete_(r4093); java -jar -Xmx256m -Djava.library.path="lib/natives"  jME_2.0.jar
    • Landscape: TestIsland
    • Steering a character over a terrain: TestThirdPersonController, TestFirstPersonController, TestObjectWalking
    • Aiming/shooting/picking: TestPick, TestTrianglePick, TestTerrainPick
    • Lots of cool effects: Particles, swarms, fire, bloom, blur, water, and more!
    • Flag Rush Tutorial
  • Then look at the example's source code in /jme/src/jmetest (/jmephysics/test, /jmephysics/test-interactive, and /jmephysics/tutorial) to learn from it!


Tip: Build the javadoc from the sources and open it in your webbrowser: file:/YOUR_PATH_TO_JME/jme/data/doc/index.html and file:/YOUR_PATH_TO_JME/jME-Physics_2/dist/javadoc/index.html


How do I get started: SimpleGame, SimplePhysicsGame, BaseGame??

First of all follow the great tutorials in jme/src/jmetest/ (and com/jmetest/physicstut respectively) to get started quickly: You begin with a SimpleGame with object nodes (and you can proceed to learn to create a SimplePhysicsGame with dynamic nodes). This way you can play and experiment, and learn the basics without bothering about implementation details at first.


It's fine to use SimpleGame for quick demos. When you got acquainted with the API, and want to start coding your actual game, you will want to be able to control all the implementation details yourself. Take some time to understand how SimpleGame and BaseSimpleGame are implemented to learn how to create your custom subclass of BaseGame.


Instance variables and methods, and where they were inherited from:

  • SimpleGame: update(), render();
    • BaseSimpleGame: rootNode, cam, timer; mouse and keyboard inputHandler (FirstPersonHandler); update(), render(); various render states and statistics;
      • BaseGame: start()
        • AbstractGame: display, logger, settings, setConfigShowMode(), finish().


One example for how you can proceed:

  • Use code snippets from BaseSimpleGame as template for a custom MyBaseGame class. Add or replace jME features such as First / ThirdPersonHandler, collision detection, water rendering passes, ParticleFactory, and set up your keyboard shortcuts.
  • Then derive a more concrete MyGame class from the MyBaseGame class: Make it provide easy-access setters for the mentioned jME features. Also allow general management of characters, terrains, colors, switching between fog and skybox–or for whatever it is YOUR game needs in particular.
  • From MyGame you derive the actual game. It uses getters and setters and loads actual content into this frame that you have prepared.


What elements Does a jMonkey 3D BaseGame Consist of?


The Game System

  • Display system – The main window where everything happens
  • Input handlers – Respond to mouse and/or keyboard input
  • Camera – A means to peek into the 3D world
  • Timer – To calculate frames per second.
  • PhysicsSpace (optional) – Real physics with gravity and friction


Important Methods

  1. initSystem() – Initialization of the jMonkeyEngine System.
  2. initGame() – Initialization of your game world. Load your stuff (3D models, animations) and attach everything to the rootNode.
  3. Main event loop:
    1. update() – Respond to user input or timer, update the game state…
    2. render() – … and draw game data to the screen.
  4. cleanup() – Clean up objects and save before exit.


The Content: Scene Graph and States

Scene graph: – A data structure to store geometrical objects in 3-D space.

  • Root node – The top of the scene graph. All object nodes are attached to a root node.
  • Leaf nodes – The actual objects you want to show (houses, cars, characters…)
  • Light nodes (optional) – To attach lights to something in-game. Has a light state.
  • Text node (optional) – To display 2-D text elements on screen. (Not attached to the root node.)

States: – Rendering settings used by the 3-D engine for each node

  • ZBuffer state – A render state for the correct rendering of spatial depth
  • Light state (optional) – A render state that allows you to see colors and shadows


What's Spatial, Geometry, Node?

The scenegraph is a tree structure of nodes, with a root, branches and leaves. Each element in your scene (root nodes, branch nodes, leaf nodes) is referred to as spatial. Only leaf nodes are visible to your players, the rest is game internal.

  • All Spatials are attached to a root node.
  • A Spatial is either a Geometry or a Node.
    • A Node with Geometry is a visible object. It can never have any child nodes itself, that's why it's also called a Leaf. For example your Terrain, players, objects, buildings…
    • A Node without Geometry is invisible, it's an internal branch of the scenegraph tree. A Node can have a child node attached to it, or a leave. Examples for invisible nodes are camera nodes, light nodes, rootNode, or a node used for grouping together all parts of character or building.
    • A text node is visible, but it's not attached to the root node. (??)
  • A node can group Spatials (which each can have Nodes and Geometries of their own). By attaching Nodes to a parent Node, they move together (Example: Wheel nodes move together with the car node).
Root Node
scene graph
A Spatial
Rotation, Translation, Scale
World Bounding Volume
Render States
Geometry Node
All vertices (corner points)Bounding Volume of all child nodes
Local Bounding volumeLinks to its child spatials (Node and Geometries)
Optional: Solid color

See also: graphic


What are Render states?

While a geometry defines a objects's shape, a render state describes how this object should look, how it is rendered. Each Node has render states, if you don't define any, it will have the same as its parent node. You can group nodes that should be rendered the same under one node that carries a specific render state (e.g. all UI elements, all transparent things, etc).


Usage:

  • LightState, CullState: Specify the default light and cull render states for one node (e.g. the rootNode), and it inherits these settings to all its child nodes. Usually all objects have the same light and cull states.
  • Child nodes can always overwrite default states with custom values if necessary.
  • TextureState, MaterialState, BlendState: Specify these individually. Usually, each object (or even part of it) has a different surface.
  • You can create several States (e.g. LightStates) with various looks to store certain settings. Then swap one state for the other to change the appearance of your world (e.g. when an alarm goes off, a light node's state may switch from white to red).

Which Render State Does What?

  • zBufferState (does the object have 3-D depth, or is it a flat user interface element?)
  • LightState (does it have colors and shadows?) – does not say “which color”
  • CullState (draw all faces, none, front or back of object?) – e.g. show/hide objects
  • WireState (draw objects' faces or just the wireframes?) – for debugging, scientific displays
  • TextureState (what's the surface like?) – a picture
  • MaterialState (what material is the surface made of?) – shininess etc
  • BlendState in jME2.0, AlphaState in jME1.0 (is it transparent or opaque?)
  • FogState (should this be affected by fog in the distance?)


All are optional, but I sorted them by how commonly I guess they are used.

Render State Tips

  • If you set one of the states twice for a Node, only the last value counts.
  • Nothing happening? Don't forget to setEnabled() to true. Are the nodes attached to the right (root)nodes?
  • Too much happening? For LightStates and TextureStates, the settings for parent and child add up! (e.g. light twice as bright)
  • After each change during the live game call rootNode.updateRenderState(); .
  • Use groupings: For example, attach a transparentThingsNode to the rootNode. Set the transparentThingsNode's BlendState, and attach all permanently transparent nodes to the transparentThingsNode (e.g. solid window panes).
  • Use CullState for back-face culling. It means only drawing the minimum (that is, only the visible side!) of an object, which improves performance.
  • Code sample:
ZBufferState buf = display.getRenderer().createZBufferState();
buf.setEnabled(true);
buf.setFunction(ZBufferState.CF_LEQUAL);
rootNode.setRenderState(buf);
 
LightState ls = display.getRenderer().createLightState();
ls.setEnabled(true);
rootNode.setRenderState( lightState );
ls.attach(light5);


How Do I Create My Game World (3-D Models)?

For a simple test world, you attach the built-in spheres and boxes of the game engine to the rootNode, as demonstrated in the tutorials.
For more complex objects like houses, characters and vehicles, you need to create models in a 3-D mesh editor. See next:


Which 3-D Mesh Editors Are There?

These 3-D mesh editors are free, and platform-independent for Mac/Win/Linux:

  • ArtOfIllusion (Intuitive, easy to learn for beginners, animations; exports only to a few formats.)
  • Google Sketchup (User-friendly interface, good for quick rough models or buildings; no animations.)
  • Blender (Advanced features, supports animation, lots of formats; takes quite a while to learn.)
  • Wings3d (Easy learning curve, good for building foundational models for detailing in other 3D modelers; basic toolset though)


Which 3-D Formats Are Good For What?

Which formats does jME import? Have a look at com.jmex.model.XMLparser.Converters.*

  • ColladaToJme (.dae file, free and open 3-D standard, importer a bit buggy?)
  • AseToJme (.ase file, no animation),
  • MaxToJme (.3ds file, no transparency),
  • md2ToJme (.md2 file),
  • md3ToJme (.md3 file),
  • milkToJme (.ms3d file),
  • X3dToJme (.x3d file, for 3-D images in web browser)
  • ObjToJme (.obj and .mtl files, no transparency, see also exporting_.obj_models_from_blender)

Add-Ons:


Most 3-D editors can export and import at least 3D Studio Max (.3ds) and Wavefront Object (.obj/.mtl) well, both of which can be read by the jmonkeyengine. They have advantages (3ds supports animation) and disadvantages (obj does not support transparency. 3ds loses transparency after import?). I haven't tested all of them yet…


Currently my favorite format for static models is Collada (.dae). There is a free plugin for Blender that lets you export a static model as Collada including transparency. For animated objects, try md5Reader.
Tip: How to export Collada files from Sketchup? Export model as .kmz file, rename suffix to .zip, unzip file, rename suffix to .dae!


Open Question: Will Blender's Collada exporter ever export textures, animations? Will jMonkeyEngine import collada+textures?


Model Loading Code Samples

    public Node loadMy3DSModel(){
        Node gamemap = new Node();
        URL modelURL=MyGame.class.getClassLoader().getResource("data/model/mymodel.3ds");
        URL textureURL=MyGame.class.getClassLoader().getResource("data/model/");
        BinaryImporter importer = BinaryImporter.getInstance();
        FormatConverter converter=new MaxToJme(); // com.jmex.model.XMLparser.Converters.*
        ByteArrayOutputStream BO=new ByteArrayOutputStream();
        try {
            converter.convert( modelURL.openStream(), BO );
            gamemap=(Node)BinaryImporter.getInstance().load(new ByteArrayInputStream(BO.toByteArray()));
            gamemap.setCullMode( SceneElement.CULL_NEVER );
            gamemap.setModelBound( new BoundingBox() );
            gamemap.updateModelBound();
        } catch (IOException e) {
            e.printStackTrace();
            System.exit(0);
        }
        return gamemap;
}
 
   public Node loadMyColladaModel() {
        // your path to the model's textures inside YourGame
        URL url = YourGame.class.getClassLoader().getResource("data/model/");
        //you path to the model itself inside YourGame.
        InputStream gamemap = YourGame.class.getClassLoader()
       .getResourceAsStream("data/model/mycoolmodel.dae");
        if (gamemap == null) {
            System.out.println("Collada data file not found");
            System.exit(0);
        }
        ColladaImporter.load(gamemap, url, "model");
        Node n = ColladaImporter.getModel();
        n.setModelBound(new BoundingBox()); // collision detection
        n.updateModelBound(); // collision detection
        return n;
    }


How Do I Create, Load, Play Animations?

  1. Learn about skeletal animation and kinematic animation.
  2. Create the animation in a 3-D mesh editor like Blender or AoI.
  3. Save and export file in a format that supports animation, such as MD5: exporting_animated_.md5_models_from_blender
  4. Use the file in the jME project: See jmetest/renderer/TestSimpleBoneAnimation.java and jmetest/TutorialGuide/HelloAnimation.java.


How Do I Load Transparent Objects/Textures?

Attach all transparent objects to a node with a transparent BlendState, or set the object's individual BlendState.
When blending, what is Alpha Test, Reference Value, Source and Destintion? See: http://www.opengl.org/resources/faq/technical/transparency.htm


What about objects that are part opaque, part transparent? (e.g. house with windows.) Idea: Split these things apart and load them half and half (first all opaque walls and floors, then all window panes)?

Textures: Wrapping, MIP map, and UV-what?

  • Texture wrapping: One image repeats over all sides of a 3D object. The seams in the texture must trivially match. Good for simple things like crates and balls.
  • jME's MultiFaceBox shape class: Each face of the cube can have its own texture. Again you must make all the seams match. Good for buildings, shelves, telephone booths, etc.
  • UV texture mapping: Design this textures to look like a flat sewing pattern. One image contains the front, back and side looks of the object. Certain areas of the flat texture (UV coordinates) are then mapped onto certain areas of your 3D model (XYZ coordinates). Ideal for game characters' clothes and faces–getting the seams perfectly right is crucial here. More...
  • MIP Map texture: You have to provide the texture in two or three resolutions to be stored in one file (MIP = “multum in parvo”). Depending on how close (or far) the camera is, the engine automatically renders a more (or less) detailed texture for the object. Thus objects look smooth from close up, but don't waste resources with unspottable details when far away. Good for everything, but requires more time to create and more space to store textures. (jME: pass a texture unit of 0 or 1 to a TextureState's setTexture() calls.)
  • Height map: If you use a 2-D grayscale pattern for terrain height information, then textures can depend on height too. E.g. mountain tops are white, on land there's grass, and below sea level is sand. (jME: com.​jmex.​terrain.​util.ProceduralTextureGenerator)
  • Procedural texture: These textures are generated from one image, but with small random changes. This procedure makes any seams match up well, and makes the texture look irregular and natural. Ideal for irregular things like grass, soil, and natural walls. (jME: com.​jmex.​terrain.​util.ProceduralTextureGenerator)


Optimal sizes for textures are 16*16, 32*32, 64*64, 128*128, 256*256, 512*256 (Is this a graphic card requirement?) Note: For TerrainPages it's that number +1 for some reason.


How do I Make Skies and Terrains?

A sky box (com.jme.scene.Skybox;) or sky dome is an artificial horizon and sky for your 3D world. It is a quick and efficient way to make the environment look more realistic.

http://www.planetside.co.uk/

Also look at the Terrains samples to use things such as com.jmex.terrain.TerrainPage. Terrains can be generated from a 2-D grayscale bitmap file (darker is lower, lighter is more elevated).


Why is Everything So Bright/Dark?

  • If your objects are shown colorless and plain gray/white: Did you create a light state? Did you light.setEnabled(true)? (Or setAttenuate(true) if you use that)? Did you set the root node's renderState to this LightState? Did you attach a light to the lightState?


  • If your objects appear colored, but they are too dark or too bright: Your light state works, so check your light settings: Light color? (Diffuse? Ambient?) Attenuation? Alpha? Too many or two few lights? (Remember that lights add up.)


  • If you use a height map together with a procedural texture, the texture turns very dark when it's out of range of the min/max values you specified.


  • Tip: Check whether you exported the model correctly (e.g. “inward- vs outward-pointing surface normal” setting makes it look different).


See also: Light JavaDoc


Collision Detection


Why Does Stuff Keep Falling Through the Ground?

If your dynamic objects fall through the floor:

  • Did you follow the SyntheticButton stuff in Lesson 8 of the physics tutorial?
  • Did you create and apply a Material to both “floor” and dynamic nodes?
  • Did you attach all collidable child nodes to the “floor” node?
  • Did you call generatePhysicsGeometry() on both “floor” and dynamic node after setting them up?
  • Did you call setModelBound(new BoundingBox()) (or BoundingSphere), updateModelBound(), setCenterOfMass(), and computeMass() on the dynamic node? In this order?

For non-physical games, have a look at the TestObjectWalking class and “how to implement walking” below.


Why are There Invisible Barriers Around Things?

You keep bumping into invisible barriers in door frames, your cubes roll downhill, and your spheres sit on slopes like blocks… What the heck is going on?

  • First toggle on the bounds to see where jME calculated them to be. (showBounds=true) Are they how you would expect?
  • If you see BoundingSpheres around angular things like walls or cubes, this can have unexpected side-effects. It means straight walls are treated as if convex, ceilings are treated as domes, cubes are treated as balls, etc. For the testplayer this appears as if there were invisible obstacles wrapped around everything. To fix the bounds' shape, use myCrate.setModelBound(new BoundingBox()).
  • In the opposite case, you see BoundingBoxes around spheres, so they don't behave like spheres, but have invisible corners and edges. Then reset the bounds with myRock.setModelBound(BoundingSphere()).


Tip 1: Bounds are either Box or Sphere. You can only set the Bound shape once per model, but it affects each part of the model individually. E.g., if you have a building with BoundingBox set as Bound, it will not be one big block, but each wall and each floor is treated as one box, the way you would expect it.


Tip 2: If there are grouped objects inside an imported model, the whole group will get one BoundingBox (or BoundingSphere)! This can be an effect that you want – or it may accidentally fill up corners and doorframes with invisible barriers.


Tip 3: Bounding Spheres cannot be elliptical in jMonkeyEngine, but you can put two spheres on top or next to each other for a similar bounding effect.


Modifying Stubborn 3-D Objects

Why Does Nothing Happen when I Set Translation, Rotation, Texture?

Very common question regarding updating the scenegraph state.

  • Make sure the Spatial is attached to the root node, and the Node to the Spatial, etc.
  • Make sure you use thing.getLocalTranslation().set() to move the thing to a position, thing.getLocalScale().set() to change its size, and thing.getLocalRotation().set() to turn or tilt it. Do not use getWorldTranslation().set() nor setLocalTranslation() etc.
  • After removing, adding, translating, scaling or rotating a spatial, always call updateGeometricState() (low-cost).
  • After adding a spatial, or changing a render state (Material, Light, Texture), always call updateRenderState() (expensive, use sparingly).
  • After adding a model that needs triangle accuracy on picking and collision detecting, call updateCollisionTree() once.
  • After setModelBound(), always call updateModelBound().

See also updatefuncs.


How Can the Player Turn and Look at Something?

Use player.lookAt(v1,Vector3f.UNIT_Y) (UNIT_Y just means he should stand upright).

/* player looks in same direction as camera */
input.addAction( new PlayerMouseLookAt() ,
                InputHandler.DEVICE_MOUSE, InputHandler.BUTTON_NONE, InputHandler.AXIS_ALL, false );
...
 private class PlayerMouseLookAt extends InputAction {
        DynamicPhysicsNode player;
        public PlayerMouseLookAt() {
        }
 
        public void performAction(InputActionEvent e) {
            if ( e.getTriggerDelta() != 0f ) {
                Vector3f v = new Vector3f( player.getWorldTranslation().x,
                                           player.getWorldTranslation().y,
                                           player.getWorldTranslation().z );
                v.addLocal( cam.getDirection().x, 0f ,cam.getDirection().z );
                player.lookAt( v , Vector3f.UNIT_Y );
            }
        }
    }



Why are my imported models the wrong way round?

This happens if your 3D editor uses different coordinate system axes than the jmonkeyengine. Rotate your object back after you load it, for example:

model.setLocalRotation( new Quaternion().fromAngleAxis( - FastMath.PI/2, new Vector3f(1,0,0)) );


Open question: I imported an existing model into Blender and edited it. After export to Collada, the pre-existing parts of the model are shown correctly in jME, but all the edits and additions I did using Blender are distorted (wrong scale, tilted)?! Work-around: Use the following settings in Blender's Collada exporter: Triangles YES, Bake Matrices NO, disable physics NO, only current scene NO, use relative path YES, use UV image NO.


Handy Rotation Constants

Keep these rotation constants handy so you don't have to type the whole quaternion every time.

    public static final Quaternion ROLL045  = new Quaternion().fromAngleAxis(FastMath.PI/4,   new Vector3f(0,0,1));
    public static final Quaternion ROLL090  = new Quaternion().fromAngleAxis(FastMath.PI/2,   new Vector3f(0,0,1));
    public static final Quaternion ROLL180  = new Quaternion().fromAngleAxis(FastMath.PI  ,   new Vector3f(0,0,1));
    public static final Quaternion ROLL270  = new Quaternion().fromAngleAxis(FastMath.PI*3/2, new Vector3f(0,0,1));
    public static final Quaternion YAW045n  = new Quaternion().fromAngleAxis(- FastMath.PI/4, new Vector3f(0,1,0));
    public static final Quaternion YAW045   = new Quaternion().fromAngleAxis(FastMath.PI/4,   new Vector3f(0,1,0));
    public static final Quaternion YAW090   = new Quaternion().fromAngleAxis(FastMath.PI/2,   new Vector3f(0,1,0));
    public static final Quaternion YAW180   = new Quaternion().fromAngleAxis(FastMath.PI  ,   new Vector3f(0,1,0));
    public static final Quaternion YAW270   = new Quaternion().fromAngleAxis(FastMath.PI*3/2, new Vector3f(0,1,0));
    public static final Quaternion PITCH045 = new Quaternion().fromAngleAxis(FastMath.PI/4,   new Vector3f(1,0,0));
    public static final Quaternion PITCH090 = new Quaternion().fromAngleAxis(FastMath.PI/2,   new Vector3f(1,0,0));
    public static final Quaternion PITCH180 = new Quaternion().fromAngleAxis(FastMath.PI  ,   new Vector3f(1,0,0));
    public static final Quaternion PITCH270 = new Quaternion().fromAngleAxis(FastMath.PI*3/2, new Vector3f(1,0,0));
    public static final Quaternion UPRIGHT  = new Quaternion().fromAngleAxis(- FastMath.PI/2, new Vector3f(1,0,0));


Player Motion: Walking, Climbing, Swimming, Flying

If you want more than walking, consider introducing a roaming_mode variable for the player. It keeps track of mutually exclusive maneuvering states such as standing/walking/running, floating/flying/rising, hanging/climbing/ascending, treading_water/swimming/diving, jumping. (Use an enum.)

All these states typically go along with different speeds and different animations.

The point of view can be a first-person or third-person character (the difference is where the camera is attached).

How Do I Implement Walking?

Have a look at the TestObjectWalking sample. In short:

  • Set up a camera that responds to arrow key input by moving.
  • Cast a ray straight down from the camera. (A ray is a line with a fixed beginning, a direction, and no end.)
  • Test where the ray intersects with the triangles of the floor. This is your loc.
  • Keep re-setting the camera's position to loc+player_height. If there's an third-person-view avatar, move it there, too.
  • This way the avatar walks smoothly “like on rails” on the terrain ground. It will even jump on top of obstacles.
  • Needs testing: What about walking upstairs and on loaded building models' floors?


Why is the Ground Solid, But Walls Are Not?

Concerning non-physical games based on the method proposed in TestObjectWalking:
When using the idea proposed in the TestObjectWalking class, the avatar will be able to walk on floors, but it still walks right through walls. This is because the algorithm only tests for triangles directly under the player's fleet. Walls and other vertical objects are not covered by this algorithm. It needs to be extended to detect walls.


Idea: Attach all wall objects to one wallsRootNode. Use hasCollison on this wallsRootNode and the player. This way you only test collision with potential walls and not waste time testing everything in the scenegraph (no need to test the floor nodes too, for instance). If Collision, stop player from walking on by setting its velocity to e.g. a negation of its current speed (bounces off obstacle) or to zero.

See colliding with the walls tutorial and sample code for the Flag Rush tutorial lesson 10.


See how player velocity is implemented in Vehicle.java:

public void update(float time) {
    this.localTranslation.addLocal(this.localRotation.getRotationColumn(2, tempVa).multLocal(velocity * time));
...


How Do I Implement Flying or Jumping?

First implement walking and the roaming_mode enum. The player is stuck to the floor…

Idea:

  • Introduce a variable that keeps track of the altitude.
  • Add a test to the update() method that handles walking: Skip resetting the camera loc to walking height if flying/jumping/etc.
  • Define a key that triggers flying/jumping.
  • If the player is in flying roaming_mode and presses arrow keys:
    • Keep track of the height in the altitude variable. Keep re-setting the loc of the camera to flight altiude.
    • Decide with which flying behaviour to respond to arrow key input (can it turn in place like a helicopter, or does it bank and yaw like an airplane?) and change the animation and position accordingly. …?
    • Decide which rising/falling behaviour your character has. (Does it have to flap wings constantly to stay up, does it stay afloat, does it constantly rise like a hot air balloon?)

…?

How Do I Implement Swimming?

First implement walking and the roaming_mode enum. The player will walk to the bottom of any body of water…

Idea: (I assume here the water surface is a Quad.)

  1. Check for collision with the water surface (Quad) and check player position:
    1. If less than one third of character is below water surface, play splashing sound, walk on slower.
    2. If between 1/3 and 2/3 of character is below water surface, play gushing sound, walk on very slowly.
    3. If between 2/3 but not all of character is below water surface, play paddling sound, change animation to swimming/treading_water.
    4. If character is below water surface, play underwater sound, change animation to diving.

How Do I Implement Climbing?

First implement walking and the roaming_mode enum. The player will run uphill too easily…

General idea – Just a guess: Determine the slope of the triangle the character stands on (in calculus terms: the 1st derivative of a line tangent to the terrain at this point). Let's assume that your characters can handle anything up to a 100% = 45° slope.

  • Everytime the player walks, test the slope, and determine whether you allow this step.
    • To obtain the slope, look at the triangle detection in TestObjectWalking's TrianglePickResults.
    • We know three vectors of the triangle (“plane”) the character is standing on. We need (x/y) coordinates of two triangle points p1 and p2 for the slope. TODO: Which two?
    • Slope m = (y2-y1) / (x2-x1).
    • Slope results (approximations):
      • m=0.0f is 0°, flat ground.
      • m=0.25f is 15° steep.
      • m=0.5f is 30° steep.
      • m=1.0f is 45° steep.
      • m=2.0f is 65° steep.
      • m=3.0f is 73° steep.
      • m=4.0f is 77° steep etc.
      • m=inf is 90°, a wall.
  • Change the animation from walking to climbing (from standing to hanging_on), respectively.
  • If it's very steep the character might even slide downhill as soon as he stops – how to implement that?

Consider slowing down walking speed according to steepness and skill!

  • Each character can have a climb skill value (whether he can climb steeper things as 45°, and how fast).
  • Everything steeper than 45° slope depends on this skill level.
  • 100% skill might mean he can even climb up all 90° walls like a fly or spiderman…

How Do I Implement Shooting, Buttons, Switches?

Mouse Picking is the keyword here. Have a look at the com.​jme.​intersection.* package.

Demos such as MousePick + TestPick show you how to determine what (which object, which mesh) the user clicked.

  • Listen to mouse input and wait for clicks. For each click:
    • Cast a ray in the direction the camera is pointing. (A Ray extends from one point infinitely in one direction)
    • Calculate the intersection of the ray with the bounding volumes of all children of the rootnode.
    • Loop over the pick results and send appropriate notifications.
  • Idea: Attach all clickable objects of a scene to one actionNode, then you can restrict testing to that node. Unless all or most of your nodes are clickable, then the rootNode is fine.

Results accuracy: You can retrieve information about which mesh was clicked (com.jme.intersection.BoundingPickResults). You can even set it to determine which triangle on the mesh was clicked (com.jme.intersection.TrianglePickResults).

You can respond to clicks (com.jme.input.action.mouseInputAction) or keyboard input (com.jme.input.action.KeyInputAction) in a similar way.

/* as part of game initialization: */
MousePick pick = new MousePick(cam, clickableNode, ...);
input.addAction(pick);
public class MousePick extends MouseInputAction {
 
    public MousePick(Camera camera, Node scene, ...) { /* init variables */  }
 
    public void performAction(InputActionEvent evt) {
        clickTime += evt.getTime();
        if( MouseInput.get().isButtonDown(0) && clickTime > 0.1f) {
            clickTime = 0;
            Ray ray = new Ray(camera.getLocation(), camera.getDirection()); /* Line of sight */
            PickResults results = new BoundingPickResults(); /* Set accuracy */
            results.setCheckDistance(true);  /* Order results closest first */
            scene.findPick(ray,results);     /* List everything in line of sight */
            if(results.getNumber() > 0) {
                for(int i = 0; i < results.getNumber(); i++) {
                    /* Now analyse what was clicked... */
                    System.out.println( results.getPickData(i).getTargetMesh().getName() );
                    System.out.println( results.getPickData(i).getDistance() );
                    /* ... and respond by informing the controller. */
                }
            }
            results.clear();
        }
    }
}


How Do I Keep Dynamic Objects From Sliding or Toppling Over?

This is a jME physics-related question.


Sliding: Your objects slide unstoppably up and down hills as if on ice?

  • Define MutableContactInfo and Materials for floor/world and objects.
  • Create a Material with contactDetails.setMu( Float.POSITIVE_INFINITY ) which does not slide.
  • See Lesson 3 of the physics tutorial, and com.jmex.physics.material.Material.*.


Shivering: Does the Physics engine constantly recalculate the object's rotation on uneven ground, so it starts shivering or dancing?

  • Don't use setLocalTranslation() and setLocalRotation() to move objects–you must use Forces and Torque.
  • If it makes sense in your case, try locking the object's bounds upright (thing.lockBounds()). This method isn't good if you need collision detection to consider the character's real shape in widely different stages of animation.


Toppling over: Even little obstacles make your object fall over?

  • This means that the center of mass is too high. To move it lower: player.setCenterOfMass( new Vector3f( 0, -0.5f, 0 ) );
  • The center of mass can also be too low, then the character does not fall over but starts swinging like a pendulum.
  • Physical forces work best on things that don't topple easily: Round objects like balls; or low, wide, and angular objects such as vehicles.


Tip: Physics generally only make sense for objects with physcial behavior, typically things such as cars driving with a shock-absorbing suspension, bouncing/rolling balls, and falling/shifting boxes. Do not use physics for tall characters walking on the ground, they will not behave as expected. A walking person's motion does not correspond to a physical object being pushed around by a mechanical forward force. For characters see: TestObjectWalking sample.


How Do I Save Games and Levels?

Learn about Java Serialization. In short:

  1. Make your saveable custom object (e.g. a game level) implement the Serializable interface. And all the sub objects it depends on, too! Start at the bottom.
  2. First create a write() method that takes the object apart into its primitives and writes them to a file.
    1. Don't write values that can easily be recalculated, or restored from data files like height map images and 3-D models.
  3. Then create a read() method that reads primitives in the same order that you wrote them!
    1. The read() method must be able to construct your object from what the write() method wrote (plus auxiliary calculations).

If you change the read/write order, or any data type in your object, the serialization will break–and you will not be able to load any previously saved files! So do this after finalizing your datatypes.


My Game is Stuck in the IDE, How Do I Distribute It?

The folowing IDE related tutorial contains a section about Generating a Distribution that is also useful if you do not use an IDE.


The following article shows you in general how to package and deploy your jME game: packaging_and_deploying_jme_applications


Tip: You can create a JAR launcher file (.bat, .sh) for your operating system that calls for example java -jar -Xmx256m -Djava.library.path=“lib/natives” MyGame.jar . Keep it in the same directory next to the libraries (in lib) and natives (in lib/natives). Execute the launcher to start the JAR.


/var/www/wiki/data/pages/zathrasbeginnersfaq.txt · Last modified: 2009/12/14 10:54 by zathras  
Recent changes · Show pagesource · Login

Recent changes RSS feed Creative Commons License Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki

subscribe to jME latest jme headlines


site design by bleedcrimson designs © 2008