Like <ahref="/com/jme3/gde/docs/jme3/advanced/shape.html">Shape</a>s, 3D models are also made up of <ahref="/com/jme3/gde/docs/jme3/advanced/mesh.html">Mesh</a>es, but models are more complex than Shapes. While Shapes are built into jME3, you typically create models in external 3D Mesh Editors.
</p>
</div>
<!-- EDIT1 SECTION "Models and Scenes" [1-226] -->
<h2><a>Using Models and Scenes with jME3</a></h2>
<h2>Using Models and Scenes with jME3</h2>
<div>
<p>
To use 3D models in a jME3 application:
</p>
<ol>
<li><div> Export the 3D model in Ogre <acronymtitle="Extensible Markup Language">XML</acronym> or Wavefront OBJ format. Export Scenes as Ogre DotScene format.</div>
<li><div> Export the 3D model in Ogre XML or Wavefront OBJ format. Export Scenes as Ogre DotScene format.</div>
</li>
<li><div> Save the files into a subdirectory of your jME3 project's <code>assets</code> directory.</div>
</li>
@ -25,17 +23,16 @@ To use 3D models in a jME3 application:
<li><div> (For the release build:) Use the jMonkeyEngine <acronymtitle="Software Development Kit">SDK</acronym> to convert models to .j3o format. You don't need this step as long you still develop and test the aplication within the jMonkeyEngine <acronymtitle="Software Development Kit">SDK</acronym>.</div>
<li><div> (For the release build:) Use the jMonkeyEngine SDK to convert models to .j3o format. You don't need this step as long you still develop and test the aplication within the jMonkeyEngine SDK.</div>
</li>
</ol>
</div>
<!-- EDIT2 SECTION "Using Models and Scenes with jME3" [227-901] -->
<h2><a>Creating Models and Scenes</a></h2>
<h2>Creating Models and Scenes</h2>
<div>
<p>
To create 3D models and scenes, you need a 3D Mesh Editor such as <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://www.blender.org/"><paramname="text"value="<html><u>Blender</u></html>"><paramname="textColor"value="blue"></object>, with an OgreXML Exporter plugin.
</p>
@ -45,7 +42,6 @@ To create 3D models and scenes, you need a 3D Mesh Editor such as <object classi
<p>
3D model editors are third-party products, so please consult their documentation for instructions how to use them. Here is an example workflow for Blender users:
</p>
<ul>
<li><div><ahref="/com/jme3/gde/docs/jme3/external/blender.html">Creating jME3 compatible 3D models in Blender</a></div>
@ -53,13 +49,12 @@ To create 3D models and scenes, you need a 3D Mesh Editor such as <object classi
</ul>
<p>
To export your models as Ogre <acronymtitle="Extensible Markup Language">XML</acronym> meshes with materials:
To export your models as Ogre XML meshes with materials:
</p>
<ol>
<li><div> Open the menu File > Export > OgreXML Exporter to open the exporter dialog.</div>
</li>
<li><div> In the Export Materials field: Give the material the same name as the model. For example, the model <code>something.mesh.xml</code> goes with <code>something.material</code>, plus (optionally) <code>something.skeleton.xml</code>, and some <acronymtitle="Joint Photographics Experts Group">JPG</acronym> files.</div>
<li><div> In the Export Materials field: Give the material the same name as the model. For example, the model <code>something.mesh.xml</code> goes with <code>something.material</code>, plus (optionally) <code>something.skeleton.xml</code>, and some JPG files.</div>
</li>
<li><div> In the Export Meshes field: Select a target subdirectory of your <code>assets/Models/</code> directory. E.g. <code>assets/Models/something/</code>.</div>
</li>
@ -82,10 +77,9 @@ To export your models as Ogre <acronym title="Extensible Markup Language">XML</a
</ol>
<p>
You can now use the <ahref="/com/jme3/gde/docs/sdk.html">jMonkeyEngine SDK</a> to <ahref="/com/jme3/gde/docs/sdk/model_loader_and_viewer.html">load and view models</a>. You can <ahref="/com/jme3/gde/docs/sdk/scene_composer.html">create scenes</a> from them and write code that loads them into your application.
</p>
</div>
<!-- EDIT3 SECTION "Creating Models and Scenes" [902-] -->
In 3D games, you do not only load static 3D models, you also want to be able to trigger animations in the model from the Java code.
</p>
</div>
<!-- EDIT1 SECTION "Animation in jME3" [1-167] -->
<h2><a>Requirements</a></h2>
<h2>Requirements</h2>
<div>
<p>
JME3 only loads and plays animated models, it does not create them.
</p>
<p>
What is required for an animated model? (<ahref="/com/jme3/gde/docs/jme3/terminology#animation.html">See also: Animation terminology</a>)
What is required for an animated model? (<ahref="/com/jme3/gde/docs/jme3/terminology.html#animation">See also: Animation terminology</a>)
</p>
<ol>
<li><div> For each model, you have to segment the model into a skeleton (<strong>bone rigging</strong>). </div>
@ -32,7 +30,6 @@ What is required for an animated model? (<a href="/com/jme3/gde/docs/jme3/termin
</ol>
<p>
Unless you download free models, or buy them from a 3D artist, you must create your animated models in an <strong>external mesh editor</strong> (for example, Blender) yourself.
</p>
<ul>
@ -51,7 +48,6 @@ Unless you download free models, or buy them from a 3D artist, you must create y
</ul>
<p>
What is required in your JME3-based Java class?
</p>
<ul>
@ -63,7 +59,7 @@ What is required in your JME3-based Java class?
Create one <code>com.jme3.animation.AnimControl</code> object in your JME3 application for each animated model that you want to control. You have to register each animated model to one of these Animation Controls. The control object gives you access to the available animation sequences in the model.
</p>
<pre> AnimControl playerControl; // you need one Control per model
@ -101,16 +96,15 @@ Create one <code>com.jme3.animation.AnimControl</code> object in your JME3 appli
</div>
<!-- EDIT5 SECTION "The Animation Control" [2984-3623] -->
<h3><a>Animation Channels</a></h3>
<h3>Animation Channels</h3>
<div>
<p>
An Animation Control has several Animation Channels (<code>com.jme3.animation.AnimChannel</code>). Each channel can play one animation sequence at a time.
</p>
<p>
There often are situations where you want to run several animation sequences at the same time, e.g. "shooting while walking" or "boxing while jumping". In this case, you create several channels, assign an animation to each, and play them in parallel.
There often are situations where you want to run several animation sequences at the same time, e.g. “shooting while walking” or “boxing while jumping”. In this case, you create several channels, assign an animation to each, and play them in parallel.
The following information is available for an AnimControl.
</p>
<div><table>
<thead>
<tr>
<th>AnimControl Property</th><th>Usage</th>
</tr>
</thead>
<tr>
<td>createChannel()</td><td>Returns a new channel, controlling all bones by default.</td>
</tr>
@ -153,9 +147,11 @@ clearListeners() </td><td>Adds or removes listeners to receive animation related
</tr>
</table></div>
<!-- EDIT8 TABLE [4360-4829] --><div><table>
<thead>
<tr>
<th>AnimControl Property</th><th>Usage</th>
</tr>
</thead>
<tr>
<td>setAnimations(aniHashMap)</td><td>Sets the animations that this AnimControl is capable of playing. The animations must be compatible with the skeleton given in the constructor.</td>
</tr>
@ -167,16 +163,18 @@ removeAnim(boneAnim)</td><td>Adds or removes an animation from this Control.</td
<td>getAnimationNames()</td><td>A String Collection of names of all animations that this Control can play for this model.</td>
</tr>
<tr>
<td>getAnim("anim")</td><td>Retrieve an animation from the list of animations.</td>
<td>getAnim(“anim”)</td><td>Retrieve an animation from the list of animations.</td>
</tr>
<tr>
<td>getAnimationLength("anim")</td><td>Returns the length of the given named animation in seconds</td>
<td>getAnimationLength(“anim”)</td><td>Returns the length of the given named animation in seconds</td>
</tr>
</table></div>
<!-- EDIT9 TABLE [4831-5391] --><div><table>
<thead>
<tr>
<th>AnimControl Property</th><th>Usage</th>
</tr>
</thead>
<tr>
<td>getSkeleton()</td><td>The Skeleton object controlled by this Control.</td>
</tr>
@ -184,24 +182,24 @@ removeAnim(boneAnim)</td><td>Adds or removes an animation from this Control.</td
<td>getTargets()</td><td>The Skin objects controlled by this Control, as Mesh array.</td>
</tr>
<tr>
<td>getAttachmentsNode("bone")</td><td>Returns the attachment node of a bone. Attach models and effects to this node to make them follow this bone's motions.</td>
<td>getAttachmentsNode(“bone”)</td><td>Returns the attachment node of a bone. Attach models and effects to this node to make them follow this bone's motions.</td>
</tr>
</table></div>
<!-- EDIT10 TABLE [5393-5708] -->
</div>
<!-- EDIT7 SECTION "Animation Control Properties" [4258-5710] -->
<h2><a>Animation Channel Properties</a></h2>
<h2>Animation Channel Properties</h2>
<div>
<p>
The following properties are set per AnimChannel.
</p>
<div><table>
<thead>
<tr>
<th>AnimChannel Property</th><th>Usage</th>
</tr>
</thead>
<tr>
<td>setLoopMode(LoopMode.Loop); </td><td> From now on, the animation on this channel will repeat from the beginning when it ends. </td>
</tr>
@ -220,14 +218,14 @@ The following properties are set per AnimChannel.
</table></div>
<!-- EDIT12 TABLE [5804-6428] -->
<p>
The following information is available for a channel.
</p>
<div><table>
<thead>
<tr>
<th>AnimChannel Property</th><th>Usage</th>
</tr>
</thead>
<tr>
<td>getAnimationName()</td><td>The name of the animation playing on this channel. Returns <code>null</code> when no animation is playing.</td>
</tr>
@ -246,64 +244,62 @@ The following information is available for a channel.
</table></div>
<!-- EDIT13 TABLE [6485-7118] -->
<p>
Use the following methods to add or remove individual bones to an AnimChannel. This is useful when you play two animations in parallel on two channels, and each controls a subset of the bones (e.g. one the arms, and the other the legs).
</p>
<div><table>
<thead>
<tr>
<th>AnimChannel Methods</th><th>Usage</th>
</tr>
</thead>
<tr>
<td>addAllBones()</td><td>Add all the bones of the model's skeleton to be influenced by this animation channel. (default)</td>
</tr>
<tr>
<td>addBone("bone1") <br/>
<td>addBone(“bone1”) <br/>
addBone(bone1)</td><td>Add a single bone to be influenced by this animation channel.</td>
</tr>
<tr>
<td>addToRootBone("bone1") <br/>
<td>addToRootBone(“bone1”) <br/>
addToRootBone(bone1) </td><td>Add a series of bones to be influenced by this animation channel: Add all bones, starting from the given bone, to the root bone.</td>
</tr>
<tr>
<td>addFromRootBone("bone1") <br/>
<td>addFromRootBone(“bone1”) <br/>
addFromRootBone(bone1) </td><td>Add a series of bones to be influenced by this animation channel: Add all bones, starting from the given root bone, going towards the children bones.</td>
Animations are played by channel. <strong>Note:</strong> Whether the animation channel plays continuously or only once, depends on the Loop properties you have set.
</p>
<div><table>
<thead>
<tr>
<th>Channel Method</th><th>Usage</th>
</tr>
</thead>
<tr>
<td>channel_walk.setAnim("Walk",0.50f); </td><td> Start the animation named "Walk" on channel channel_walk. <br/>
<td>channel_walk.setAnim(“Walk”,0.50f); </td><td> Start the animation named “Walk” on channel channel_walk. <br/>
The float value specifies the time how long the animation should overlap with the previous one on this channel. If set to 0f, then no blending will occur and the new animation will be applied instantly.</td>
</tr>
</table></div>
<!-- EDIT16 TABLE [8167-8493] -->
<p>
<strong>Tip:</strong> Use the AnimEventLister below to react at the end or start of an animation cycle.
The onAnimCycleDone() event is invoked when an animation cycle has ended. For non-looping animations, this event is invoked when the animation is finished playing. For looping animations, this event is invoked each time the animation loop is restarted.
</p>
@ -370,11 +364,10 @@ You have access to the following objects:
</div>
<!-- EDIT19 SECTION "Responding to Animation End" [9681-10471] -->
<h3><a>Responding to Animation Start</a></h3>
<h3>Responding to Animation Start</h3>
<div>
<p>
The onAnimChange() event is invoked every time before an animation is set by the user to be played on a given channel (<code>channel.setAnim()</code>).
</p>
@ -399,4 +392,4 @@ You have access to the following objects
</div>
<!-- EDIT20 SECTION "Responding to Animation Start" [10472-] -->
The <code>com.jme3.app.state.AppState</code> class is a customizable jME3 interface that allows you to control the global game logic, the overall game mechanics. (To control the behaviour of a Spatial, see <ahref="/com/jme3/gde/docs/jme3/advanced/custom_controls.html">Custom Controls</a> instead. Controls and AppStates can be used together.)
There are situations during your game development where you think:
</p>
<ul>
@ -26,22 +24,21 @@ There are situations during your game development where you think:
</li>
<li><div> I have the in-game scene, and a character editor, and a Captain's Quarters screen. Can I group a set of nodes and behaviours, and swap them in and out in one step?</div>
</li>
<li><div> When I pause the game, I want the character's "idle" animation to continue, but all other loops and game events should stop. How do I define what happens when the game is paused/unpaused? </div>
<li><div> When I pause the game, I want the character's “idle” animation to continue, but all other loops and game events should stop. How do I define what happens when the game is paused/unpaused? </div>
</li>
<li><div> I have a conditional block that takes up a lot of space in my simpleUpdate() loop. Can I wrap up this block of code, and switch it on and off in one step?</div>
</li>
<li><div> Can I package everything that belongs in-game, and everything that belongs to the menu screen, and switch between these two "big states" in one step? </div>
<li><div> Can I package everything that belongs in-game, and everything that belongs to the menu screen, and switch between these two “big states” in one step? </div>
</li>
</ul>
<p>
You can! This is what AppStates are there for. An AppState class is subset of (or an extension to) your application. Every AppState class has access to all fields in your main application (AssetManager, ViewPort, StateManager, InputManager, RootNode, GuiNode, etc) and hooks into the main update loop. An AppState can contain:
</p>
<ul>
<li><div> a subset of class fields, functions, methods (game state data and accessors), </div>
</li>
<li><div> a subset of <acronymtitle="Graphical User Interface">GUI</acronym> elements and their listeners, </div>
<li><div> a subset of <abbrtitle="Graphical User Interface">GUI</abbr> elements and their listeners, </div>
</li>
<li><div> a subset of input handlers and mappings, </div>
</li>
@ -51,17 +48,16 @@ You can! This is what AppStates are there for. An AppState class is subset of (o
</li>
<li><div> a subset of other AppStates and Controls</div>
</li>
<li><div>??? or combinations thereof. </div>
<li><div>… or combinations thereof. </div>
</li>
</ul>
</div>
<!-- EDIT3 SECTION "Use Case Examples" [345-2032] -->
<h3><a>Supported Features</a></h3>
<h3>Supported Features</h3>
<div>
<p>
Each AppState lets you define what happens to it in the following situations:
</p>
<ul>
@ -73,25 +69,23 @@ The AppState executes its own simpleInitApp() method when it is attached, so to
<li><div><strong>While the AppState is running/paused:</strong> You can poll isEnabled() to define paused and unpaused game behaviour in the update() loop. In update(), you poll and modify the game state, modify the scene graph, and trigger events. Test if <code>!isEnabled()</code>, and write code that skips the running sections of this AppState's <code>update()</code> loop. <br/>
Each AppState has its own update loop, which hooks into the main simpleUpdate() loop (callback). </div>
</li>
<li><div><strong>The AppState has been disabled (paused):</strong> This toggles a boolean isEnabled() to false. Here you switch all objects to their specific "paused" behaviour. </div>
<li><div><strong>The AppState has been disabled (paused):</strong> This toggles a boolean isEnabled() to false. Here you switch all objects to their specific “paused” behaviour. </div>
</li>
<li><div><strong>The AppState is cleaned up:</strong> Here you decide what happens when the AppState is detached. Save this AppState's game state, unregister Controls and InputHandlers, detach related AppStates, detach nodes from the rootNode, etc.</div>
</li>
</ul>
<p>
<p><div>Tip: AppStates are extremely handy to swap out, or pause/unpause whole sets of other AppStates. For example, an InGameState (loads in-game <acronymtitle="Graphical User Interface">GUI</acronym>, activates click-to-shoot input mappings, inits game content, starts game loop) versus MainScreenState (stops game loop, saves and detaches game content, switches to menu screen <acronymtitle="Graphical User Interface">GUI</acronym>, switches to click-to-select input mappings).
<p><div>Tip: AppStates are extremely handy to swap out, or pause/unpause whole sets of other AppStates. For example, an InGameState (loads in-game <abbrtitle="Graphical User Interface">GUI</abbr>, activates click-to-shoot input mappings, inits game content, starts game loop) versus MainScreenState (stops game loop, saves and detaches game content, switches to menu screen <abbrtitle="Graphical User Interface">GUI</abbr>, switches to click-to-select input mappings).
When you add several AppStates to one Application and activate them, their initialize() methods and update() loops are executed in the order in which the AppStates were added to the AppStateManager.
</p>
</div>
<!-- EDIT5 SECTION "Usage" [3762-4620] -->
<h3><a>Code Samples</a></h3>
<h3>Code Samples</h3>
<div>
<p>
JME3 comes with a BulletAppState that implements Physical behaviour (using the jBullet library). You, for example, could write an Artificial Intelligence AppState to control all your enemy units. Existing examples in the code base include:
</p>
<ul>
@ -140,18 +132,18 @@ JME3 comes with a BulletAppState that implements Physical behaviour (using the j
</div>
<!-- EDIT6 SECTION "Code Samples" [4621-5401] -->
<h2><a>AppState</a></h2>
<h2>AppState</h2>
<div>
<p>
The AppState interface lets you initialize sets of objects, and hook a set of continously executing code into the main loop.
</p>
<div><table>
<thead>
<tr>
<th>AppState Method</th><th>Usage</th>
</tr>
</thead>
<tr>
<td>initialize(asm,app)</td><td>When this AppState is added to the game, the RenderThread initializes the AppState and then calls this method. You can modify the scene graph from here (e.g. attach nodes). To get access to the main app, call: <pre>super.initialize(stateManager, app);
this.app = (SimpleApplication) app;</pre>
@ -187,17 +179,15 @@ stateDetached(asm)</td><td>The AppState knows when it is attached to, or detache
<!-- EDIT8 TABLE [5550-7112] -->
</div>
<!-- EDIT7 SECTION "AppState" [5402-7113] -->
<h2><a>AbstractAppState</a></h2>
<h2>AbstractAppState</h2>
<div>
<p>
The AbstractAppState class already implements some common methods (<code>isInitialized(), setActive(), isActive()</code>) and makes creation of custom AppStates a bit easier. We recommend you extend AbstractAppState and override the remaining AppState methods: <code>initialize(), setEnabled(), cleanup()</code>.
</p>
<p>
Definition:
</p>
<pre>public class MyAppState extends AbstractAppState {
You define what an AppState does when Paused or Unpaused, in the <code>setEnabled()</code> and <code>update()</code> methods. Call <code>myState.setEnabled(false)</code> on all states that you want to pause. Call <code>myState.setEnabled(true)</code> on all states that you want to unpause.
</p>
</div>
<!-- EDIT10 SECTION "Pausing and Unpausing" [9287-9577] -->
<h2><a>AppStateManager</a></h2>
<h2>AppStateManager</h2>
<div>
<p>
The com.jme3.app.state.AppStateManager holds the list of AppStates for an application. AppStateManager ensures that active AppStates can modify the scene graph, and that the update() loops of active AppStates is executed. There is one AppStateManager per application. You typically attach several AppStates to one AppStateManager, but the same state can only be attached once.
You can only access other AppStates (read from and write to them) from certain places: From a Control's update() method, from an AppState's update() method, and from the SimpleApplication's simpleUpdate() loop. Don't mess with the AppState from other places, because from other methods you have no control over the order of modifications; the game can go out of sync because you can't know when (during which half-finished step of another state change) your modification will be performed.
</p>
<p>
You can use custom accessors to get data from AppStates, to set data in AppStates, or to trigger methods in AppStates.
<!-- EDIT14 SECTION "Communication Among AppStates" [10990-11745] -->
<h3><a>Initialize Familiar Class Fields</a></h3>
<h3>Initialize Familiar Class Fields</h3>
<div>
<p>
To access class fields of the SimpleApplication the way you are used to, initialize them to local variables, as shown in the following AppState template:
</p>
<pre>private SimpleApplication app;
@ -352,4 +336,4 @@ public class MyAppState extends AbstractAppState {
</div>
<!-- EDIT15 SECTION "Initialize Familiar Class Fields" [11746-] -->
<h1><a>THIS DEMO IS OUT OF DATE AND NEEDS CORRECTING FOR NOW PLEASE SEE</a></h1>
<h1>THIS DEMO IS OUT OF DATE AND NEEDS CORRECTING FOR NOW PLEASE SEE</h1>
<div>
<p>
@ -21,7 +19,7 @@ THIS DEMO IS OUT OF DATE AND NEEDS CORRECTING
</p>
<p>
Note: this tutorial needs to be fixed and is currently not correct. One should almost never override stateDetached and stateAttached??? and should certainly never do anything scene related in them.
Note: this tutorial needs to be fixed and is currently not correct. One should almost never override stateDetached and stateAttached… and should certainly never do anything scene related in them.
</p>
<p>
@ -30,12 +28,11 @@ This demo is a simple example of how you use AppStates to toggle between a Start
<p>
There are four files, Main.java, GameRunningState.java, StartScreenState.java, SettingsScreenState.java.
</p>
</div>
<!-- EDIT2 SECTION "THIS DEMO IS OUT OF DATE AND NEEDS CORRECTING FOR NOW PLEASE SEE" [109-793] -->
<h2><a>Main.java</a></h2>
<h2>Main.java</h2>
<div>
<pre>package chapter04.appstatedemo;
@ -94,7 +91,7 @@ public class Main extends SimpleApplication {
inputManager.addListener(actionListener, new String[]{"Toggle Settings"});
}
private ActionListener actionListener = new ActionListener(){
private ActionListener(){
public void onAction(String name, boolean isPressed, float tpf){
By assets we mean multi-media files, such as 3D models, materials, textures, scenes, custom shaders, music and sound files, and custom fonts. JME3 has an integrated asset manager that helps you keep your project assets organized. Think of the asset manager as the filesystem of your game, independent of the actual deployment platform. By default, store your assets in the <code>MyGame/assets/ </code> directory of your project.
</p>
@ -21,13 +20,12 @@ For example, the same textures are not uploaded to the graphics card multiple ti
</ul>
<p>
Advanced users can write a custom build and packaging script, and can register custom paths to the AssetManager, but this is up to you then.
</p>
</div>
<h4><a>Context</a></h4>
<h4>Context</h4>
<div>
<pre>jMonkeyProjects/MyGame/assets/ # You store assets in subfolders here! <------
jMonkeyProjects/MyGame/build/ # SDK generates built classes here (*)
@ -44,11 +42,10 @@ See also <a href="/com/jme3/gde/docs/jme3/intermediate/best_practices.html">Best
</div>
<!-- EDIT1 SECTION "AssetManager" [1-1702] -->
<h2><a>Usage</a></h2>
<h2>Usage</h2>
<div>
<p>
The <code>assetManager</code> object is an com.jme3.asset.AssetManager instance that every com.jme3.app.Application can access. It maintains a root that also includes your project's classpath by default, so you can load any asset that's on the classpath, that is, the top level of your project directory.
</p>
@ -63,7 +60,7 @@ Here is an example how you load assets using the AssetManager. This lines loads
new AssetKey("Common/Materials/RedColor.j3m"));</pre>
<p>
This Material is "somewhere" in the jME3 JAR; the default Asset Manager is configured to handle a <code>Common/???</code> path correctly, so you don't have to specify the whole path when referring to built-in assets (such as default Materials).
This Material is “somewhere” in the jME3 JAR; the default Asset Manager is configured to handle a <code>Common/…</code> path correctly, so you don't have to specify the whole path when referring to built-in assets (such as default Materials).
</p>
<p>
@ -72,16 +69,15 @@ Additionally, you can configure the Asset Manager and add any path to its root.
</div>
<!-- EDIT2 SECTION "Usage" [1703-2860] -->
<h2><a>Asset Directory</a></h2>
<h2>Asset Directory</h2>
<div>
<p>
By default, jME3 searches for models in a directory named <code>assets</code>.
</p>
<p>
<p><div>In Java projects created with the jMonkeyEngine <acronymtitle="Software Development Kit">SDK</acronym>, an <code>assets</code> folder is created by default in your project directory. If you are using any other IDE, or the command line, you simply create an <code>assets</code> directory manually (see the Codeless Project tip below).
<p><div>In Java projects created with the jMonkeyEngine SDK, an <code>assets</code> folder is created by default in your project directory. If you are using any other IDE, or the command line, you simply create an <code>assets</code> directory manually (see the Codeless Project tip below).
</div></p>
</p>
@ -104,7 +100,7 @@ These subdirectories are just the most common examples.
</p>
<p>
<p><div>You can rename/delete/add (sub)directories inside the <code>assets</code> directory in any way you like. Note however that there is no automatic refactoring for asset paths in the <acronymtitle="Software Development Kit">SDK</acronym>, so if you modify them late in the development process, you have to refactor all paths manually.
<p><div>You can rename/delete/add (sub)directories inside the <code>assets</code> directory in any way you like. Note however that there is no automatic refactoring for asset paths in the SDK, so if you modify them late in the development process, you have to refactor all paths manually.
</div></p>
</p>
@ -120,39 +116,33 @@ After the conversion, you move the .j3o file into the <code>assets/Models/</code
Spatial scene = assetManager.loadModel("main.scene");
@ -171,18 +161,20 @@ jME3 also offers a ClasspathLocator, ZipLocator, FileLocator, HttpZipLocator, an
</p>
<p>
<p><div>The custom build script does not automatically include all ZIP files in the executable build. See "Cannot Locate Resource" solution below.
<p><div>The custom build script does not automatically include all ZIP files in the executable build. See “Cannot Locate Resource” solution below.
<td> Load a model with materials </td><td> Use the asset manager's <code>loadModel()</code> method and attach the Spatial to the rootNode. <pre>Spatial elephant = assetManager.loadModel("Models/Elephant/Elephant.mesh.xml");
My game runs fine when I run it right from the jMonkeyEngine <acronymtitle="Software Development Kit">SDK</acronym>. But when I run the stand-alone executables (.jar, .jnlp .exe, .app), a DesktopAssetManager error message occurs in the console, and it quits?
My game runs fine when I run it right from the jMonkeyEngine SDK. But when I run the stand-alone executables (.jar, .jnlp .exe, .app), a DesktopAssetManager error message occurs in the console, and it quits?
If you use the default build script, <strong>original models and scenes (.mesh.xml, .obj, .blend, .zip), are excluded</strong> from the distribution automatically. A stand-alone executable includes converted <strong>.j3o files</strong> (models and scenes) only. The default build script makes sure to bundle existing .j3o files in the distribution, but you need to remember to convert the models (from mesh.xml???>.j3o, or .obj???>.j3o, etc) yourself.
If you use the default build script, <strong>original models and scenes (.mesh.xml, .obj, .blend, .zip), are excluded</strong> from the distribution automatically. A stand-alone executable includes converted <strong>.j3o files</strong> (models and scenes) only. The default build script makes sure to bundle existing .j3o files in the distribution, but you need to remember to convert the models (from mesh.xml–>.j3o, or .obj–>.j3o, etc) yourself.
</p>
<p>
@ -236,16 +227,16 @@ If you use the default build script, <strong>original models and scenes (.mesh.x
</p>
<p>
Before building the executable, you must use the jMonkeyEngine <acronymtitle="Software Development Kit">SDK</acronym>'s context menu action to <ahref="/com/jme3/gde/docs/sdk/model_loader_and_viewer.html">convert 3D models to .j3o binary format</a>.
Before building the executable, you must use the jMonkeyEngine SDK's context menu action to <ahref="/com/jme3/gde/docs/sdk/model_loader_and_viewer.html">convert 3D models to .j3o binary format</a>.
</p>
<ol>
<li><div> Save your original models (.mesh.xml, .scene, .blend, or .obj files, plus textures) into <code>assets/Textures/</code>. (!)</div>
</li>
<li><div> Open the jME3 project in the jMonkeyEngine <acronymtitle="Software Development Kit">SDK</acronym>.</div>
<li><div> Open the jME3 project in the jMonkeyEngine SDK.</div>
</li>
<li><div> Browse to the <code>assets</code> directory in the Projects window. </div>
</li>
<li><div> Right-click an original model in <code>assets/Textures/</code>, and choose "Convert to JME3 binary".</div>
<li><div> Right-click an original model in <code>assets/Textures/</code>, and choose “Convert to JME3 binary”.</div>
</li>
<li><div> The converted file appears in the same directory as the original file. It has the same name and a <code>.j3o</code> suffix. </div>
</li>
@ -256,7 +247,6 @@ Before building the executable, you must use the jMonkeyEngine <acronym title="S
</ol>
<p>
This ensures that the model's Texture paths keep working between your 3D mesh editor and JME3.
</p>
@ -267,16 +257,15 @@ This ensures that the model's Texture paths keep working between your 3D me
<h2><a>Asset Handling For Other IDEs: Codeless Projects</a></h2>
<h2>Asset Handling For Other IDEs: Codeless Projects</h2>
<div>
<p>
<strong>Problem:</strong>
</p>
<p>
I use another IDE than jMonkeyEngine <acronymtitle="Software Development Kit">SDK</acronym> for coding (Eclipse, IntelliJ, text editor). Where is my <code>asset</code> folder and .j3o converter?
I use another IDE than jMonkeyEngine SDK for coding (Eclipse, IntelliJ, text editor). Where is my <code>asset</code> folder and .j3o converter?
</p>
<p>
@ -284,8 +273,7 @@ I use another IDE than jMonkeyEngine <acronym title="Software Development Kit">S
</p>
<p>
You can code in any IDE, but you must create a so-called codeless project in the jMonkeyEngine <acronymtitle="Software Development Kit">SDK</acronym> to maintain assets. <strong>A code-less jMonkeyEngine project does not meddle with your sources or custom build scripts.</strong> You merely use it to convert models to .j3o binaries.
You can code in any IDE, but you must create a so-called codeless project in the jMonkeyEngine SDK to maintain assets. <strong>A code-less jMonkeyEngine project does not meddle with your sources or custom build scripts.</strong> You merely use it to convert models to .j3o binaries.
</p>
<ol>
<li><div> Create your (Eclipse or whatever) project as you like.</div>
@ -293,28 +281,27 @@ You can code in any IDE, but you must create a so-called codeless project in the
<li><div> Create a directory in your project folder and name it, for example, <code>assets</code>. <br/>
Store your assets there as described above.</div>
</li>
<li><div> Download and install the jMonkeyEngine <acronymtitle="Software Development Kit">SDK</acronym>.</div>
<li><div> Download and install the jMonkeyEngine SDK.</div>
</li>
<li><div> In the <acronymtitle="Software Development Kit">SDK</acronym>, go to File ??? Import Projects ??? External Project Assets.</div>
<li><div> In the SDK, go to File → Import Projects → External Project Assets.</div>
</li>
<li><div> Select your (Eclipse or whatever) project and your assets folder in the Import Wizard.</div>
</li>
<li><div> You can now open this (Eclipse or whatever) project in the jMonkeyEngine <acronymtitle="Software Development Kit">SDK</acronym>. <br/>
<li><div> You can now open this (Eclipse or whatever) project in the jMonkeyEngine SDK. <br/>
Convert assets as described above.</div>
</li>
</ol>
<p>
<p><div>If you don't use the <acronymtitle="Software Development Kit">SDK</acronym> for some reason, you can still convert models to j3o format: Load any model in Ogre3D or Wavefront format with the AssetManager.loadModel() as a spatial. Then save the spatial as j3o file using <ahref="/com/jme3/gde/docs/jme3/advanced/save_and_load.html">BinaryExporter</a>.
<p><div>If you don't use the SDK for some reason, you can still convert models to j3o format: Load any model in Ogre3D or Wavefront format with the AssetManager.loadModel() as a spatial. Then save the spatial as j3o file using <ahref="/com/jme3/gde/docs/jme3/advanced/save_and_load.html">BinaryExporter</a>.
</div></p>
</p>
<p>
<p><div>Use file version control and let team members check out the project. Your developers open the project in Eclipse (etc) as they are used to. Additionally to their graphic tools, ask your graphic designers to install the jMonkeyEngine <acronymtitle="Software Development Kit">SDK</acronym>, and to check out the codeless project that you just prepared. This makes it easy for non-coding team member to browse and preview game assets, to arrange scenes, and to convert files. At the same time, non-coders don't accidentally mess with code, and developers don't accidentally mess with assets. :)
<p><div>Use file version control and let team members check out the project. Your developers open the project in Eclipse (etc) as they are used to. Additionally to their graphic tools, ask your graphic designers to install the jMonkeyEngine SDK, and to check out the codeless project that you just prepared. This makes it easy for non-coding team member to browse and preview game assets, to arrange scenes, and to convert files. At the same time, non-coders don't accidentally mess with code, and developers don't accidentally mess with assets. :)
</div></p>
</p>
</div>
<!-- EDIT8 SECTION "Asset Handling For Other IDEs: Codeless Projects" [9810-] -->
Place audio files in the <code>assets/Sound/</code> directory of your project. jME3 supports Ogg Vorbis audio compression (.ogg) and uncompressed PCM Wave (.wav) formats. You can use for example <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://audacity.sourceforge.net/"><paramname="text"value="<html><u>Audacity</u></html>"><paramname="textColor"value="blue"></object> to convert from other formats.
</p>
</div>
<!-- EDIT1 SECTION "Audio in jME3" [1-293] -->
<h2><a>Audio Terminology</a></h2>
<h2>Audio Terminology</h2>
<div>
<ul>
<li><div><strong>Streaming:</strong> There are two ways to load audio data: Short audio files are to be stored entirely in memory (prebuffered), while long audio files, such as music, are streamed from the hard drive as it is played.</div>
@ -23,13 +22,11 @@ You cannot loop streamed sounds.</div>
<h2><a>Creating Audio Nodes: Streamed or Buffered</a></h2>
<h2>Creating Audio Nodes: Streamed or Buffered</h2>
<div>
<p>
The main jME audio class to look at is <code>com.jme3.audio.AudioNode</code>. When creating a new audio node you need to declare whether how you want to load this sound:
</p>
<ul>
<li><div><strong>Buffered:</strong> By default, a new audio node is buffered. This means jME3 loads the whole file into memory before playing. Use this for short sounds. You create a buffered sound by setting the boolean to false, or using no boolean at all: <pre>AudioNode boom = new AudioNode(assetManager, "Sound/boom.wav");
setDirectional(false)</td><td>All 3D effects switched off. This sound is global and plays in headspace (it appears to come from everywhere). Good for environmental ambient sounds and background music.</td>
@ -112,58 +115,59 @@ setDirectional(false)</td><td>All 3D effects switched off. This sound is global
setLocalTranslation(???)</td><td>Activates 3D audio: The sound appears to come from a certain position, where it is loudest. Position the AudioNode in the 3D scene, or move it with mobile players or NPCs.</td>
setLocalTranslation(…)</td><td>Activates 3D audio: The sound appears to come from a certain position, where it is loudest. Position the AudioNode in the 3D scene, or move it with mobile players or NPCs.</td>
</tr>
<tr>
<td>setReverbEnabled(true)</td><td>Reverb is a 3D echo effect that only makes sense with positional AudioNodes. Use Audio Environments to make scenes sound as if they were "outdoors", or "indoors" in a large or small room, etc. The reverb effect is defined by the <code>com.jme3.audio.Environment</code> that the <code>audioRenderer</code> is in. See "Setting Audio Environment Properties" below. </td>
<td>setReverbEnabled(true)</td><td>Reverb is a 3D echo effect that only makes sense with positional AudioNodes. Use Audio Environments to make scenes sound as if they were “outdoors”, or “indoors” in a large or small room, etc. The reverb effect is defined by the <code>com.jme3.audio.Environment</code> that the <code>audioRenderer</code> is in. See “Setting Audio Environment Properties” below. </td>
</tr>
</table></div>
<!-- EDIT11 TABLE [3917-4533] -->
<p>
<p><div>Positional 3D sounds require an <code>AudioListener</code> object in the scene (representing the player's ears).
</div></p>
</p>
</div>
<!-- EDIT10 SECTION "Positional 3D Sounds" [3885-4662] -->
<h3><a>Directional 3D Sounds</a></h3>
<h3>Directional 3D Sounds</h3>
<div>
<div><table>
<thead>
<tr>
<th>AudioNode Method</th><th>Usage</th>
</tr>
</thead>
<tr>
<td>setDirectional(true) <br/>
setDirection(???) </td><td>Activates 3D audio: This sound can only be heard from a certain direction. Specify the direction and angle in the 3D scene if you have setDirectional() true. Use this to restrict noises that should not be heard, for example, through a wall.</td>
setDirection(…) </td><td>Activates 3D audio: This sound can only be heard from a certain direction. Specify the direction and angle in the 3D scene if you have setDirectional() true. Use this to restrict noises that should not be heard, for example, through a wall.</td>
</tr>
<tr>
<td>setInnerAngle() <br/>
setOuterAngle()</td><td>Set the angle in degrees for the directional audio. The angle is relative to the direction. Note: By default, both angles are 360?? and the sound can be heard from all directions!</td>
setOuterAngle()</td><td>Set the angle in degrees for the directional audio. The angle is relative to the direction. Note: By default, both angles are 360° and the sound can be heard from all directions!</td>
</tr>
</table></div>
<!-- EDIT13 TABLE [4696-5223] -->
<p>
<p><div>Directional 3D sounds require an AudioListener object in the scene (representing the player's ears).
</div></p>
</p>
</div>
<!-- EDIT12 SECTION "Directional 3D Sounds" [4663-5350] -->
<h2><a>Play, Pause, Stop</a></h2>
<h2>Play, Pause, Stop</h2>
<div>
<p>
You play, pause, and stop a node called myAudioNode by using the respective of the following three methods:
</p>
<pre>myAudioNode.play();</pre>
@ -181,11 +185,10 @@ You can also start playing instances of an AudioNode. Use the <code>playInstance
The default AudioListener object <code>listener</code> in <code>SimpleApplication</code> is the user's ear in the scene. If you use 3D audio (positional or directional sounds), you must move the AudioListener with the player: For example, for a first-person player, you move the listener with the camera. For a third-person player, you move the listener with the player avatar Geometry.
</p>
<pre> @Override
@ -197,18 +200,18 @@ The default AudioListener object <code>listener</code> in <code>SimpleApplicatio
</div>
<!-- EDIT15 SECTION "The Audio Listener" [6056-6692] -->
Optionally, You can choose from the following environmental presets from <code>com.jme3.audio.Environment</code>. This presets influence subtle echo effects (reverb) that evoke associations of different environments in your users. That is, it makes you scene sound "indoors" or "outdoors" etc. You use Audio Environments together with <code>setReverbEnabled(true)</code> on positional AudioNodes (see above).
Optionally, You can choose from the following environmental presets from <code>com.jme3.audio.Environment</code>. This presets influence subtle echo effects (reverb) that evoke associations of different environments in your users. That is, it makes you scene sound “indoors” or “outdoors” etc. You use Audio Environments together with <code>setReverbEnabled(true)</code> on positional AudioNodes (see above).
@ -228,7 +231,7 @@ Optionally, You can choose from the following environmental presets from <code>c
<!-- EDIT17 TABLE [7135-7624] --><ol>
<li><div> Activate a Environment preset</div>
<ul>
<li><div> Either use a default, e.g. make you scene sounds like a dungeon environment: <pre>audioRenderer.setEnvironment(new Environment(Environment.Dungeon));</pre>
<li><div> Either use a default, e.g. make you scene sounds like a dungeon environment: <pre>audioRenderer.setEnvironment(new Environment.Dungeon));</pre>
</div>
</li>
<li><div> Or activate <ahref="/com/jme3/gde/docs/jme3/advanced/audio_environment_presets.html">custom environment settings</a> in the Environment constructor:<pre>audioRenderer.setEnvironment(
<p><div>A sound engineer can create a custom <code>com.???jme3.???audio.Environment</code> object and specify custom environment values such as density, diffusion, gain, decay, delay??? You can find many <ahref="/com/jme3/gde/docs/jme3/advanced/audio_environment_presets.html">examples of custom audio environment presets</a> here.
<p><div>A sound engineer can create a custom <code>com.jme3.audio.Environment</code> object and specify custom environment values such as density, diffusion, gain, decay, delay… You can find many <ahref="/com/jme3/gde/docs/jme3/advanced/audio_environment_presets.html">examples of custom audio environment presets</a> here.
</div></p>
</p>
<p>
Advanced users find more info about OpenAL and its features here: <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://connect.creativelabs.com/openal/Documentation/OpenAL%201.1%20Specification.pdf"><paramname="text"value="<html><u>OpenAL 1.1 Specification</u></html>"><paramname="textColor"value="blue"></object>.
Advanced users find more info about OpenAL and its features here: <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://web.archive.org/web/20130327063429/http://connect.creativelabs.com/openal/Documentation/OpenAL_Programmers_Guide.pdf"><paramname="text"value="<html><u>OpenAL 1.1 Specification</u></html>"><paramname="textColor"value="blue"></object>.
</p>
<p>
<p><div>It depends on the hardware whether audio effects are supported (if not, you get the message <code>OpenAL EFX not available! Audio effects won't work.</code>)
Use these presets together with <ahref="/com/jme3/gde/docs/jme3/advanced/audio.html">Audio</a> Nodes to create different "moods" for sounds. Environment effects make your audio sound as if the listener were in various places that have different types of echoes.
Use these presets together with <ahref="/com/jme3/gde/docs/jme3/advanced/audio.html">Audio</a> Nodes to create different “moods” for sounds. Environment effects make your audio sound as if the listener were in various places that have different types of echoes.
Bloom is a popular shader effect in 3D games industry. It usually consist in displaying a glowing halo around light sources or bright areas of a scene.
In practice, the bright areas are extracted from the rendered scene, blurred and finally added up to the render.
</p>
@ -16,7 +15,7 @@ Those images gives an idea of what bloom does. The left image has no bloom effec
</div>
<!-- EDIT1 SECTION "Bloom and Glow" [1-484] -->
<h1><a>Bloom Usage</a></h1>
<h1>Bloom Usage</h1>
<div>
<ol>
<li><div> Create a FilterPostProcessor</div>
@ -34,12 +33,14 @@ Those images gives an idea of what bloom does. The left image has no bloom effec
<td> blur scale </td><td><code>setBlurScale(float)</code></td><td>1.5f </td><td> the scale of the bloom effect, but be careful, high values does artifacts </td>
</tr>
@ -53,30 +54,27 @@ Here are the parameters that you can tweak :
<td> bloom intensity </td><td><code>setBloomIntensity(float)</code></td><td>2.0f </td><td> the resulting bloom value is multiplied by this intensity </td>
</tr>
</table></div>
<!-- EDIT3 TABLE [865-1454] -->
<!-- EDIT3 TABLE [864-1454] -->
<p>
You'll probably need to adjust those parameters depending on your scene.
</p>
</div>
<!-- EDIT2 SECTION "Bloom Usage" [485-1529] -->
<h1><a>Bloom with a glow map</a></h1>
<h1>Bloom with a glow map</h1>
<div>
<p>
Sometimes, you want to have more control over what glows and does not glow.
The bloom filter supports a glow map or a glow color.
</p>
</div>
<h5><a>Creating a glow-map</a></h5>
<h5>Creating a glow-map</h5>
<div>
<p>
Let's take the hover tank example bundled with JME3 test data.<br/>
Here you can see the diffuse map of the tank, and the associated glow map that only contains the parts of the texture that will glow and their glowing color: <br/>
@ -88,7 +86,6 @@ Here you can see the diffuse map of the tank, and the associated glow map that o
<p>
Glow maps work with Lighting.j3md, Particles.j3md and SolidColor.j3md material definitions.
The tank material looks like this :
</p>
<pre>Material My Material : Common/MatDefs/Light/Lighting.j3md {
MaterialParameters {
@ -105,13 +102,12 @@ The tank material looks like this :
}</pre>
<p>
The glow map is defined here : <strong>GlowMap : Models/HoverTank/tank_glow_map_highres.png</strong>
</p>
</div>
<h5><a>Usage</a></h5>
<h5>Usage</h5>
<div>
<ol>
<li><div> Create a FilterPostProcessor</div>
@ -136,18 +132,17 @@ Here is the result : <br/>
</div>
<!-- EDIT4 SECTION "Bloom with a glow map" [1530-3231] -->
<h1><a>Bloom with a glow color</a></h1>
<h1>Bloom with a glow color</h1>
<div>
<p>
Sometimes you need an entire object to glow, not just parts of it.
In this case you'll need to use the glow color parameter.
</p>
</div>
<h5><a>Usage</a></h5>
<h5>Usage</h5>
<div>
<ol>
<li><div> Create a material for your object and set the GlowColor parameter</div>
@ -178,33 +173,30 @@ Here is the result on Oto's plasma ball (before and after) : <br/>
</div>
<!-- EDIT5 SECTION "Bloom with a glow color" [3232-4239] -->
<h1><a>Hints and tricks</a></h1>
<h1>Hints and tricks</h1>
<div>
</div>
<h5><a>Increasing the blur range and reducing fps cost</a></h5>
<h5>Increasing the blur range and reducing fps cost</h5>
<div>
<p>
The glow render is sampled on a texture that has the same dimensions as the viewport.
You can reduce the size of the bloom sampling just by using the setDownSamplingFactor method like this : <br/>
<h1><a>Multithreading Bullet Physics in jme3</a></h1>
<h1>Multithreading Bullet Physics in jme3</h1>
<div>
</div>
<!-- EDIT1 SECTION "Multithreading Bullet Physics in jme3" [1-53] -->
<h2><a>Introduction</a></h2>
<h2>Introduction</h2>
<div>
<p>
Since bullet is not (yet) multithreaded or GPU accelerated, the jME3 implementation allows to run each physics space on a separate thread that is executed in parallel to rendering.
</p>
</div>
<!-- EDIT2 SECTION "Introduction" [54-261] -->
<h2><a>How is it handled in jme3 and bullet?</a></h2>
<h2>How is it handled in jme3 and bullet?</h2>
<div>
<p>
A SimpleApplication with a BulletAppState allows setting the threading type via
Now the physics update happens in parallel to render(), that is, after the user's changes in the update() call have been applied. During update() the physics update loop pauses. This way the loop logic is still maintained: the user can set and change values in physics and scenegraph objects before render() and physicsUpdate() are called in parallel. This allows you to use physics methods in update() as if it was single-threaded.
@ -50,16 +50,14 @@ Now the physics update happens in parallel to render(), that is, after the user&
</table></div>
<!-- EDIT4 TABLE [1202-1424] -->
<p>
<p><div>You can add more physics spaces by using multiple PARALLEL bulletAppStates. You would do that if you have sets physical objects that never collide (for example, underground bolders and flying cannon balls above ground), so you put those into separate physics spaces, which improves performances (less collisions to check!).
The <code>flyCam</code> class field gives you access to an AppState that extends the default camera in <code>com.jme3.app.SimpleApplication</code> with more features. The input manager of the <code>com.jme3.input.FlyByCamera</code> AppState is preconfigured to respond to the WASD keys for walking forwards and backwards, and strafing to the sides; move the mouse to rotate the camera ("Mouse Look"), scroll the mouse wheel for zooming in or out. The QZ keys raise or lower the camera vertically.
The <code>flyCam</code> class field gives you access to an AppState that extends the default camera in <code>com.jme3.app.SimpleApplication</code> with more features. The input manager of the <code>com.jme3.input.FlyByCamera</code> AppState is preconfigured to respond to the WASD keys for walking forwards and backwards, and strafing to the sides; move the mouse to rotate the camera (“Mouse Look”), scroll the mouse wheel for zooming in or out. The QZ keys raise or lower the camera vertically.
</p>
<pre>Q W up forw
A S D --> left back right
Z down </pre>
<div><table>
<thead>
<tr>
<th>Method</th><th>Usage</th>
</tr>
</thead>
<tr>
<td>flyCam.setEnabled(true);</td><td>Activate the flyby cam</td>
</tr>
@ -123,25 +124,25 @@ Z down </pre>
</table></div>
<!-- EDIT5 TABLE [2634-3016] -->
<p>
The FlyByCamera is active by default, but you can change all these defaults for your game.
</p>
</div>
<!-- EDIT4 SECTION "FlyBy Camera" [2036-3109] -->
<h2><a>Chase Camera</a></h2>
<h2>Chase Camera</h2>
<div>
<p>
jME3 also supports an optional Chase Cam that can follow a moving target Spatial (<code>com.jme3.input.ChaseCamera</code>). When you use the chase cam, the player clicks and hold the mouse button to rotate the camera around the camera target. You can use a chase cam if you need the mouse pointer visible in your game.
</p>
<pre>flyCam.setEnabled(false);
ChaseCamera chaseCam = new ChaseCamera(cam, target, inputManager);</pre>
<div><table>
<thead>
<tr>
<th>Method</th><th>Usage</th>
</tr>
</thead>
<tr>
<td>chaseCam.setSmoothMotion(true);</td><td>Interpolates a smoother acceleration/deceleration when the camera moves.</td>
<td>chaseCam.setDefaultHorizontalRotation(-FastMath.PI/2);</td><td>The default horizontal rotation angle of the camera around the target at the start of the application.</td>
So you've made your cool new JMonkeyEngine3 game and you want to
create a demo video to show off your hard work. Or maybe you want to
make a cutscene for your game using the physics and characters in the
@ -22,11 +21,10 @@ feature to record high-quality game trailers!
</div>
<!-- EDIT1 SECTION "Capture Audio/Video to a File" [1-658] -->
<h2><a>Simple Way</a></h2>
<h2>Simple Way</h2>
<div>
<p>
First off, if all you need is to record video at 30fps with no sound, then look
no further than jMonkeyEngine 3's built in <code>VideoRecorderAppState</code>
class.
@ -55,15 +53,14 @@ That's all!
</div>
<!-- EDIT2 SECTION "Simple Way" [659-1362] -->
<h2><a>Advanced Way</a></h2>
<h2>Advanced Way</h2>
<div>
<p>
<p><div>This way of A/V recording is still in development.
It works for all of jMonkeyEngine's test cases.
If you experience any problems or
if something isn't clear, please <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://jmonkeyengine.org/members/bortreb/"><paramname="text"value="<html><u>let me know</u></html>"><paramname="textColor"value="blue"></object>. ??? bortreb
if something isn't clear, please <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://jmonkeyengine.org/members/bortreb/"><paramname="text"value="<html><u>let me know</u></html>"><paramname="textColor"value="blue"></object>. – bortreb
</div></p>
</p>
@ -131,20 +128,20 @@ video frames to it will fail, and nothing will be written.
</p>
<p>
2.) If the filename ends in ".avi" then the frames will be encoded as
2.) If the filename ends in “.avi” then the frames will be encoded as
a RAW stream inside an AVI 1.0 container. The resulting file
will be quite large and you will probably want to re-encode it to
your preferred container/codec format. Be advised that some
video payers cannot process AVI with a RAW stream, and that AVI
1.0 files generated by this method that exceed 2.0GB are invalid
according to the AVI 1.0 <acronymtitle="specification">spec</acronym> (but many programs can still deal
according to the AVI 1.0 <abbrtitle="specification">spec</abbr> (but many programs can still deal
The <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://www.adobe.com/products/flashplayer/"><paramname="text"value="<html><u>Adobe Flash Plugin</u></html>"><paramname="textColor"value="blue"></object> is needed to display this content.
The <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://www.adobe.com/products/flashplayer/"><paramname="text"value="<html><u>Adobe Flash Plugin</u></html>"><paramname="textColor"value="blue"></object> is needed to display this content.
JME3 cinematics (com.jme.cinematic) allow you to remote control nodes and cameras in a 3D game: You can script and and play cinematic scenes. You can use cinematics to create <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://en.wikipedia.org/wiki/Cutscene"><paramname="text"value="<html><u>cutscenes</u></html>"><paramname="textColor"value="blue"></object> and movies/trailers for your game. Another good use case is efficient "destruction physics": Playing back prerecorded flying pieces of debris for demolitions is much faster than calculating them with live physics.
JME3 cinematics (com.jme.cinematic) allow you to remote control nodes and cameras in a 3D game: You can script and and play cinematic scenes. You can use cinematics to create <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://en.wikipedia.org/wiki/Cutscene"><paramname="text"value="<html><u>cutscenes</u></html>"><paramname="textColor"value="blue"></object> and movies/trailers for your game. Another good use case is efficient “destruction physics”: Playing back prerecorded flying pieces of debris for demolitions is much faster than calculating them with live physics.
</p>
<p>
@ -29,7 +28,7 @@ This Node can be the rootNode, or a Node that is attached to the rootNode. </div
<td>MotionEvent</td><td>Use a MotionEvent to move a Spatial non-linearly over time. A MotionEvent is based on a list of waypoints in a MotionPath. The curve goes through each waypoint, and you can adjust the tension of the curve to modify the roundedness of the path. This is the motion interpolation you are going to use in most cases. </td>
</tr>
@ -115,7 +115,7 @@ Here is the list of available CinematicEvents that you use as events. Each track
<td>SoundEvent</td><td>Use a SoundEvent to play a <ahref="/com/jme3/gde/docs/jme3/advanced/audio.html">sound</a> at a given time for the given duration.</td>
</tr>
<tr>
<td>GuiEvent</td><td>Displays a <ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui.html">Nifty GUI</a> at a given time for the given duration. Use it to display subtitles or HUD elements. Bind the Nifty <acronymtitle="Graphical User Interface">GUI</acronym><acronymtitle="Extensible Markup Language">XML</acronym> to the cinematic using <code>cinematic.bindUi("path/to/nifty/file.xml");</code></td>
<td>GuiEvent</td><td>Displays a <ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui.html">Nifty GUI</a> at a given time for the given duration. Use it to display subtitles or HUD elements. Bind the Nifty <abbrtitle="Graphical User Interface">GUI</abbr> XML to the cinematic using <code>cinematic.bindUi(“path/to/nifty/file.xml”);</code></td>
</tr>
<tr>
<td>AnimationEvent</td><td>Use this to start playing a model <ahref="/com/jme3/gde/docs/jme3/advanced/animation.html">animation</a> at a given time (a character walking animation for example)</td>
@ -123,20 +123,16 @@ Here is the list of available CinematicEvents that you use as events. Each track
</table></div>
<!-- EDIT6 TABLE [2868-3669] -->
<p>
Of course one can make is own event implementation, by extending the AbstractCinematicEvent.
You can add custom events by extending AbstractCinematicEvent.
<td>event.setLoopMode(LoopMode.Loop)</td><td>Sets whether the animation along this path should loop (LoopMode.Loop) or play only once (LoopMode.DontLoop).</td>
</tr>
@ -193,30 +190,26 @@ To create a MotionEvent, do the following:
<td>event.setRotation(quaternion)</td><td>Sets the rotation. Use together with <code>MotionEvent.Direction.Rotation</code> or <code>MotionEvent.Direction.PathAndRotation</code>.</td>
</tr>
</table></div>
<!-- EDIT8 TABLE [4249-5658] -->
<!-- EDIT8 TABLE [4219-5628] -->
<p>
<strong>Tip:</strong> Most likely you remote-control more than one object in your scene. Give the events and paths useful names such as <code>dragonEvent</code>, <code>dragonPath</code>, <code>heroEvent</code>, <code>heroPath</code>, etc.
</p>
</div>
<!-- EDIT7 SECTION "MotionEvent" [3764-5853] -->
<h3><a>SoundEvent</a></h3>
<!-- EDIT7 SECTION "MotionEvent" [3734-5823] -->
<h3>SoundEvent</h3>
<div>
<p>
A SoundEventplays a sound as part of the cinematic.
<li><div><code>audioPath</code> is the path to an audio file as String, e.g. "Sounds/mySound.wav".</div>
<li><div><code>audioPath</code> is the path to an audio file as String, e.g. “Sounds/mySound.wav”.</div>
</li>
<li><div><code>isStream</code> toggles between streaming and buffering. Set to true to stream long audio file, set to false to play short buffered sounds.</div>
</li>
@ -227,21 +220,17 @@ Details of the constructor:
</ul>
</div>
<!-- EDIT9 SECTION "SoundEvent" [5854-6384] -->
<h3><a>GuiEvent</a></h3>
<!-- EDIT9 SECTION "SoundEvent" [5824-6354] -->
<h3>GuiEvent</h3>
<div>
<p>
A GuiEventshows or hide a NiftyGUI as part of a cinematic.
You must use this together with bindUI() to specify the Nifty <acronymtitle="Graphical User Interface">GUI</acronym><acronymtitle="Extensible Markup Language">XML</acronym> file that you want to load:
You must use this together with bindUI() to specify the Nifty <abbrtitle="Graphical User Interface">GUI</abbr> XML file that you want to load:
There is a built in system for camera switching in Cinematics. It based on CameraNode, and the cinematic just enable the given CameraNode control at a given time.
</p>
<p>
First you have to bind a camera to the cinematic with a unique name. You'll be provided with a CameraNode
then you can do whatever you want with this camera node : place it so that you have a the camera angle you'd like, attach it to a motion event to have some camera scrolling, attach control of your own that give it whatever behavior you'd like.
In the above example, I want it to be a top view of the scene looking at the world origin.
@ -313,32 +295,30 @@ In the above example, I want it to be a top view of the scene looking at the wor
<p>
Then i just have to schedule its activation in the cinematic. I want it to get activated 3 seconds after the start of the cinematic so I just have to do
You can extend individual CinematicEvents. The <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/animation/SubtitleTrack.java"><paramname="text"value="<html><u>SubtitleTrack.java example</u></html>"><paramname="textColor"value="blue"></object> shows how to extend a GuiTrack to script subtitles. See how the subtitles are used in the <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/animation/TestCinematic.java"><paramname="text"value="<html><u>TestCinematic.java example</u></html>"><paramname="textColor"value="blue"></object>.
</p>
<p>
You can also create new CinematicEvent by extending <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/core/com/jme3/cinematic/events/AbstractCinematicEvent.java"><paramname="text"value="<html><u>AbstractCinematicEvent</u></html>"><paramname="textColor"value="blue"></object>. An AbstractCinematicEvent implements the CinematicEvent interface and provides duration, time, speed, etc??? management. Look at the <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/animation/TestCinematic.java"><paramname="text"value="<html><u>TestCinematic.java example</u></html>"><paramname="textColor"value="blue"></object> is to use this for a custom fadeIn/fadeOut effect in combination with a com.jme3.post.filters.FadeFilter.
You can also create new CinematicEvent by extending <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/core/com/jme3/cinematic/events/AbstractCinematicEvent.java"><paramname="text"value="<html><u>AbstractCinematicEvent</u></html>"><paramname="textColor"value="blue"></object>. An AbstractCinematicEvent implements the CinematicEvent interface and provides duration, time, speed, etc… management. Look at the <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/animation/TestCinematic.java"><paramname="text"value="<html><u>TestCinematic.java example</u></html>"><paramname="textColor"value="blue"></object> is to use this for a custom fadeIn/fadeOut effect in combination with a com.jme3.post.filters.FadeFilter.
The term collision can be used to refer to <ahref="/com/jme3/gde/docs/jme3/advanced/physics_listeners.html">physical interactions</a> (where <ahref="/com/jme3/gde/docs/jme3/advanced/physics.html">physical objects</a> collide, push and bump off one another), and also to non-physical <em>intersections</em> in 3D space. This article is about the non-physical (mathematical) collisions.
</p>
@ -12,16 +11,15 @@ Non-physical collision detection is interesting because it uses less computing r
</p>
<p>
<strong>Example:</strong> One example for an optimization is a physical vehicle's wheels. You could make the wheels fully physical disks, and have jME calculate every tiny force ??? sounds very accurate? It's total overkill and too slow for a racing game. A more performant solution is to cast four invisible rays down from the vehicle and calculate the intersections with the floor. These non-physical wheels require (in the simplest case) only four calculations per tick to achieve an effect that players can hardly distinguish from the real thing.
<strong>Example:</strong> One example for an optimization is a physical vehicle's wheels. You could make the wheels fully physical disks, and have jME calculate every tiny force – sounds very accurate? It's total overkill and too slow for a racing game. A more performant solution is to cast four invisible rays down from the vehicle and calculate the intersections with the floor. These non-physical wheels require (in the simplest case) only four calculations per tick to achieve an effect that players can hardly distinguish from the real thing.
</p>
</div>
<!-- EDIT1 SECTION "Collision and Intersection" [1-1432] -->
<h2><a>Collidable</a></h2>
<h2>Collidable</h2>
<div>
<p>
The interface com.jme3.collision.Collidable declares one method that returns how many collisions were found between two Collidables: <code>collideWith(Collidable other, CollisionResults results)</code>.
</p>
<ul>
@ -32,9 +30,11 @@ Note that jME counts <em>all</em> collisions, this means a ray intersecting a bo
</li>
</ul>
<div><table>
<thead>
<tr>
<th>CollisionResults Method</th><th>Usage</th>
</tr>
</thead>
<tr>
<td>size() </td><td>Returns the number of CollisionResult objects.</td>
</tr>
@ -53,9 +53,11 @@ Note that jME counts <em>all</em> collisions, this means a ray intersecting a bo
A CollisionResult object contains information about the second party of the collision event.
</p>
<div><table>
<thead>
<tr>
<th>CollisionResult Method</th><th>Usage</th>
</tr>
</thead>
<tr>
<td>getContactPoint()</td><td>Returns the contact point coordinate on the second party, as Vector3f.</td>
</tr>
@ -78,11 +80,10 @@ A CollisionResult object contains information about the second party of the coll
<!-- EDIT4 TABLE [2497-3030] -->
</div>
<!-- EDIT2 SECTION "Collidable" [1433-3031] -->
<h3><a>Code Sample</a></h3>
<h3>Code Sample</h3>
<div>
<p>
Assume you have two collidables a and b and want to detect collisions between them. The collision parties can be Geometries, Nodes with Geometries attached (including the rootNode), Planes, Quads, Lines, or Rays. An important restriction is that you can only collide geometry vs bounding volumes or rays. (This means for example that a must be of Type Node or Geometry and b respectively of Type BoundingBox, BoundingSphere or Ray.)
</p>
@ -129,16 +130,14 @@ You can also loop over all results and trigger different reactions depending on
<p>
Knowing the distance of the collisions is useful for example when you intersect Lines and Rays with other objects.
</p>
</div>
<!-- EDIT5 SECTION "Code Sample" [3032-5570] -->
<h2><a>Bounding Volumes</a></h2>
<h2>Bounding Volumes</h2>
<div>
<p>
A <code>com.jme3.bounding.BoundingVolume</code> is an interface for dealing with containment of a collection of points. All BoundingVolumes are <code>Collidable</code> and are used as optimization to calculate non-physical collisions more quickly: It's always faster to calculate an intersection between simple shapes like spheres and boxes than between complex shapes like models.
</p>
@ -147,12 +146,12 @@ jME3 computes bounding volumes for all objects. These bounding volumes are later
</p>
<p>
All fast-paced action and shooter games use BoundingVolumes as an optimization. Wrap all complex models into simpler shapes ??? in the end, you get equally useful collision detection results, but faster. <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://en.wikipedia.org/wiki/Bounding_volume"><paramname="text"value="<html><u>More about bounding volumes...</u></html>"><paramname="textColor"value="blue"></object>
All fast-paced action and shooter games use BoundingVolumes as an optimization. Wrap all complex models into simpler shapes – in the end, you get equally useful collision detection results, but faster. <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://en.wikipedia.org/wiki/Bounding_volume"><paramname="text"value="<html><u>More about bounding volumes...</u></html>"><paramname="textColor"value="blue"></object>
</p>
<p>
Supported types:
<imgsrc="/wiki/lib/exe/fetch.php">
<imgsrc="/lib/exe/fetch.php">
</p>
<ul>
<li><div> Type.AABB = Axis-aligned bounding box, that means it doesn't rotate, which makes it less precise. A <code>com.jme3.bounding.BoundingBox</code> is an axis-aligned cuboid used as a container for a group of vertices of a piece of geometry. A BoundingBox has a center and extents from that center along the x, y and z axis. This is the default bounding volume, since it is fairly fast to generate and gives better accuracy than the bounding sphere.</div>
@ -161,52 +160,46 @@ Supported types:
</li>
<li><div> Type.OBB = Oriented bounding box. This bounding box is more precise because it can rotate with its content, but is computationally more expensive. (Currently not supported.)</div>
</li>
<li><div> Type.Capsule = Cylinder with rounded ends, also called "swept sphere". Typically used for mobile characters. (Currently not supported.)</div>
<li><div> Type.Capsule = Cylinder with rounded ends, also called “swept sphere”. Typically used for mobile characters. (Currently not supported.)</div>
</li>
</ul>
<p>
<p><div>Note: If you are looking for bounding volumes for physical objects, use <ahref="/com/jme3/gde/docs/jme3/advanced/physics.html">CollisionShapes</a>.
One of the supported <code>Collidable</code>s are meshes and scene graph objects. To execute a collision detection query against a scene graph, use <code>Spatial.collideWith()</code>. This will traverse the scene graph and return any mesh collisions that were detected. Note that the first collision against a particular scene graph may take a long time, this is because a special data structure called <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://en.wikipedia.org/wiki/Bounding_interval_hierarchy"><paramname="text"value="<html><u>|Bounding Interval Hierarchy (BIH)</u></html>"><paramname="textColor"value="blue"></object> needs to be generated for the meshes. At a later point, the mesh could change and the BIH tree would become out of date, in that case, call <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://jmonkeyengine.org/javadoc/com/jme3/scene/Mesh.html#createCollisionData()"><paramname="text"value="<html><u>Mesh.createCollisionData()</u></html>"><paramname="textColor"value="blue"></object> on the changed mesh to update the BIH tree.
</p>
</div>
<!-- EDIT8 SECTION "Mesh and Scene Graph Collision" [7797-8617] -->
<h2><a>Intersection</a></h2>
<h2>Intersection</h2>
<div>
<p>
A <code>com.jme3.math.Ray</code> is an infinite line with a beginning, a direction, and no end; whereas a <code>com.jme3.math.Line</code> is an infinite line with only a direction (no beginning, no end).
</p>
<p>
Rays are used to perform line-of-sight calculations. This means you can detect what users were "aiming at" when they clicked or pressed a key. You can also use this to detect whether game characters can see something (or someone) or not.
Rays are used to perform line-of-sight calculations. This means you can detect what users were “aiming at” when they clicked or pressed a key. You can also use this to detect whether game characters can see something (or someone) or not.
</p>
<ul>
<li><div><strong>Click to select:</strong> You can determine what a user has clicked by casting a ray from the camera forward in the direction of the camera. Now identify the closest collision of the ray with the rootNode, and you have the clicked object.</div>
@ -216,8 +209,7 @@ Rays are used to perform line-of-sight calculations. This means you can detect w
</ul>
<p>
<p><div>These simple but powerful ray-surface intersection tests are called Ray Casting. As opposed to the more advanced Ray Tracing technique, Ray Casting does not follow the ray's reflection after the first hit ??? the ray just goes straight on.
<p><div>These simple but powerful ray-surface intersection tests are called Ray Casting. As opposed to the more advanced Ray Tracing technique, Ray Casting does not follow the ray's reflection after the first hit – the ray just goes straight on.
@ -7,7 +7,7 @@ The ComboMoves class allows you to define combinations of inputs that trigger sp
</p>
<p>
Combos are usually a series of inputs, in a fixed order: For example a keyboard combo can look like: "press Down, then Down+Right together, then Right".
Combos are usually a series of inputs, in a fixed order: For example a keyboard combo can look like: “press Down, then Down+Right together, then Right”.
</p>
<p>
@ -25,30 +25,28 @@ Usage:
</ol>
<p>
Copy the two classes ComboMoveExecution.java and ComboMove.java into your application and adjust them to your package paths.
First you <ahref="/com/jme3/gde/docs/jme3/advanced/input_handling.html">define your game's inputs</a> as you usually do: Implement the com.jme3.input.controls.ActionListener interface for your class, and add triggers mappings such as com.jme3.input.controls.KeyTrigger and com.jme3.input.KeyInput.
For each of your combo moves, you specify the series of inputs that will trigger it. The order in which you define them is the order the player has to press them for the step to be recorded. When all steps have been recorded, the combo is triggered.
</p>
<p>
The following example shows how a fireball combo move is triggered by pressing the navigation keys for "down, down+right, right", in this order.
The following example shows how a fireball combo move is triggered by pressing the navigation keys for “down, down+right, right”, in this order.
</p>
<pre>ComboMove fireball = new ComboMove("Fireball");
Use the following ComboMove methods to specify the combo:
</p>
<div><table>
<thead>
<tr>
<th>ComboMove Method</th><th>Description</th>
</tr>
</thead>
<tr>
<td>press("A").done(); <br/>
press("A","B").done();</td><td>Combo step is recorded if A is entered. <br/>
<td>press(“A”).done(); <br/>
press(“A”,“B”).done();</td><td>Combo step is recorded if A is entered. <br/>
Combo step is recorded if A and B are entered simultaneously.</td>
</tr>
<tr>
<td>notPress("A").done(); <br/>
notPress("A","B").done();</td><td>Combo step is recorded if A is released. <br/>
<td>notPress(“A”).done(); <br/>
notPress(“A”,“B”).done();</td><td>Combo step is recorded if A is released. <br/>
Combo step is recorded if A and B are both released.</td>
</tr>
<tr>
<td>press("A").notPress("B").done();</td><td>Combo step is recorded if A is entered, and not B</td>
<td>press(“A”).notPress(“B”).done();</td><td>Combo step is recorded if A is entered, and not B</td>
</tr>
<tr>
<td>press("A").notPress("B").timeElapsed(0.11f).done();</td><td>Combo step is recorded a certain time after A and not B is entered. <br/>
etc, etc ???</td>
<td>press(“A”).notPress(“B”).timeElapsed(0.11f).done();</td><td>Combo step is recorded a certain time after A and not B is entered. <br/>
etc, etc …</td>
</tr>
<tr>
<td>setPriority(0.5f);</td><td>If there is an ambiguity, a high-priority combo will trigger instead of a low-priority combo. This prevents that a similar looking combo step "hijacks" another Combo. Use only once per ComboMove.</td>
<td>setPriority(0.5f);</td><td>If there is an ambiguity, a high-priority combo will trigger instead of a low-priority combo. This prevents that a similar looking combo step “hijacks” another Combo. Use only once per ComboMove.</td>
</tr>
<tr>
<td>setUseFinalState(false); <br/>
@ -131,18 +128,18 @@ True: This is the final state, do not chain combo steps. (?)</td>
</table></div>
<!-- EDIT6 TABLE [3096-4090] -->
<p>
The <code>press()</code> and <code>notPress()</code> methods accept sets of Input Triggers, e.g. <code>fireball.press("A","B","C").done()</code>.
The <code>press()</code> and <code>notPress()</code> methods accept sets of Input Triggers, e.g. <code>fireball.press(“A”,“B”,“C”).done()</code>.
</p>
<p>
The following getters give you more information about the game state:
</p>
<div><table>
<thead>
<tr>
<th>ComboMove Method</th><th>Usage</th>
</tr>
</thead>
<tr>
<td>getCastTime()</td><td>Returns the time since the last step has been recorded. (?)</td>
</tr>
@ -156,11 +153,10 @@ The following getters give you more information about the game state:
<!-- EDIT7 TABLE [4283-4489] -->
</div>
<!-- EDIT5 SECTION "ComboMove Class Methods" [3002-4490] -->
<h2><a>Detect Combos in ActionListener</a></h2>
<h2>Detect Combos in ActionListener</h2>
<div>
<p>
Now that you have specified the combo steps, you want to detect them. You do that in the onAction() method that you get from the ActionListener interface.
<!-- EDIT8 SECTION "Detect Combos in ActionListener" [4491-6314] -->
<h2><a>Execute Combos in the Update Loop</a></h2>
<h2>Execute Combos in the Update Loop</h2>
<div>
<p>
Now that you have detected the current move, you want to execute it. You do that in the update loop.
</p>
<pre>@Override
@ -245,26 +240,23 @@ Test <code>currentMove.getMoveName()</code> and proceed to call methods that imp
</div>
<!-- EDIT9 SECTION "Execute Combos in the Update Loop" [6315-7152] -->
<h2><a>Why Combos?</a></h2>
<h2>Why Combos?</h2>
<div>
<p>
Depending on the game genre, the designer can reward the players' intrinsical or extrinsical skills:
</p>
<ul>
<li><div> (intrinsical:) RPGs typically calculate the success of an attack from the character's in-game training level: The player plays the role of a character whose skill level is defined in numbers. RPGs typically do not offer any Combos.</div>
</li>
<li><div> (extrinsical:) Sport and fighter games typically choose to reward the player's "manual" skills: The success of a special move solely depends on the player's own dexterity. These games typically offer optional Combos.</div>
<li><div> (extrinsical:) Sport and fighter games typically choose to reward the player's “manual” skills: The success of a special move solely depends on the player's own dexterity. These games typically offer optional Combos.</div>
A <code>com.jme3.scene.control.Control</code> is a customizable jME3 interface that allows you to cleanly steer the behaviour of game entities (Spatials), such as artificially intelligent behaviour in NPCs, traps, automatic alarms and doors, animals and pets, self-steering vehicles or platforms ??? anything that moves and interacts. Several instances of custom Controls together implement the behaviours of a type of Spatial.
A <code>com.jme3.scene.control.Control</code> is a customizable jME3 interface that allows you to cleanly steer the behaviour of game entities (Spatials), such as artificially intelligent behaviour in NPCs, traps, automatic alarms and doors, animals and pets, self-steering vehicles or platforms – anything that moves and interacts. Several instances of custom Controls together implement the behaviours of a type of Spatial.
</p>
<p>
To control global game behaviour see <ahref="/com/jme3/gde/docs/jme3/advanced/application_states.html">Application States</a>??? you often use AppStates and Control together.
To control global game behaviour see <ahref="/com/jme3/gde/docs/jme3/advanced/application_states.html">Application States</a>– you often use AppStates and Control together.
</p>
<ul>
<li><div><objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://www.youtube.com/watch?v=MNDiZ9YHIpM"><paramname="text"value="<html><u>Quick video introduction to Custom Controls</u></html>"><paramname="textColor"value="blue"></object></div>
@ -15,7 +15,6 @@ To control global game behaviour see <a href="/com/jme3/gde/docs/jme3/advanced/a
</ul>
<p>
To control the behaviour of spatials:
</p>
<ol>
@ -38,17 +37,15 @@ For example, one NPC can be controlled by a PhysicsControl instance and an AICon
</ol>
<p>
To implement game logic for a type of spatial, you will either extend AbstractControl (most common case), or implement the Control interface, as explained in this article.
</p>
</div>
<!-- EDIT1 SECTION "Custom Controls" [1-1746] -->
<h2><a>Usage</a></h2>
<h2>Usage</h2>
<div>
<p>
Use <span><ahref="/com/jme3/gde/docs/jme3/advanced/custom_controls.html">Controls</a></span> to implement the <em>behaviour of types of game entities</em>.
</p>
<ul>
@ -67,11 +64,10 @@ Use <span><a href="/com/jme3/gde/docs/jme3/advanced/custom_controls.html">Contro
</ul>
<p>
Examples: You can write
</p>
<ul>
<li><div> A WalkerNavControl, SwimmerNavControl, FlyerNavControl??? that defines how a type of NPC finds their way around. All NPCs can walk, some can fly, others can swim, and some can all three, etc.</div>
<li><div> A WalkerNavControl, SwimmerNavControl, FlyerNavControl… that defines how a type of NPC finds their way around. All NPCs can walk, some can fly, others can swim, and some can all three, etc.</div>
</li>
<li><div> A PlayerNavControl that is steered by user-configurable keyboard and mouse input.</div>
</li>
@ -81,22 +77,20 @@ Examples: You can write
</li>
<li><div> An IdleBehaviourControl that remote-controls NPC behaviour in neutral situations. </div>
</li>
<li><div> A DestructionControl that automatically replaces a structure with an appropriate piece of debris after collision with a projectile???</div>
<li><div> A DestructionControl that automatically replaces a structure with an appropriate piece of debris after collision with a projectile…</div>
</li>
</ul>
<p>
The possibilities are endless. <imgsrc="/wiki/lib/images/smileys/icon_smile.gif"class="middle"alt=":-)"/>
The possibilities are endless. <imgsrc="/lib/images/smileys/icon_smile.gif"class="icon"alt=":-)"/>
</p>
</div>
<!-- EDIT2 SECTION "Usage" [1747-3214] -->
<h2><a>Example Code</a></h2>
<h2>Example Code</h2>
<div>
<p>
Other examples include the built-in RigidBodyControl in JME's physics integration, the built-in TerrainLODControl that updates the terrain's level of detail depending on the viewer's perspective, etc.
</p>
@ -116,11 +110,10 @@ Existing examples in the code base include:
</div>
<!-- EDIT3 SECTION "Example Code" [3215-4499] -->
<h2><a>AbstractControl Class</a></h2>
<h2>AbstractControl Class</h2>
<div>
<p>
<p><div>The most common way to create a Control is to create a class that extends AbstractControl.
</div></p>
</p>
@ -141,7 +134,6 @@ For example, you disable your IdleBehaviourControl when you enable your Defensiv
</ul>
<p>
Usage: Your custom subclass implements the three methods <code>controlUpdate()</code>, <code>controlRender()</code>, <code>setSpatial()</code>, and <code>cloneForSpatial()</code> as shown here:
</p>
<pre>public class MyControl extends AbstractControl implements Savable, Cloneable {
<p><div>In the less common case that you want to create a Control that also extends another class, create a custom interface that extends jME3's Control interface. Your class can become a Control by implementing the Control interface, and at the same time extending another class.
</div></p>
</p>
@ -246,19 +237,15 @@ The AssetManager also uses this method if the same spatial is loaded twice. You
</ul>
<p>
Usage example:
1. Create a custom control interface
</p>
<pre>public interface MyControlInterface extends Control {
public void setSomething(int x); // optionally, add custom methods
}</pre>
<p>
2. Create custom Controls implementing your Control interface.
</p>
<pre>public class MyControl extends MyCustomClass implements MyControlInterface {
@ -329,14 +316,12 @@ Usage example:
</div>
<!-- EDIT5 SECTION "The Control Interface" [7584-10841] -->
<h2><a>Best Practices</a></h2>
<h2>Best Practices</h2>
<div>
<p>
<strong>Tip:</strong> Use the getControl() accessor to get Control objects from Spatials. No need to pass around lots of object references.
Here an example from the <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://code.google.com/p/monkeyzone/"><paramname="text"value="<html><u>MonkeyZone</u></html>"><paramname="textColor"value="blue"></object> code:
</p>
<pre>public class CharacterAnimControl implements Control {
...
@ -349,9 +334,7 @@ Here an example from the <object classid="java:org.netbeans.modules.javahelp.Bro
}</pre>
<p>
<strong>Tip:</strong> You can create custom Control interfaces so a set of different Controls provide the same methods and can be accessed with the interface class type.
</p>
<pre>public interface ManualControl extends Control {
public void steerX(float value);
@ -363,22 +346,17 @@ Here an example from the <object classid="java:org.netbeans.modules.javahelp.Bro
}</pre>
<p>
Then you create custom sub-Controls and implement the methods accordingly to the context:
</p>
<pre>public class ManualVehicleControl extends ManualControl {...}</pre>
<p>
and
</p>
<pre>public class ManualCharacterControl extends ManualControl {...}</pre>
Use the Mesh class to create custom shapes that go beyond Quad, Box, Cylinder, and Sphere, even procedural shapes are possible. Thank you to KayTrance for providing the sample code!
</p>
<p>
<strong>Note:</strong> In this tutorial, we (re)create a very simple rectangular mesh (a quad), and we have a look at different ways of coloring it. Coding a custom quad may not be very useful because it's exactly the same as the built-in <code>com.jme3.scene.shape.Quad</code>. We chose a simple quad to teach you how to build any shape out of triangles, without the distractions of more complex shapes.
</p>
<ul>
<li><div> Full code sample: <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://jmonkeyengine.googlecode.com/svn/branches/stable-alpha4/engine/src/test/jme3test/model/shape/TestCustomMesh.java"><paramname="text"value="<html><u>TestCustomMesh.java</u></html>"><paramname="textColor"value="blue"></object></div>
@ -18,11 +17,10 @@ Use the Mesh class to create custom shapes that go beyond Quad, Box, Cylinder, a
Polygon <ahref="/com/jme3/gde/docs/jme3/advanced/mesh.html">mesh</a>es are made up of triangles. The corners of the triangles are called vertices. When ever you create any new shape, you break it down into triangles.
</p>
@ -35,17 +33,16 @@ The important thing is that you have to specify the vertices of each triangle in
</p>
<p>
Sounds harder than it is ??? let's create a simple custom mesh, a quad.
Sounds harder than it is – let's create a simple custom mesh, a quad.
In this tutorial we want to create a 3x3 Quad. The quad has four vertices, and is made up of two triangles. In our example, we decide that the bottom left corner is at 0/0/0 and the top right is at 3/3/0.
In this tutorial we want to create a 3×3 Quad. The quad has four vertices, and is made up of two triangles. In our example, we decide that the bottom left corner is at 0/0/0 and the top right is at 3/3/0.
</p>
<pre>0,3,0--3,3,0
| \ |
@ -57,13 +54,11 @@ In this tutorial we want to create a 3x3 Quad. The quad has four vertices, and i
</div>
<!-- EDIT3 SECTION "Creating a Quad Mesh" [1519-1864] -->
<h3><a>The Mesh Object</a></h3>
<h3>The Mesh Object</h3>
<div>
<p>
The base class for creating meshes is <code>com.jme3.scene.Mesh</code>.
</p>
<pre>Mesh mesh = new Mesh();</pre>
@ -73,13 +68,11 @@ Tip: If you create your own Mesh-based class (<code>public class MyMesh extends
</div>
<!-- EDIT4 SECTION "The Mesh Object" [1865-2157] -->
<h3><a>Vertex Coordinates</a></h3>
<h3>Vertex Coordinates</h3>
<div>
<p>
To define your own shape, determine the shape's <strong>vertex coordinates</strong> in 3D space. Store the list of corner positions in an <code>com.jme3.math.Vector3f</code> array. For a Quad, we need four vertices: Bottom left, bottom right, top left, top right. We name the array <code>vertices[]</code>.
</p>
<pre>Vector3f [] vertices = new Vector3f[4];
vertices[0] = new Vector3f(0,0,0);
@ -89,12 +82,11 @@ vertices[3] = new Vector3f(3,3,0);</pre>
Next, we define the Quad's 2D <strong>texture coordinates</strong> for each vertex, in the same order as the vertices: Bottom left, bottom right, top left, top right. We name this Vector2f array <code>texCoord[]</code>
</p>
<pre>Vector2f[] texCoord = new Vector2f[4];
texCoord[0] = new Vector2f(0,0);
@ -103,13 +95,12 @@ texCoord[2] = new Vector2f(0,1);
texCoord[3] = new Vector2f(1,1);</pre>
<p>
This syntax means, when you apply a texture to this mesh, the texture will fill the quad from corner to corner at 100% percent size. Especially when you stitch together a larger mesh, you use this to tell the renderer whether, and how exactly, you want to cover the whole mesh. E.g. if you use .5f or 2f as texture coordinates instead of 1f, textures will be stretched or shrunk accordingly.
If the shape is more complex, it has more triangles, and therefor also more vertices/indices. Just continue expanding the list by adding groups of three indices for each triangle. (For example a three-triangle "house" shape has 5 vertices/indices and you'd specify three groups: <code>int [] indexes = { 2,0,1, 1,3,2, 2,3,4 };</code>.)
If the shape is more complex, it has more triangles, and therefor also more vertices/indices. Just continue expanding the list by adding groups of three indices for each triangle. (For example a three-triangle “house” shape has 5 vertices/indices and you'd specify three groups: <code>int [] indexes = { 2,0,1, 1,3,2, 2,3,4 };</code>.)
</p>
<p>
<p><div>If you get the order wrong (clockwise) for some of the triangles, then these triangles face backwards. If the <ahref="/com/jme3/gde/docs/jme3/advanced/spatial.html">Spatial</a>'s material uses the default <code>FaceCullMode.Back</code> (see "face culling"), the broken triangles appear as holes in the rendered mesh. You need to identify and fix them in your code.
<p><div>If you get the order wrong (clockwise) for some of the triangles, then these triangles face backwards. If the <ahref="/com/jme3/gde/docs/jme3/advanced/spatial.html">Spatial</a>'s material uses the default <code>FaceCullMode.Back</code> (see “face culling”), the broken triangles appear as holes in the rendered mesh. You need to identify and fix them in your code.
</div></p>
</p>
</div>
<!-- EDIT7 SECTION "Connecting the Dots" [3476-4947] -->
<!-- EDIT8 SECTION "Setting the Mesh Buffer" [4948-6071] -->
<h2><a>Using the Mesh in a Scene</a></h2>
<!-- EDIT8 SECTION "Setting the Mesh Buffer" [4948-6073] -->
<h2>Using the Mesh in a Scene</h2>
<div>
<p>
We create a <code>com.jme3.scene.Geometry</code> from our <code>mesh</code>, apply a simple color material to it, and attach it to the rootNode to make it appear in the scene.
We create a <code>com.jme3.scene.Geometry</code> and <code>com.jme3.material.Material</code>from our <code>mesh</code>, apply a simple color material to it, and attach it to the rootNode to make it appear in the scene.
</p>
<pre>Geometry geo = new Geometry("OurMesh", mesh); // using our custom mesh object
<!-- EDIT10 SECTION "Using a Quad instead" [6611-7273] -->
<h2>Dynamic Meshes</h2>
<div>
<p>
If you are modifying a mesh dynamically in a way which changes the model's bounds, you need to update it:
</p>
<ol>
<li><div> Call <code>updateBounds()</code> on the mesh object, and then </div>
<li><div> Call <code>updateBound()</code> on the mesh object, and then </div>
</li>
<li><div> call <code>updateModelBound()</code> on the Geometry object containing the mesh. </div>
</li>
</ol>
<p>
The updateModelBounds() method warns you about not usually needing to use it, but that can be ignored in this special case.
The updateModelBound() method warns you about not usually needing to use it, but that can be ignored in this special case.
</p>
<p>
<em>N.B.: This does not work on TerrainQuad. Please use the TerrainQuad.adjustHeight() function to edit the TerrainQuad mesh instead. Additionally, if you want to use collisions on them afterwards, you need to call TerrainPatch.getMesh().createCollisionData(); to update the collision data, else it will collide with what seems to be the old mesh. </em>
@ -271,7 +282,6 @@ You create a float array color buffer:
</ul>
<p>
Loop over the colorArray buffer to quickly set some RGBA value for each vertex. As usual, RGBA color values range from 0.0f to 1.0f. <strong>Note that the color values in this example are arbitrarily chosen.</strong> It's just a quick loop to give every vertex a different RGBA value (a purplish gray, purple, a greenish gray, green, see screenshot), without writing too much code. For your own mesh, you'd assign meaningful values for the color buffer depending on which color you want your mesh to have.
</p>
<pre>// note: the red and green values are arbitray in this example
@ -288,23 +298,20 @@ for(int i = 0; i < 4; i++){
<p>
Next, set the color buffer. An RGBA color value contains four float components, thus the parameter <code>4</code>.
The previous examples used the mesh together with the <code>Unshaded.j3md</code> material. If you want to use the mesh with a Phong illuminated material (such as <code>Lighting.j3md</code>), the mesh must include information about its Normals. (Normal Vectors encode in which direction a mesh polygon is facing, which is important for calculating light and shadow!)
</p>
<pre>float[] normals = new float[12];
@ -320,12 +327,11 @@ If the mesh is more complex or rounded, calculate cross products of neighbouring
</p>
</div>
<!-- EDIT13 SECTION "Example: Using Meshes With Lighting.j3md" [9362-10288] -->
<h3><a>Example: Point Mode</a></h3>
<!-- EDIT14 SECTION "Example: Using Meshes With Lighting.j3md" [10438-11364] -->
<h3>Example: Point Mode</h3>
<div>
<p>
Additionally to coloring the faces as just described, you can hide the faces and show only the vertices as colored corner points.
</p>
<pre>Geometry coloredMesh = new Geometry ("ColoredMesh", cMesh);
This will result in a 10 px dot being rendered for each of the four vertices. The dot has the vertex color you specified above. The Quad's faces are not rendered at all in this mode. You can use this to visualize a special debugging or editing mode in your game.
</p>
</div>
<!-- EDIT14 SECTION "Example: Point Mode" [10289-11022] -->
<h2><a>Debugging Tip: Culling</a></h2>
<!-- EDIT15 SECTION "Example: Point Mode" [11365-12098] -->
<h2>Debugging Tip: Culling</h2>
<div>
<p>
By default, jME3 optimizes a mesh by "backface culling", this means not drawing the inside. It determines the side of a triangle by the order of the vertices: The frontface is the face where the vertices are specified counter-clockwise.
By default, jME3 optimizes a mesh by “backface culling”, this means not drawing the inside. It determines the side of a triangle by the order of the vertices: The frontface is the face where the vertices are specified counter-clockwise.
</p>
<p>
This means for you that, by default, your custom mesh is invisible when seen from "behind" or from the inside. This may not be a problem, typically this is even intended, because it's faster. The player will not look at the inside of most things anyway. For example, if your custom mesh is a closed polyhedron, or a flat wallpaper-like object, then rendering the backfaces (the inside of the pillar, the back of the painting, etc) would indeed be a waste of resources.
This means for you that, by default, your custom mesh is invisible when seen from “behind” or from the inside. This may not be a problem, typically this is even intended, because it's faster. The player will not look at the inside of most things anyway. For example, if your custom mesh is a closed polyhedron, or a flat wallpaper-like object, then rendering the backfaces (the inside of the pillar, the back of the painting, etc) would indeed be a waste of resources.
</p>
<p>
@ -373,22 +377,18 @@ In case however that your usecase requires the backfaces be visible, you have tw
<p>
See also:
</p>
<ul>
<li><div><ahref="/com/jme3/gde/docs/jme3/advanced/spatial.html">Spatial</a>??? contains more info about how to debug custom meshes (that do not render as expected) by changing the default culling behaviour.</div>
<li><div><ahref="/com/jme3/gde/docs/jme3/advanced/spatial.html">Spatial</a>– contains more info about how to debug custom meshes (that do not render as expected) by changing the default culling behaviour.</div>
</li>
<li><div><ahref="/com/jme3/gde/docs/jme3/advanced/mesh.html">Mesh</a>??? more details about advanced Mesh properties</div>
<li><div><ahref="/com/jme3/gde/docs/jme3/advanced/mesh.html">Mesh</a>– more details about advanced Mesh properties</div>
When you deal with complex game engine features like animations or physics it is handy to get feedback from the engine how it interpreted the current state. Is the physical object's collision shape really where you think it is? Is the skeleton of the animated character moving like you think it should? This document shows you how to activate visual debug aides.
</p>
<p>
What if you just want to quickly write code that loads models and brings them in their start position? You may not want to hunt for a sample model, convert it, add lights, and load materials. Instead you use "hasslefree" simple shapes, and a "hasslefree" unshaded material or wireframe: No model, no light source, no materials are needed to see them in your test scene.
What if you just want to quickly write code that loads models and brings them in their start position? You may not want to hunt for a sample model, convert it, add lights, and load materials. Instead you use “hasslefree” simple shapes, and a “hasslefree” unshaded material or wireframe: No model, no light source, no materials are needed to see them in your test scene.
</p>
<p>
If you ever have problems with objects appearing in the wrong spot, with the wrong scale, or wrong orientation, simply attach debug shapes to your scene to have a point of reference in 3D space ??? just like a giant ruler. If your code positions the debug shapes correctly, but models remain invisible when you apply the same code to them, you know that the problem must be either the model (where is its origin coordinate?), or the light (too dark? too bright? missing?), or the model's material (missing?) ??? and not the positioning code.
If you ever have problems with objects appearing in the wrong spot, with the wrong scale, or wrong orientation, simply attach debug shapes to your scene to have a point of reference in 3D space – just like a giant ruler. If your code positions the debug shapes correctly, but models remain invisible when you apply the same code to them, you know that the problem must be either the model (where is its origin coordinate?), or the light (too dark? too bright? missing?), or the model's material (missing?) – and not the positioning code.
</p>
<p>
@ -25,17 +24,16 @@ Here are some different debug shapes:
</div>
<!-- EDIT1 SECTION "Debugging" [1-1389] -->
<h2><a>Debug Shapes</a></h2>
<h2>Debug Shapes</h2>
<div>
</div>
<!-- EDIT2 SECTION "Debug Shapes" [1390-1415] -->
<h3><a>Coordinate Axes</a></h3>
<h3>Coordinate Axes</h3>
<div>
<p>
The coordinate axes (com.jme3.scene.debug.Arrow) help you see the cardinal directions (X,Y,Z) from their center point. Scale the arrows to use them as a "ruler" for a certain length.
The coordinate axes (com.jme3.scene.debug.Arrow) help you see the cardinal directions (X,Y,Z) from their center point. Scale the arrows to use them as a “ruler” for a certain length.
Use a wireframe sphere (com.jme3.scene.debug.WireSphere) as a stand-in object to see whether your code scales, positions, or orients, loaded models right.
You can display a wireframe of the (usually invisible) collision shape around all physical objects. Use this for debugging when analyzing unexpected behaviour. Does not work with DETACHED physics, please switch to PARALLEL or SEQUENTIAL for debugging.
@ -149,12 +143,11 @@ With debugging enabled, colors are used to indicate various types of physical ob
</ul>
</div>
<!-- EDIT7 SECTION "Wireframe for Physics" [4221-4913] -->
<h2><a>Wireframe for Animations</a></h2>
<!-- EDIT7 SECTION "Wireframe for Physics" [4233-4925] -->
<h2>Wireframe for Animations</h2>
<div>
<p>
Making the skeleton visible inside animated models can be handy for debugging animations. The <code>control</code> object is an AnimControl, <code>player</code> is the loaded model.
</p>
<pre> SkeletonDebugger skeletonDebug =
@ -166,25 +159,23 @@ Making the skeleton visible inside animated models can be handy for debugging an
player.attachChild(skeletonDebug);</pre>
</div>
<!-- EDIT8 SECTION "Wireframe for Animations" [4914-5505] -->
<h2><a>Example: Toggle Wireframe on Model</a></h2>
<!-- EDIT8 SECTION "Wireframe for Animations" [4926-5517] -->
<h2>Example: Toggle Wireframe on Model</h2>
<div>
<p>
We assume that you have loaded a model with a material <code>mat</code>.
</p>
<p>
Then you can add a switch to toggle the model's wireframe on and off, like this:
</p>
<ol>
<li><div> Create a key input trigger that switches between the two materials: E.g. we toggle when the T key is pressed: <pre> inputManager.addMapping("toggle wireframe", new KeyTrigger(KeyInput.KEY_T));
<li><div> Now add the toggle action to the action listener <pre> private ActionListener actionListener = new ActionListener(){
<li><div> Now add the toggle action to the action listener <pre> private ActionListener(){
@Override
public void onAction(String name, boolean pressed, float tpf){
// toggle wireframe
@ -197,7 +188,7 @@ Then you can add a switch to toggle the model's wireframe on and off, like
};</pre>
</div>
</li>
<li><div> Alternatively you could traverse over the whole scene and toggle for all Geometry objects in there if you don't want to create a new SceneProcessor <pre> private ActionListener actionListener = new ActionListener(){
<li><div> Alternatively you could traverse over the whole scene and toggle for all Geometry objects in there if you don't want to create a new SceneProcessor <pre> private ActionListener(){
boolean wireframe = false;
@Override
@ -224,12 +215,11 @@ TIP :: To set the line width of wireframe display, use mesh.setLineWidth(lineWid
</p>
</div>
<!-- EDIT9 SECTION "Example: Toggle Wireframe on Model" [5506-7396] -->
<h2><a>Example: Toggle Wireframe on the scene</a></h2>
<!-- EDIT9 SECTION "Example: Toggle Wireframe on Model" [5518-7408] -->
<h2>Example: Toggle Wireframe on the scene</h2>
<div>
<p>
To display the wireframe of the entire scene instead on one material at a time, first create the following Scene Processor
</p>
<pre>public class WireProcessor implements SceneProcessor {
@ -273,19 +263,19 @@ To display the wireframe of the entire scene instead on one material at a time,
}</pre>
<p>
Then attach the scene processor to the <acronymtitle="Graphical User Interface">GUI</acronym> Viewport.
Then attach the scene processor to the <abbrtitle="Graphical User Interface">GUI</abbr> Viewport.
<!-- EDIT10 SECTION "Example: Toggle Wireframe on the scene" [7397-8770] -->
<h2><a>See also</a></h2>
<!-- EDIT10 SECTION "Example: Toggle Wireframe on the scene" [7409-8782] -->
<h2>See also</h2>
<div>
<ul>
<li><div><ahref="/com/jme3/gde/docs/jme3/advanced/spatial.html">Spatial</a>??? if you can't see certain spatials, you can modify the culling behaviour to identify problems (such as inside-out custom meshes)</div>
<li><div><ahref="/com/jme3/gde/docs/jme3/advanced/spatial.html">Spatial</a>– if you can't see certain spatials, you can modify the culling behaviour to identify problems (such as inside-out custom meshes)</div>
jME3 supports several types of special effects: Post-Processor Filters, SceneProcessors, and Particle Emitters (also known as particle systems). This list contains screenshots and links to sample code that demonstrates how to add the effect to a scene.
</p>
</div>
<!-- EDIT1 SECTION "jME3 Special Effects Overview" [1-299] -->
<h2><a>Sample Code</a></h2>
<h2>Sample Code</h2>
<div>
<ul>
<li><div> There is one <code>com.jme3.effect.ParticleEmitter</code> class for all Particle Systems. </div>
@ -22,7 +21,7 @@ jME3 supports several types of special effects: Post-Processor Filters, ScenePro
</div>
<!-- EDIT2 SECTION "Sample Code" [300-768] -->
<h3><a>Particle Emitter</a></h3>
<h3>Particle Emitter</h3>
<div>
<pre>public class MyGame extends SimpleApplication {
public void simpleInitApp(){
@ -38,7 +37,7 @@ jME3 supports several types of special effects: Post-Processor Filters, ScenePro
The jMonkeyEngine's <ahref="/com/jme3/gde/docs/jme3/advanced/water.html">"SeaMonkey" WaterFilter</a> simulates ocean waves, foam, including cool underwater caustics.
Use the SimpleWaterProcessor (SceneProcessor) for small, limited bodies of water, such as puddles, drinking troughs, pools, fountains.
@ -81,9 +79,9 @@ Use the SimpleWaterProcessor (SceneProcessor) for small, limited bodies of water
See also the <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://jmonkeyengine.org/2011/01/15/new-advanced-water-effect-for-jmonkeyengine-3"><paramname="text"value="<html><u>Rendering Water as Post-Process Effect</u></html>"><paramname="textColor"value="blue"></object> announcement with video.
<li><div><objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/light/TestPssmShadow.java"><paramname="text"value="<html><u>jme3/src/test/jme3test/light/TestPssmShadow.java</u></html>"><paramname="textColor"value="blue"></object>??? PssmShadowRenderer (SceneProcessor), also known as Parallel-Split Shadow Mapping (PSSM).</div>
<li><div><objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/light/TestPssmShadow.java"><paramname="text"value="<html><u>jme3/src/test/jme3test/light/TestPssmShadow.java</u></html>"><paramname="textColor"value="blue"></object>– PssmShadowRenderer (SceneProcessor), also known as Parallel-Split Shadow Mapping (PSSM).</div>
</li>
<li><div><objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/post/TestSSAO.java"><paramname="text"value="<html><u>jme3/src/test/jme3test/post/TestSSAO.java</u></html>"><paramname="textColor"value="blue"></object>, <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/post/TestSSAO2.java"><paramname="text"value="<html><u>jme3/src/test/jme3test/post/TestSSAO2.java</u></html>"><paramname="textColor"value="blue"></object>??? SSAOFilter, also known as Screen-Space Ambient Occlusion shadows (SSOA).</div>
<li><div><objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/post/TestSSAO.java"><paramname="text"value="<html><u>jme3/src/test/jme3test/post/TestSSAO.java</u></html>"><paramname="textColor"value="blue"></object>, <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/post/TestSSAO2.java"><paramname="text"value="<html><u>jme3/src/test/jme3test/post/TestSSAO2.java</u></html>"><paramname="textColor"value="blue"></object>– SSAOFilter, also known as Screen-Space Ambient Occlusion shadows (SSOA).</div>
</li>
<li><div><objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/post/TestTransparentSSAO.java"><paramname="text"value="<html><u>jme3/src/test/jme3test/post/TestTransparentSSAO.java</u></html>"><paramname="textColor"value="blue"></object>??? SSAOFilter, also known as Screen-Space Ambient Occlusion shadows (SSOA), plus transparancy</div>
<li><div><objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/post/TestTransparentSSAO.java"><paramname="text"value="<html><u>jme3/src/test/jme3test/post/TestTransparentSSAO.java</u></html>"><paramname="textColor"value="blue"></object>– SSAOFilter, also known as Screen-Space Ambient Occlusion shadows (SSOA), plus transparancy</div>
</li>
<li><div> More details: <ahref="/com/jme3/gde/docs/jme3/advanced/light_and_shadow.html">Light and Shadow</a></div>
</li>
@ -204,42 +200,39 @@ See also the <object classid="java:org.netbeans.modules.javahelp.BrowserDisplaye
<ahref="/com/jme3/gde/docs/jme3/advanced/particle_emitters.html">Particle emitter effects</a> are highly configurable and can have any texture. They can simulate smoke, dust, leaves, meteors, snowflakes, mosquitos, fire, explosions, clusters, embers, sparks???
<ahref="/com/jme3/gde/docs/jme3/advanced/particle_emitters.html">Particle emitter effects</a> are highly configurable and can have any texture. They can simulate smoke, dust, leaves, meteors, snowflakes, mosquitos, fire, explosions, clusters, embers, sparks…
<li><div><objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/effect/TestPointSprite.java"><paramname="text"value="<html><u>jme3/src/test/jme3test/effect/TestPointSprite.java</u></html>"><paramname="textColor"value="blue"></object>??? cluster of points </div>
<li><div><objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/effect/TestPointSprite.java"><paramname="text"value="<html><u>jme3/src/test/jme3test/effect/TestPointSprite.java</u></html>"><paramname="textColor"value="blue"></object>– cluster of points </div>
Here is an extract taken from @nehon in the forum thread (<objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://hub.jmonkeyengine.org/forum/topic/how-exactly-do-filters-work/"><paramname="text"value="<html><u>http://hub.jmonkeyengine.org/forum/topic/how-exactly-do-filters-work/</u></html>"><paramname="textColor"value="blue"></object>)
</p>
@ -325,7 +315,7 @@ Those methods are optional in a filter, they are only there if you want to hook
</p>
<p>
The material variable is here for convenience. You have a getMaterial method that returns the material that???s gonna be used to render the full screen quad. It just happened that in every implementation I had a material attribute in all my sub-classes, so I just put it back in the abstract class. Most of the time getMaterial returns this attribute.
The material variable is here for convenience. You have a getMaterial method that returns the material that’s gonna be used to render the full screen quad. It just happened that in every implementation I had a material attribute in all my sub-classes, so I just put it back in the abstract class. Most of the time getMaterial returns this attribute.
</p>
<p>
@ -336,7 +326,7 @@ You assume well about the SSAO filer, the normal of the scene are rendered to a
<p>
Passes : these are filters in filters in a way. First they are a convenient way to initialize a FrameBuffer and the associated textures it needs, then you can use them for what ever you want.
For example, a Pass can be (as in the SSAO filter) an extra render of the scene with a forced technique, and you have to handle the render yourself in the postQueue method.
It can be a post pass to do after the main filter has been rendered to screen (for example an additional blur pass used in SSAO again). You have a list of passes called postRenderPass in the Filter abstract class. If you add a pass to this list, it???ll be automatically rendered by the FilterPostProcessor during the filter chain.
It can be a post pass to do after the main filter has been rendered to screen (for example an additional blur pass used in SSAO again). You have a list of passes called postRenderPass in the Filter abstract class. If you add a pass to this list, it’ll be automatically rendered by the FilterPostProcessor during the filter chain.
</p>
<p>
@ -345,7 +335,6 @@ The bloom Filter does an intensive use of passes.
<p>
Filters in a nutshell.
</p>
<hr/>
@ -360,13 +349,11 @@ See also:
<li><div><objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://www.smashingmagazine.com/2008/08/07/50-photoshop-tutorials-for-sky-and-space-effects/"><paramname="text"value="<html><u>Photoshop Tutorial for Sky and space effects (article)</u></html>"><paramname="textColor"value="blue"></object></div>
TerrainGrid is an extension built on top of the TerraMonkey tools like TerrainQuad and HeightMap, that provides "infinite" Terrain paging routines. <br/>
<p><div>Deprecated. Look at <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://hub.jmonkeyengine.org/forum/topic/design-question-terrain/#post-262072"><paramname="text"value="<html><u>http://hub.jmonkeyengine.org/forum/topic/design-question-terrain/#post-262072</u></html>"><paramname="textColor"value="blue"></object> instead
</div></p>
</p>
Thanks to G??bor (@anthyon) and Brent (@sploreg) for this contribution!
<p>
TerrainGrid is DEPRECATED.
</p>
<p>
TerrainGrid is an extension built on top of the TerraMonkey tools like TerrainQuad and HeightMap, that provides “infinite” Terrain paging routines. <br/>
Thanks to Gábor (@anthyon) and Brent (@sploreg) for this contribution!
</p>
</div>
<!-- EDIT1 SECTION "Endless Terrain" [1-254] -->
<h2><a>Sample Code</a></h2>
<!-- EDIT1 SECTION "Endless Terrain" [1-484] -->
<h2>Sample Code</h2>
<div>
<p>
@ -27,8 +35,8 @@ The classes with source code can be found in the org.jme3.terrain.geomipmapping
</ul>
</div>
<!-- EDIT2 SECTION "Sample Code" [255-1134] -->
<h2><a>Specification</a></h2>
<!-- EDIT2 SECTION "Sample Code" [485-1364] -->
<h2>Specification</h2>
<div>
<p>
@ -50,27 +58,25 @@ TerrainGrid is made up of the TerrainGrid class, and the HeightMapGrid and Terra
<p>
<br/>
Multiple listeners can be added to the TerrainGrid, they will be called in the order of addition, so it???s possible to have multiple changes to the material before completing the load of the tile.
Multiple listeners can be added to the TerrainGrid, they will be called in the order of addition, so it’s possible to have multiple changes to the material before completing the load of the tile.
<br/>
HeightMapGrid adds the possibility of loading terrain tiles on demand instead of having a simple height array. There???s no predefined way of how to store these tiles, it only takes care of loading one HeightMap object at given location at a time.
HeightMapGrid adds the possibility of loading terrain tiles on demand instead of having a simple height array. There’s no predefined way of how to store these tiles, it only takes care of loading one HeightMap object at given location at a time.
After playing around with the terrain in jME3, soon comes the requirement of having larger explorable lands. Increasing the size of one TerrainQuad leads to more memory usage, while it will still be easy to reach the worlds boundaries. That???s why TerrainGrid was designed. It extends the TerraindQuad class and uses 4 HeightMaps (dark blue) as the four sub-quad. This means that a terrain of size 513 will use tiles of 257. Also an LRUCache is built into the terrain package, so surrounding tiles (green) can be pre-cached on a different thread, lowering the loading time. The quads are updated as the camera approaches the boundary of the light blue section.
After playing around with the terrain in jME3, soon comes the requirement of having larger explorable lands. Increasing the size of one TerrainQuad leads to more memory usage, while it will still be easy to reach the worlds boundaries. That’s why TerrainGrid was designed. It extends the TerraindQuad class and uses 4 HeightMaps (dark blue) as the four sub-quad. This means that a terrain of size 513 will use tiles of 257. Also an LRUCache is built into the terrain package, so surrounding tiles (green) can be pre-cached on a different thread, lowering the loading time. The quads are updated as the camera approaches the boundary of the light blue section.
</p>
</div>
<!-- EDIT4 SECTION "Motivation" [2426-3157] -->
<h2><a>Rationale</a></h2>
<!-- EDIT4 SECTION "Motivation" [2656-3387] -->
<h2>Rationale</h2>
<div>
<p>
@ -80,13 +86,13 @@ There exist also two basic HeightMapGrid implementations:
<ul>
<li><div> ImageBasedHeightMapGrid: uses a sequentially numbered, 16 bit grayscale heightmaps. The physical filename of these files can be generated through the Namer interface. When a tile cannot be found by the assetManager, an empty (all-zero) heightmap is created, and a warning is added to the log.</div>
</li>
<li><div> FractalHeightMapGrid: uses a noise library to create a landscape on the fly. The shape of the terrain can be controlled by the various parameters and postfilters of the fractals. With the help of this grid implementation there???s no limitation ??? above of floating point precision limits ??? how far the camera can get. The tiles generated this way can be cached to the filesystem, for later modification. The FractalHeightMapGrid will always load from cache if a tile exists there!</div>
<li><div> FractalHeightMapGrid: uses a noise library to create a landscape on the fly. The shape of the terrain can be controlled by the various parameters and postfilters of the fractals. With the help of this grid implementation there’s no limitation – above of floating point precision limits – how far the camera can get. The tiles generated this way can be cached to the filesystem, for later modification. The FractalHeightMapGrid will always load from cache if a tile exists there!</div>
</li>
</ul>
</div>
<!-- EDIT5 SECTION "Rationale" [3158-4368] -->
<h2><a>Usage</a></h2>
<!-- EDIT5 SECTION "Rationale" [3388-4598] -->
<h2>Usage</h2>
<div>
<ol>
<li><div> instantiate a TerrainGrid object</div>
@ -112,5 +118,5 @@ Further information about terrain and TerrainQuad can be found in the wiki at:
You can use a fade in/fade out effect to make smooth transitions, for example between game levels. The effect fades in from black to the initialized scene, or fades out from the scene to black.
The effect uses com.jme3.post.FilterPostProcessor and com.jme3.post.filters.FadeFilter.
When adding multiplayer to your game, you may find that your server needs to know about game state (e.g. where are players, objects? Was that a direct hit? etc.) You can code all this up yourself, but there's an easier way.
</p>
@ -13,31 +12,29 @@ It's very easy to change your current (client) game to function as a server
@ -47,11 +44,10 @@ First, let's take a look at the default way of creating a new game (in its
</div>
<!-- EDIT3 SECTION "Client Code" [749-975] -->
<h2><a>Headless Server Code</a></h2>
<h2>Headless Server Code</h2>
<div>
<p>
Now, with a simple change you can start your game in Headless mode. This means that all input and audio/visual output will be ignored. That's a good thing for a server.
</p>
<pre>import com.jme3.system.JmeContext;
@ -64,16 +60,14 @@ public static void main(String[] args) {
</div>
<!-- EDIT4 SECTION "Headless Server Code" [976-1390] -->
<h2><a>Next steps</a></h2>
<h2>Next steps</h2>
<div>
<p>
Okay, so you can now start your game in a headless 'server mode', where to go from here?
</p>
<ul>
<li><div> Parse <code>String[] args</code> from the <code>main</code>-method to enable server mode on demand (e.g. start your server like <code>java -jar mygame.jar ???server</code>.</div>
<li><div> Parse <code>String[] args</code> from the <code>main</code>-method to enable server mode on demand (e.g. start your server like <code>java -jar mygame.jar –server</code>.</div>
</li>
<li><div> Integrate <ahref="/com/jme3/gde/docs/jme3/advanced/networking.html">SpiderMonkey</a>, to provide game updates to the server over a network.</div>
</li>
@ -82,14 +76,11 @@ Okay, so you can now start your game in a headless 'server mode', wher
<li><div> Add decent <ahref="/com/jme3/gde/docs/jme3/advanced/logging.html">logging</a> so your server actually makes sense.</div>
The jMonkeyEngine3 has built-in support for <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://jbullet.advel.cz"><paramname="text"value="<html><u>jBullet physics</u></html>"><paramname="textColor"value="blue"></object> via the <code>com.jme3.bullet</code> package.
</p>
@ -17,7 +16,7 @@ In this example, we will create a pendulum. The joint is the (invisible) connect
</div>
<!-- EDIT1 SECTION "Physical Hinges and Joints" [1-692] -->
@ -92,16 +89,15 @@ For a rope bridge, each set of planks would be one dynamic node.
</div>
<!-- EDIT5 SECTION "Creating a Dynamic Node" [2040-2537] -->
<h2><a>Understanding DOF, Joints, and Hinges</a></h2>
<h2>Understanding DOF, Joints, and Hinges</h2>
<div>
<p>
A PhysicsHingeJoint is an invisible connection between two nodes ??? here between the pendulum body and the hook. Why are hinges and joints represented by the same class? Hinges and joints have something in common: They constrain the <em>mechanical degree of freedom</em> (DOF) of another object.
A PhysicsHingeJoint is an invisible connection between two nodes – here between the pendulum body and the hook. Why are hinges and joints represented by the same class? Hinges and joints have something in common: They constrain the <em>mechanical degree of freedom</em> (DOF) of another object.
</p>
<p>
Consider a free falling, "unchained" object in physical 3D space: It has 6 DOFs:
Consider a free falling, “unchained” object in physical 3D space: It has 6 DOFs:
</p>
<ul>
<li><div> It translates along 3 axes</div>
@ -111,7 +107,6 @@ Consider a free falling, "unchained" object in physical 3D space: It h
</ul>
<p>
Now consider some examples of objects with joints:
</p>
<ul>
@ -124,18 +119,16 @@ Now consider some examples of objects with joints:
</ul>
<p>
You'll understand that, when creating any type of joint, it is important to correctly specify the DOFs that the joint restricts, and the DOFs that the joint allows. For the typical DOF of a <ahref="/com/jme3/gde/docs/jme3/advanced/ragdoll.html">ragDoll</a> character's limbs, jME even offers a special joint, <code>ConeJoint</code>.
</p>
</div>
<!-- EDIT6 SECTION "Understanding DOF, Joints, and Hinges" [2538-3728] -->
<h2><a>Creating the Joint</a></h2>
<h2>Creating the Joint</h2>
<div>
<p>
You create the HingeJoint after you have created the nodes that are to be chained together. In the code snippet you see that the HingeJoint constructor requires the two node objects. You also have to specify axes and pivots ??? they are the degrees of freedom that you just heard about.
You create the HingeJoint after you have created the nodes that are to be chained together. In the code snippet you see that the HingeJoint constructor requires the two node objects. You also have to specify axes and pivots – they are the degrees of freedom that you just heard about.
</p>
<pre>private HingeJoint joint;
...
@ -152,7 +145,6 @@ You create the HingeJoint after you have created the nodes that are to be chaine
Vector3f.UNIT_Z ); // DoF Axis of B (Z axis)</pre>
<p>
The pivot point's position will be at <code>(0,0,0)</code> in the global 3D space. In A's local space that is at <code>(0,0,0)</code> and in B's local space (remember B's position was set to <code>(0,-1,0)</code>) that is at <code>(0,1,0)</code>.
</p>
@ -160,15 +152,15 @@ The pivot point's position will be at <code>(0,0,0)</code> in the global 3D
Specify the following parameters for each joint:
</p>
<ul>
<li><div> PhysicsControl A and B ??? the two nodes that are to be joined</div>
<li><div> PhysicsControl A and B – the two nodes that are to be joined</div>
</li>
<li><div> Vector3f pivot A and pivot B ??? coordinates of the attachment point relative to A and B</div>
<li><div> Vector3f pivot A and pivot B – coordinates of the attachment point relative to A and B</div>
<ul>
<li><div> The points typically lie on the surface of the PhysicsControl's Spatials, rarely in the middle.</div>
</li>
</ul>
</li>
<li><div> Vector3f axisA and axisB ??? around which axes each node is allowed to spin.</div>
<li><div> Vector3f axisA and axisB – around which axes each node is allowed to spin.</div>
<ul>
<li><div> In our example, we constrain the pendulum to swing only along the Z axis.</div>
</li>
@ -177,7 +169,6 @@ Specify the following parameters for each joint:
</ul>
<p>
Remember to add all joint objects to the physicsSpace, just like you would do with any physical objects.
<li><div> Navigational aides: Crosshairs, mouse pointer or hand, ???</div>
<li><div> Navigational aides: Crosshairs, mouse pointer or hand, …</div>
</li>
</ul>
<p>
You have two options how to create HUDs.
</p>
<div><table>
<thead>
<tr>
<th>Option</th><th>Pros</th><th>Cons</th>
</tr>
</thead>
<tr>
<th>Attach elements to default guiNode:</th><td>Easy to learn. jMonkeyEngine built-in <acronymtitle="Application Programming Interface">API</acronym> for attaching plain images and bitmap text.</td><td>Only basic features. <br/>
<th>Attach elements to default guiNode:</th><td>Easy to learn. jMonkeyEngine built-in <abbrtitle="Application Programming Interface">API</abbr> for attaching plain images and bitmap text.</td><td>Only basic features. <br/>
You will have to write custom controls / buttons / effects if you need them.</td>
</tr>
<tr>
<th>Use advanced <ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui.html">Nifty GUI</a> integration:</th><td>Full-featured interactive user interface. <br/>
Includes buttons, effects, controls. <br/>
Supports <acronymtitle="Extensible Markup Language">XML</acronym> and Java layouts.</td><td>Steeper learning curve.</td>
Supports XML and Java layouts.</td><td>Steeper learning curve.</td>
</tr>
</table></div>
<!-- EDIT2 TABLE [834-1259] -->
<p>
Using the <acronymtitle="Graphical User Interface">GUI</acronym> Node is the default approach in jme3 to create simple HUDs. If you just quickly want to display a line of text, or a simple icon on the screen, use the no-frills <acronymtitle="Graphical User Interface">GUI</acronym> Node, it's easier.
Using the <abbrtitle="Graphical User Interface">GUI</abbr> Node is the default approach in jme3 to create simple HUDs. If you just quickly want to display a line of text, or a simple icon on the screen, use the no-frills <abbrtitle="Graphical User Interface">GUI</abbr> Node, it's easier.
You already know the <code>rootNode</code> that holds the 3-dimensional scene graph. jME3 also offers a 2-dimension (orthogonal) node, the <code>guiNode</code>.
</p>
@ -64,7 +61,7 @@ You already know the <code>rootNode</code> that holds the 3-dimensional scene gr
This is how you use the guiNode for HUDs:
</p>
<ul>
<li><div> Create a <acronymtitle="Graphical User Interface">GUI</acronym> element: a BitmapText or Picture object.</div>
<li><div> Create a <abbrtitle="Graphical User Interface">GUI</abbr> element: a BitmapText or Picture object.</div>
</li>
<li><div> Attach the element to the guiNode. </div>
</li>
@ -77,7 +74,7 @@ The BitmapTexts and Pictures appear as 2 dimensional element on the screen.
</p>
<p>
<p><div>By default, the guiNode has some scene graph statistics attached. To clear the guiNode before you attach your own <acronymtitle="Graphical User Interface">GUI</acronym> elements, use the following methods:
<p><div>By default, the guiNode has some scene graph statistics attached. To clear the guiNode before you attach your own <abbrtitle="Graphical User Interface">GUI</abbr> elements, use the following methods:
A simple image can be displayed using <code>com.jme3.ui.Picture</code>.
</p>
<pre>Picture pic = new Picture("HUD Picture");
@ -108,11 +104,10 @@ When you set the last boolean in setImage() to true, the alpha channel of your i
</div>
<!-- EDIT4 SECTION "Displaying Pictures in the HUD" [2190-2714] -->
<h3><a>Displaying Text in the HUD</a></h3>
<h3>Displaying Text in the HUD</h3>
<div>
<p>
You use <code>com.jme3.font.BitmapText</code> to display text on the screen.
</p>
<pre>BitmapText hudText = new BitmapText(guiFont, false);
@ -130,12 +125,12 @@ hudText = new BitmapText(myFont, false);</pre>
</div>
<!-- EDIT5 SECTION "Displaying Text in the HUD" [2715-3562] -->
<h3><a>Positioning HUD Elements</a></h3>
<h3>Positioning HUD Elements</h3>
<div>
<ul>
<li><div> When positioning <acronymtitle="Graphical User Interface">GUI</acronym> text and images in 2D, the <strong>bottom left corner</strong> of the screen is <code>(0f,0f)</code>, and the <strong>top right corner</strong> is at <code>(settings.getWidth(),settings.getHeight())</code>.</div>
<li><div> When positioning <abbrtitle="Graphical User Interface">GUI</abbr> text and images in 2D, the <strong>bottom left corner</strong> of the screen is <code>(0f,0f)</code>, and the <strong>top right corner</strong> is at <code>(settings.getWidth(),settings.getHeight())</code>.</div>
</li>
<li><div> If you have several 2D elements in the <acronymtitle="Graphical User Interface">GUI</acronym> bucket that overlap, define their depth order by specifing a Z value. For example use <code>pic.move(x, y, -1)</code> to move the picture to the background, or <code>hudText.setLocalTranslation(x,y,1)</code> to move text to the foreground.</div>
<li><div> If you have several 2D elements in the <abbrtitle="Graphical User Interface">GUI</abbr> bucket that overlap, define their depth order by specifing a Z value. For example use <code>pic.move(x, y, -1)</code> to move the picture to the background, or <code>hudText.setLocalTranslation(x,y,1)</code> to move text to the foreground.</div>
</li>
<li><div> Size and length values in the orthogonal render queue are treated like pixels. A 20*20-wu big quad is rendered 20 pixels wide.</div>
</li>
@ -143,26 +138,24 @@ hudText = new BitmapText(myFont, false);</pre>
It is technically possible to attach Quads and 3D Geometries to the HUD. They show up as flat, static <acronymtitle="Graphical User Interface">GUI</acronym> elements. The size unit for the guiNode is pixels, not world units. If you attach a Geometry that uses a lit Material, you must add a light to the guiNode.
It is technically possible to attach Quads and 3D Geometries to the HUD. They show up as flat, static <abbrtitle="Graphical User Interface">GUI</abbr> elements. The size unit for the guiNode is pixels, not world units. If you attach a Geometry that uses a lit Material, you must add a light to the guiNode.
</p>
<p>
<p><div>If you don't see an attached object in the <acronymtitle="Graphical User Interface">GUI</acronym>, check it's position and material (add a light to guiNode). Also verify whether it is not too tiny to be seen. For comparison: A 1 world-unit wide cube is only 1 pixel wide when attached to the guiNode! You may need to scale it bigger.
<p><div>If you don't see an attached object in the <abbrtitle="Graphical User Interface">GUI</abbr>, check it's position and material (add a light to guiNode). Also verify whether it is not too tiny to be seen. For comparison: A 1 world-unit wide cube is only 1 pixel wide when attached to the guiNode! You may need to scale it bigger.
</div></p>
</p>
</div>
<!-- EDIT7 SECTION "Displaying Geometries in the HUD" [4188-4803] -->
<h3><a>Keeping the HUD Up-To-Date</a></h3>
<h3>Keeping the HUD Up-To-Date</h3>
<div>
<p>
Use the update loop to keep the content up-to-date.
@ -175,25 +168,23 @@ Use the update loop to keep the content up-to-date.
</div>
<!-- EDIT8 SECTION "Keeping the HUD Up-To-Date" [4804-5078] -->
<h2><a>Advanced HUD: Nifty GUI</a></h2>
<h2>Advanced HUD: Nifty GUI</h2>
<div>
<p>
The recommended approach to create HUDs is using <ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui.html">Nifty GUI</a>.
</p>
<ol>
<li><div> Lay out the <acronymtitle="Graphical User Interface">GUI</acronym> in one or several Nifty <acronymtitle="Extensible Markup Language">XML</acronym> or Java files. </div>
<li><div> Lay out the <abbrtitle="Graphical User Interface">GUI</abbr> in one or several Nifty XML or Java files. </div>
</li>
<li><div> Write the controller classes in Java.</div>
</li>
<li><div> Load the <acronymtitle="Extensible Markup Language">XML</acronym> file with the controller object in your game's simpleInit() method.</div>
<li><div> Load the XML file with the controller object in your game's simpleInit() method.</div>
</li>
</ol>
<p>
The advantage of Nifty <acronymtitle="Graphical User Interface">GUI</acronym> is that it is well integrated into jME and the jMonkeyEngine <acronymtitle="Software Development Kit">SDK</acronym>, and that it offers all the features that you expect from a professional modern user interface.
The advantage of Nifty <abbrtitle="Graphical User Interface">GUI</abbr> is that it is well integrated into jME and the jMonkeyEngine SDK, and that it offers all the features that you expect from a professional modern user interface.
</p>
<p>
@ -202,19 +193,17 @@ For HUDs, you basically follow the same instructions as for creating a normal <a
Users interact with your jME3 application with different input devices ??? the mouse, the keyboard, or a joystick. To respond to inputs we use the <code>inputManager</code> object in <code>SimpleApplication</code>.
Users interact with your jME3 application with different input devices – the mouse, the keyboard, or a joystick. To respond to inputs we use the <code>inputManager</code> object in <code>SimpleApplication</code>.
</p>
<p>
This is how you add interaction to your game:
</p>
<ol>
<li><div> For each action, choose the trigger(s) (a key or mouse click etc)</div>
@ -26,7 +24,7 @@ This is how you add interaction to your game:
@ -37,22 +35,22 @@ This is how you add interaction to your game:
</div>
<!-- EDIT2 SECTION "Code Samples" [562-858] -->
<h2><a>1. Choose Trigger</a></h2>
<h2>1. Choose Trigger</h2>
<div>
<p>
Choose one or several key/mouse events for the interaction. We use <code>KeyTrigger</code>, <code>MouseAxisTrigger</code>, <code>MouseButtonTrigger</code>, <code>JoyAxisTrigger</code> and <code>JoyButtonTrigger</code> constants from the <code>com.jme3.input.controls</code> package.
</p>
<p>
<strong>Note:</strong> The MouseAxis and JoyAxis triggers go along the X axis (right/left) or Y axis (up/down). These Triggers come with extra booleans for the negative half of the axis (left, down). Remember to write code that listens to the negative (true) and positive (false) axis!
</p>
<div><table>
<thead>
<tr>
<th> Trigger </th><th> Code </th>
</tr>
</thead>
<tr>
<td> Mouse button: Left Click </td><td> MouseButtonTrigger(MouseInput.BUTTON_LEFT) </td>
</tr>
@ -81,13 +79,13 @@ Choose one or several key/mouse events for the interaction. We use <code>KeyTrig
<td> Mouse wheel: Down </td><td> MouseAxisTrigger(MouseInput.AXIS_WHEEL,true) </td>
In your IDE, use code completion to quickly look up Trigger literals. In the jMonkeyEngine <acronymtitle="Software Development Kit">SDK</acronym> for example, press ctrl-space or ctrl-/ after <code>KeyInput.|</code> to choose from the list of all keys.
In your IDE, use code completion to quickly look up Trigger literals. In the jMonkeyEngine SDK for example, press ctrl-space or ctrl-/ after <code>KeyInput.|</code> to choose from the list of all keys.
The jME3 input manager supports two types of event listeners for inputs: AnalogListener and ActionListener. You can use one or both listeners in the same application. Add one or both of the following code snippets to your main SimpleApplication-based class to activate the listeners.
</p>
@ -207,15 +204,14 @@ The jME3 input manager supports two types of event listeners for inputs: AnalogL
To activate the mappings, you must register them to a Listener. Write your registration code after the code block where you have added the mappings to the inputManager.
</p>
<p>
In the following example, you register the "Pause Game" mapping to the <code>actionListener</code> object, because pausing a game is in "either/or" decision.
In the following example, you register the “Pause Game” mapping to the <code>actionListener</code> object, because pausing a game is in “either/or” decision.
</p>
<pre>inputManager.addListener(actionListener, new String[]{"Pause Game"});</pre>
<p>
In the following example, you register navigational mappings to the <code>analogListener</code> object, because walking is a continuous action. Players typically keep the key pressed to express continuity, for example when they want to "walk on" or "accelerate".
In the following example, you register navigational mappings to the <code>analogListener</code> object, because walking is a continuous action. Players typically keep the key pressed to express continuity, for example when they want to “walk on” or “accelerate”.
</p>
<pre>inputManager.addListener(analogListener, new String[]{"Left", "Right"});</pre>
@ -304,11 +298,10 @@ As you see, you can add several listeners in one String array. You can call the
</div>
<!-- EDIT11 SECTION "4. Register Mappings to Listeners" [6962-8210] -->
<h2><a>5. Implement Actions in Listeners</a></h2>
<h2>5. Implement Actions in Listeners</h2>
<div>
<p>
You specify the action to be triggered where it says TODO in the Listener code snippets. Typically, you write a series of if/else conditions, testing for all the mapping names, and then calling the respective action.
</p>
@ -324,14 +317,13 @@ Make use of the distinction between <code>if</code> and <code>else if</code> in
</div>
<!-- EDIT12 SECTION "5. Implement Actions in Listeners" [8211-8946] -->
<h3><a>ActionListener</a></h3>
<h3>ActionListener</h3>
<div>
<p>
In the most common case, you want an action to be triggered once, in the moment when the button or key trigger is released. For example, when the player presses a key to open a door, or clicks to pick up an item. For these cases, use an ActionListener and test for <code>&& !keyPressed</code>, like shown in the following example.
</p>
<pre>private ActionListener actionListener = new ActionListener(){
<pre>private ActionListener(){
public void onAction(String name, boolean keyPressed, float tpf){
if (name.equals("Pause Game")&& !keyPressed){ // test?
@ -345,11 +337,10 @@ In the most common case, you want an action to be triggered once, in the moment
The following example shows how you define actions with an AnalogListener. Thiese actions are triggered continuously, as long (intensity <code>value</code>) as the named key or mouse button is down. Use this listeners for semi-automatic weapons and navigational actions.
</p>
<pre>private AnalogListener analogListener = new AnalogListener(){
@ -366,23 +357,21 @@ The following example shows how you define actions with an AnalogListener. Thies
It is likely that your players have different keyboard layouts, are used to "reversed" mouse navigation, or prefer different navigational keys than the ones that you defined. You should create an options screen that lets users customize their mouse/key triggers for your mappings. Replace the trigger literals in the <code>inputManager.addMapping()</code> lines with variables, and load sets of triggers when the game starts.
It is likely that your players have different keyboard layouts, are used to “reversed” mouse navigation, or prefer different navigational keys than the ones that you defined. You should create an options screen that lets users customize their mouse/key triggers for your mappings. Replace the trigger literals in the <code>inputManager.addMapping()</code> lines with variables, and load sets of triggers when the game starts.
</p>
<p>
The abstraction of separating triggers and mappings has the advantage that you can remap triggers easily. Your code only needs to remove and add some trigger mappings. The core of the code (the listeners and actions) remains unchanged.
<h1><a>Saving and Loading Materials with .j3m Files</a></h1>
<h1>Saving and Loading Materials with .j3m Files</h1>
<div>
<p>
In the <ahref="/com/jme3/gde/docs/jme3/advanced/material_definitions.html">Material Definitions</a> article you learned how to configure <ahref="/com/jme3/gde/docs/jme3/advanced/materials_overview.html">Materials</a> programmatically in Java code. If you have certain commonly used Materials that never change, you can clean up the amount of Java code that clutters your init method, by moving material settings into .j3m files. Then later in your code, you only need to call one setter instead of several to apply the material.
</p>
@ -13,7 +12,7 @@ If you want to colorize simple shapes (one texture all around), then .j3m are th
</div>
<!-- EDIT1 SECTION "Saving and Loading Materials with .j3m Files" [1-753] -->
<h2><a>Writing the .j3m File</a></h2>
<h2>Writing the .j3m File</h2>
<div>
<ol>
<li><div> For every Material, create a file and give it a name that describes it: e.g. <code>SimpleBump.j3m</code></div>
@ -35,7 +34,6 @@ If you want to colorize simple shapes (one texture all around), then .j3m are th
</ol>
<p>
How to this file is structured:
</p>
<ol>
@ -60,40 +58,36 @@ How to this file is structured:
</ol>
<p>
<p><div>In the jMonkeyEngine <acronymtitle="Software Development Kit">SDK</acronym>, use File???New File???Material???Empty Material File to create .j3m files. You can edit .j3m files directly in the <acronymtitle="Software Development Kit">SDK</acronym>. On the other hand, they are plain text files, so you can also create them in any plain text editor.
<p><div>In the jMonkeyEngine SDK, use File→New File→Material→Empty Material File to create .j3m files. You can edit .j3m files directly in the SDK. On the other hand, they are plain text files, so you can also create them in any plain text editor.
</div></p>
</p>
</div>
<!-- EDIT2 SECTION "Writing the .j3m File" [754-2349] -->
<h2><a>How to Use .j3m Materials</a></h2>
<h2>How to Use .j3m Materials</h2>
<div>
<p>
This is how you use the prepared .j3m Material on a Spatial. Since you have saved the .j3m file to your project's Assets directory, the .j3m path is relative to <code>MyGame/src/assets/???</code>.
This is how you use the prepared .j3m Material on a Spatial. Since you have saved the .j3m file to your project's Assets directory, the .j3m path is relative to <code>MyGame/src/assets/…</code>.
<strong>Tip:</strong> In the jMonkeyEngine <acronymtitle="Software Development Kit">SDK</acronym>, open Windows>Palette and drag the <code>JME Material: Set J3M</code> snippet into your code.
<strong>Tip:</strong> In the jMonkeyEngine SDK, open Windows>Palette and drag the <code>JME Material: Set J3M</code> snippet into your code.
</p>
</div>
<!-- EDIT3 SECTION "How to Use .j3m Materials" [2350-2795] -->
<h2><a>Syntax Reference for .j3m Files</a></h2>
<h2>Syntax Reference for .j3m Files</h2>
<div>
</div>
<!-- EDIT4 SECTION "Syntax Reference for .j3m Files" [2796-2840] -->
<h3><a>Paths</a></h3>
<h3>Paths</h3>
<div>
<p>
Make sure to get the paths to the textures (.png, .jpg) and material definitions (.j3md) right.
</p>
<ul>
<li><div> The paths to the built-in .j3md files are relative to jME3's Core Data directory. Just copy the path stated in the <ahref="/com/jme3/gde/docs/jme3/advanced/materials_overview.html">Material</a> table. <br/>
@ -106,19 +100,19 @@ Make sure to get the paths to the textures (.png, .jpg) and material definitions
</div>
<!-- EDIT5 SECTION "Paths" [2841-3417] -->
<h3><a>Data Types</a></h3>
<h3>Data Types</h3>
<div>
<p>
All data types (except Color) are specified in com.jme3.shader.VarType.
"Color" is specified as Vector4 in J3MLoader.java.
“Color” is specified as Vector4 in J3MLoader.java.
<td> Float</td><td> (basic Java type) </td><td> a float (e.g. 0.72) , no comma or parentheses </td>
</tr>
@ -183,7 +177,7 @@ All data types (except Color) are specified in com.jme3.shader.VarType.
<!-- EDIT7 TABLE [3565-4979] -->
</div>
<!-- EDIT6 SECTION "Data Types" [3418-4981] -->
<h3><a>Flip and Repeat Syntax</a></h3>
<h3>Flip and Repeat Syntax</h3>
<div>
<ul>
<li><div> A texture can be flipped using the following syntax <code>NormalMap: Flip Textures/bump_rock_normal.png</code></div>
@ -196,26 +190,26 @@ All data types (except Color) are specified in com.jme3.shader.VarType.
</div>
<!-- EDIT8 SECTION "Flip and Repeat Syntax" [4982-5325] -->
<h3><a>Syntax for Additional Render States</a></h3>
<h3>Syntax for Additional Render States</h3>
<div>
<ul>
<li><div> A Boolean can be "On" or "Off"</div>
<li><div> A Boolean can be “On” or “Off”</div>
</li>
<li><div> Float is "123.0" etc</div>
<li><div> Float is “123.0” etc</div>
</li>
<li><div> Enum - values depend on the enum</div>
</li>
</ul>
<p>
See the <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://jmonkeyengine.org/javadoc/com/jme3/material/RenderState.html"><paramname="text"value="<html><u>RenderState</u></html>"><paramname="textColor"value="blue"></object> javadoc for a detailed explanation of render states.
<li><div><ahref="/com/jme3/gde/docs/jme3/advanced/material_specification.html">Developer specification of the jME3 material system (.j3md,.j3m)</a></div>
Shaders are sets of instructions that are executed on the GPU. They are used to take advantage of hardware acceleration available on the GPU for rendering purposes.<br/>
This paper only covers Vertex and Fragment shaders because they are the only ones supported by JME3 for the moment. But be aware that there are some other types of shaders (geometry, tessellation,???).<br/>
This paper only covers Vertex and Fragment shaders because they are the only ones supported by JME3 for the moment. But be aware that there are some other types of shaders (geometry, tessellation,…).<br/>
There are multiple frequently used languages that you may encounter to code shaders but as JME3 is based on OpenGL, shaders in JME use GLSL and any example in this paper will be written in GLSL.<br/>
<br/>
</p>
</div>
<!-- EDIT2 SECTION "Shaders Basics" [37-634] -->
<h3><a>How Does it work?</a></h3>
<h3>How Does it work?</h3>
<div>
<p>
@ -42,12 +40,11 @@ This is a very simplified graphic to describe the call stack: <br/>
The main program sends mesh data to the vertex shader (vertex position in object space, normals, tangents, etc..). The vertex shader computes the screen position of the vertex and sends it to the Fragment shader. The fragment shader computes the color, and the result is displayed on screen or in a texture.
<br/>
</p>
</div>
<!-- EDIT3 SECTION "How Does it work?" [635-1483] -->
<h3><a>Variables scope</a></h3>
<h3>Variables scope</h3>
<div>
<p>
@ -67,12 +64,11 @@ There is a large panel of variable types to be used, for more information about
@ -84,12 +80,11 @@ The engine passes the object space coordinates to the vertex shader. We need to
<br/>
</p>
</div>
<!-- EDIT5 SECTION "Spaces and Matrices" [2150-2694] -->
<h3><a>Simple example : rendering a solid color on an object</a></h3>
<h3>Simple example : rendering a solid color on an object</h3>
<div>
<p>
@ -97,7 +92,6 @@ Here is the simplest application to shaders, rendering a solid color.<br/>
Vertex Shader : <br/>
</p>
<pre>//the global uniform World view projection matrix
//(more on global uniforms below)
@ -116,10 +110,8 @@ void main(){
}</pre>
<p>
Fragment Shader : <br/>
</p>
<pre>void main(){
//returning the color of the pixel (here solid blue)
@ -129,28 +121,25 @@ Fragment Shader : <br/>
}</pre>
<p>
For example applying this shader to a sphere would render a solid blue sphere on screen.<br/>
<br/>
</p>
</div>
<!-- EDIT6 SECTION "Simple example : rendering a solid color on an object" [2695-3932] -->
<h1><a>How to use shaders in JME3</a></h1>
<h1>How to use shaders in JME3</h1>
<div>
<p>
You probably heard that JME3 is ???shader oriented???, but what does that mean?<br/>
You probably heard that JME3 is “shader oriented”, but what does that mean?<br/>
Usually to use shaders you must create what is called a program. This program specify the vertex shader and the fragment shader to use.<br/>
JME3 encloses this in the material system. Every material in JME3 uses shaders.<br/>
For example let???s have a look at the SolidColor.j3md file : <br/>
For example let’s have a look at the SolidColor.j3md file : <br/>
</p>
<pre>MaterialDef Solid Color {
@ -175,23 +164,21 @@ For example let???s have a look at the SolidColor.j3md file : <br/>
}</pre>
<p>
For more information on JME3 material system, i suggest you read this <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://jmonkeyengine.org/groups/development-discussion-jme3/forum/topic/jmonkeyengine3-material-system-full-explanation"><paramname="text"value="<html><u>topic</u></html>"><paramname="textColor"value="blue"></object>.<br/>
<br/>
</p>
</div>
<!-- EDIT7 SECTION "How to use shaders in JME3" [3933-5176] -->
<h3><a>JME3 Global uniforms</a></h3>
<h3>JME3 Global uniforms</h3>
<div>
<p>
JME3 can expose pre-computed global uniforms to your shaders. You must specify the one that are required for your shader in the WorldParameters section of the material definition file (.j3md).<br/>
Note that in the shader the uniform names will be prefixed by a ???g_???.<br/>
Note that in the shader the uniform names will be prefixed by a “g_”.<br/>
In the example above, WorldViewProjectionMatrix is declared as uniform mat4 g_WorldViewProjectionMatrix in the shader.<br/>
@ -199,12 +186,11 @@ The complete list of global uniforms that can be used in JME3 can be found <obje
<br/>
</p>
</div>
<!-- EDIT8 SECTION "JME3 Global uniforms" [5177-5798] -->
<h3><a>JME3 Lighting Global uniforms</a></h3>
<h3>JME3 Lighting Global uniforms</h3>
<div>
<p>
@ -225,7 +211,7 @@ JME3 uses some global uniforms for lighting :
</li>
<li><div> use for PointLight : x,y,z contain the world position of the light, the w component contains 1/lightRadius</div>
</li>
<li><div> use for DirectionalLight : strangely enough it's used for the direction of the light???this might change though. The fourth component contains -1 and it's used in the lighting shader to know if it's a directionalLight or not.</div>
<li><div> use for DirectionalLight : strangely enough it's used for the direction of the light…this might change though. The fourth component contains -1 and it's used in the lighting shader to know if it's a directionalLight or not.</div>
</li>
</ul>
</li>
@ -234,15 +220,14 @@ JME3 uses some global uniforms for lighting :
</ul>
<p>
These uniforms are passed to the shader without having to declare them in the j3md file, but you have to specify in the technique definition " LightMode MultiPass" see lighting.j3md for more information.
These uniforms are passed to the shader without having to declare them in the j3md file, but you have to specify in the technique definition “ LightMode MultiPass” see lighting.j3md for more information.
<br/>
</p>
</div>
<!-- EDIT9 SECTION "JME3 Lighting Global uniforms" [5799-6889] -->
<h3><a>JME3 attributes</a></h3>
<h3>JME3 attributes</h3>
<div>
<p>
@ -250,7 +235,7 @@ Those are different attributes that are always passed to your shader.<br/>
You can find a complete list of those attribute in the Type enum of the VertexBuffer <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/core/com/jme3/scene/VertexBuffer.java"><paramname="text"value="<html><u>here</u></html>"><paramname="textColor"value="blue"></object>.<br/>
Note that in the shader the attributes names will be prefixed by an ???in???.<br/>
Note that in the shader the attributes names will be prefixed by an “in”.<br/>
<br/>
@ -259,14 +244,13 @@ When the enumeration lists some usual types for each attribute (for example texC
@ -385,7 +362,7 @@ A result preview can be seen here: <object classid="java:org.netbeans.modules.ja
</div>
<!-- EDIT12 SECTION "Example: Adding Color Keying to the Lighting.j3md Material Definition" [9305-10795] -->
<h3><a>Step by step</a></h3>
<h3>Step by step</h3>
<div>
<ul>
<li><div> Create a vertex shader (.vert) file</div>
@ -396,37 +373,37 @@ A result preview can be seen here: <object classid="java:org.netbeans.modules.ja
</li>
<li><div> In your initSimpleApplication, create a material using this definition, apply it to a geometry</div>
</li>
<li><div> That???s it!!</div>
<li><div> That’s it!!</div>
</li>
</ul>
<pre> // A cube
Box box= new Box(Vector3f.ZERO, 1f,1f,1f);
Box(Vector3f.ZERO, 1f,1f,1f);
Geometry cube = new Geometry("box", box);
Material mat = new Material(assetManager,"Path/To/My/materialDef.j3md");
cube.setMaterial(mat);
rootNode.attachChild(cube);</pre>
<p>
<br/>
</p>
</div>
<!-- EDIT13 SECTION "Step by step" [10796-11415] -->
<h3><a>JME3 and OpenGL 3 & 4 compatibility</a></h3>
<h3>JME3 and OpenGL 3 & 4 compatibility</h3>
<div>
<p>
GLSL 1.0 to 1.2 comes with built in attributes and uniforms (ie, gl_Vertex, gl_ModelViewMatrix, etc???).<br/>
GLSL 1.0 to 1.2 comes with built in attributes and uniforms (ie, gl_Vertex, gl_ModelViewMatrix, etc…).<br/>
Those attributes are deprecated since GLSL 1.3 (opengl 3), hence JME3 global uniforms and attributes. Here is a list of deprecated attributes and their equivalent in JME3<br/>
@ -18,18 +17,16 @@ Light and Shadow are two separate things in 3D engines, although we percieve the
</ul>
<p>
<p><div>A light source with a direction or location is required for all Geometries with Lighting.j3md-based Materials. An ambient light is not sufficient. In a scene with no appropriate light sources, Geometries with Lighting.j3md-based Materials do not render. Only Geometries with Unshaded.j3md-based Materials are visible independent of any light sources.
</div></p>
</p>
</div>
<!-- EDIT1 SECTION "Light and Shadow" [1-1017] -->
@ -38,7 +35,7 @@ You can add several types of light sources to a scene using <code>rootNode.addLi
</p>
<p>
The available light sources in <code>com.???jme3.???light</code> are:
The available light sources in <code>com.jme3.light</code> are:
</p>
<ul>
<li><div> SpotLight </div>
@ -52,7 +49,6 @@ The available light sources in <code>com.???jme3.???light</code> are:
</ul>
<p>
You control the color and intensity of each light source. Typically you set the color to white (<code>new ColorRGBA(1.0f,1.0f,1.0f,1.0f)</code> or <code>ColorRGBA.White</code>), which makes all scene elements appear in their natural color.
</p>
@ -66,11 +62,10 @@ You can get a list of all lights added to a Spatial by calling <code>getWorldLig
</div>
<!-- EDIT2 SECTION "Light Sources and Colors" [1018-2059] -->
A DirectionalLight has no position, only a direction. It sends out parallel beams of light and is considered "infinitely" far away. You typically have one directional light per scene. A DirectionalLight can be used together with shadows.
A DirectionalLight has no position, only a direction. It sends out parallel beams of light and is considered “infinitely” far away. You typically have one directional light per scene. A DirectionalLight can be used together with shadows.
If you want the spotlight to follow the flycam, repeat the setDirection(???) and setPosition(???) calls in the update loop, and kee syncing them with the camera position and direction.
If you want the spotlight to follow the flycam, repeat the setDirection(…) and setPosition(…) calls in the update loop, and kee syncing them with the camera position and direction.
</p>
</div>
<!-- EDIT5 SECTION "SpotLight" [3356-4490] -->
<h3><a>AmbientLight</a></h3>
<h3>AmbientLight</h3>
<div>
<p>
An AmbientLight simply influences the brightness and color of the scene globally. It has no direction and no location and shines equally everywhere. An AmbientLight does not cast any shadows, and it lights all sides of Geometries evenly, which makes 3D objects look unnaturally flat; this is why you typically do not use an AmbientLight alone without one of the other lights.
You can use a <code>com.jme3.scene.control.LightControl</code> to make a SpotLight or PointLight follow a Spatial. This can be used for a flashlight being carried by a character, or for car headlights, or an aircraft's spotlight, etc.
</p>
<pre>PointLight myLight = new PointLight();
@ -182,11 +173,10 @@ Obviously, this does not apply to AmbientLights, which have no position.
@ -228,7 +219,6 @@ For each type of non-ambient light source, JME3 implements two ways to simulate
</table></div>
<!-- EDIT10 TABLE [6369-6708] -->
<p>
You only need one shadow simulation per light source: if you use shadow rendering, you won't need a shadow filter and vice versa. Which way is more efficient depends partly on the complexity of your scene. All six shadow simulation classes have similar interfaces, so once you know how to use one, you can easily figure out the rest.
</p>
@ -255,9 +245,7 @@ Here's a sample application which demonstrates both DirectionalLightShadowR
</ul>
<p>
Here is the key code fragment:
</p>
<pre> DirectionalLight sun = new DirectionalLight();
sun.setColor(ColorRGBA.White);
@ -280,26 +268,24 @@ Here is the key code fragment:
<p>
Constructor arguments:
* your AssetManager object
* size of the rendered shadow maps, in pixels per side (512, 1024, 2048, etc???)
* size of the rendered shadow maps, in pixels per side (512, 1024, 2048, etc…)
* the number of shadow maps rendered (more shadow maps = better quality, but slower)
</p>
<p>
Properties you can set:
* setDirection(Vector3f) ??? the direction of the light
<li><div><objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/post/TestTransparentSSAO.java"><paramname="text"value="<html><u>jme3/src/test/jme3test/post/TestTransparentSSAO.java</u></html>"><paramname="textColor"value="blue"></object>??? Screen-Space Ambient Occlusion shadows plus transparancy</div>
<li><div><objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/post/TestTransparentSSAO.java"><paramname="text"value="<html><u>jme3/src/test/jme3test/post/TestTransparentSSAO.java</u></html>"><paramname="textColor"value="blue"></object>– Screen-Space Ambient Occlusion shadows plus transparancy</div>
</li>
<li><div><objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://hub.jmonkeyengine.org/2010/08/screen-space-ambient-occlusion-for-jmonkeyengine-3-0/"><paramname="text"value="<html><u>Screen Space Ambient Occlusion for jMonkeyEngine (article)</u></html>"><paramname="textColor"value="blue"></object></div>
</li>
</ul>
<p>
Ambient Occlusion refers to the shadows which nearby objects cast on each other under an ambient lighting. Screen Space Ambient Occlusion (SSAO) approximates how light radiates in real life.
<h3><a>Creating the bindings to use the Nifty XML</a></h3>
<h3>Creating the bindings to use the Nifty XML</h3>
<div>
<p>
@ -128,7 +122,6 @@ There are 3 main ways to update a progress bar. To understand why these methods
<p>
Something like this in a single thread will not work:
</p>
<pre>load_scene();
update_bar(30%);
@ -138,8 +131,7 @@ load_sounds();
update_bar(100%);</pre>
<p>
If you do all of this in a single frame, then it is sent to the graphics card only after the whole code block has executed. By this time the bar has reached 100% and the game has already begun ??? for the user, the progressbar on the screen would not have visibly changed.
If you do all of this in a single frame, then it is sent to the graphics card only after the whole code block has executed. By this time the bar has reached 100% and the game has already begun – for the user, the progressbar on the screen would not have visibly changed.
</p>
<p>
@ -154,13 +146,11 @@ The 2 main good solutions are:
</div>
<h4><a>Updating progress bar over a number of frames</a></h4>
<h4>Updating progress bar over a number of frames</h4>
<div>
<p>
The idea is to break down the loading of the game into discrete parts
</p>
<pre>package jme3test;
@ -324,12 +314,12 @@ public class TestLoadingScreen extends SimpleApplication implements ScreenContro
}
@Override
public void bind(Nifty nifty, Screen screen, Element elmnt, Properties prprts, Attributes atrbts){
public void bind(Nifty nifty, Screen screen, Attributes atrbts){
Localizing an application can mean several things:
</p>
<ul>
<li><div> At minimum you translate all messages and dialogs in the user interface to your target languages.</div>
</li>
<li><div> You should also translate the "read me", help, and other documentation.</div>
<li><div> You should also translate the “read me”, help, and other documentation.</div>
</li>
<li><div> Also translating web content related to the application makes sure international users find out about your localized game.</div>
</li>
<li><div> If you go the whole way of internationalization, you also "translate" metaphors in icons or symbols used. <br/>
<li><div> If you go the whole way of internationalization, you also “translate” metaphors in icons or symbols used. <br/>
E.g. For localizations to right-to-left languages, you must also adjust the whole flow of the UI (order of menus and buttons).</div>
</li>
</ul>
<p>
There are tools that assist you with localizing Java Swing GUIs. jME3 applications do not typically have a Swing <acronymtitle="Graphical User Interface">GUI</acronym>, so those tools are not of much help. Just stick to the normal Java rules about using Bundle Properties:
There are tools that assist you with localizing Java Swing GUIs. jME3 applications do not typically have a Swing <abbrtitle="Graphical User Interface">GUI</abbr>, so those tools are not of much help. Just stick to the normal Java rules about using Bundle Properties:
</p>
</div>
<!-- EDIT2 SECTION "Scope" [39-879] -->
<h2><a>Preparing the Localization</a></h2>
<h2>Preparing the Localization</h2>
<div>
<p>
<strong>Tip:</strong> The jMonkeyEngine <acronymtitle="Software Development Kit">SDK</acronym> supports opening and editing Bundle.properties files. Also note the Tools > Localization menu.
<strong>Tip:</strong> The jMonkeyEngine SDK supports opening and editing Bundle.properties files. Also note the Tools > Localization menu.
</p>
<p>
To prepare the application for localization, you have to first identify all hard-coded messages.
</p>
<ol>
<li><div> Find every line in your jME3 game where you hard-coded message strings, e.g. <br/>
<li><div> In the source code, replace every occurence of a hard-coded message with the appropriate Resource Bundle call to its unique key: <pre>System.out.print(ResourceBundle.getBundle("Bundle").getString("greeting"));
<li><div> In the source code, replace every occurence of a hard-coded message with the appropriate Resource Bundle call to its unique key: <pre>ResourceBundle.getBundle("Bundle").getString("greeting"));
The language used in the Bundle.properties files will be the default language for your game.
</p>
</div>
<!-- EDIT3 SECTION "Preparing the Localization" [880-2088] -->
<h2><a>Translating the Messages</a></h2>
<h2>Translating the Messages</h2>
<div>
<p>
Each additional language comes in a set of files that is marked with a (usually) two-letter suffix. Common locales are de for German, en for English, fr for French, ja for Japanese, pt for Portuguese, etc.
</p>
<p>
To translate the messages to another language, for example, German:
</p>
<ol>
<li><div> Make a copy of the <code>Bundle.properties</code> files.</div>
<strong>Tip:</strong> In the jMonkeyEngine <acronymtitle="Software Development Kit">SDK</acronym>, you set this VM Option in the Project properties under Run. Here you can also save individual run configuraions for each language you want to test.
<strong>Tip:</strong> In the jMonkeyEngine SDK, you set this VM Option in the Project properties under Run. Here you can also save individual run configuraions for each language you want to test.
<!-- EDIT4 SECTION "Translating the Messages" [2089-3243] -->
<h2><a>Which Strings Not to Translate</a></h2>
<h2>Which Strings Not to Translate</h2>
<div>
<p>
<strong>Important:</strong> In the Bundle.properties file, do not include any strings that are asset paths, node or geometry names, input mappings, or material layers.
<!-- EDIT5 SECTION "Which Strings Not to Translate" [3244-3918] -->
<h2><a>Common Localization Problems</a></h2>
<h2>Common Localization Problems</h2>
<div>
<p>
Typical problems include:
</p>
<ul>
<li><div> Localized strings will be of vastly different lengths and will totally break your UI layout. ??? Test every localization.</div>
<li><div> Localized strings will be of vastly different lengths and will totally break your UI layout. ⇒ Test every localization.</div>
</li>
<li><div> Strings with variable text or numbers don't work the same in different languages. ??? Either work in grammatical cases/numbers/gender for each language, or use <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://www.gnu.org/software/gettext/manual/gettext.html#Plural-forms"><paramname="text"value="<html><u>gettext</u></html>"><paramname="textColor"value="blue"></object> or <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://userguide.icu-project.org/formatparse/messages"><paramname="text"value="<html><u>ICU4J</u></html>"><paramname="textColor"value="blue"></object>.</div>
<li><div> Strings with variable text or numbers don't work the same in different languages. ⇒ Either work in grammatical cases/numbers/gender for each language, or use <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://www.gnu.org/software/gettext/manual/gettext.html#Plural-forms"><paramname="text"value="<html><u>gettext</u></html>"><paramname="textColor"value="blue"></object> or <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://userguide.icu-project.org/formatparse/messages"><paramname="text"value="<html><u>ICU4J</u></html>"><paramname="textColor"value="blue"></object>.</div>
</li>
<li><div> The localizer only sees the strings, without any context. E.g. does "Search History" mean "display the history of searches", or "search through the history"? ??? Use clear key labels. Work closely with the localizers if they require extra info, and add that info as comments to the translation file.</div>
<li><div> The localizer only sees the strings, without any context. E.g. does “Search History” mean “display the history of searches”, or “search through the history”? ⇒ Use clear key labels. Work closely with the localizers if they require extra info, and add that info as comments to the translation file.</div>
</li>
<li><div> Broken international characters ??? Make sure the files are saved with the same character encoding as the font file(s) you're using. Nowadays, that usually means UTF-8 since font files tend to come for Unicode.</div>
<li><div> Broken international characters ⇒ Make sure the files are saved with the same character encoding as the font file(s) you're using. Nowadays, that usually means UTF-8 since font files tend to come for Unicode.</div>
</li>
<li><div> Missing international characters ??? Make sure that there's a glyph for every needed character in your font, either by using more complete font files or by having the translation changed.</div>
<li><div> Missing international characters ⇒ Make sure that there's a glyph for every needed character in your font, either by using more complete font files or by having the translation changed.</div>
<!-- EDIT1 SECTION "Logging and Monitoring" [1-38] -->
<h2><a>Logging Like a Newbie</a></h2>
<h2>Logging Like a Newbie</h2>
<div>
<p>
Many developers just use <code>System.out.println()</code> to print diagnostic strings to the terminal. The problem with that is that before the release, you have to go through all your code and make certain you removed all these <code>println()</code> calls. You do not want your customers to see them, and needlessly worry about ominous outdated debugging diagnostics.
</p>
</div>
<!-- EDIT2 SECTION "Logging Like a Newbie" [39-428] -->
<h2><a>Logging Like a Pro</a></h2>
<h2>Logging Like a Pro</h2>
<div>
<p>
Instead of <code>println()</code>, use the standard Java logger from <code>java.util.logging</code>. It has many advantages for professional game development:
</p>
<ul>
@ -37,7 +35,6 @@ Instead of <code>println()</code>, use the standard Java logger from <code>java.
</ul>
<p>
To print comments like a pro, you use the following logger syntax.
</p>
<ol>
@ -64,8 +61,7 @@ Example: <code>Vector3f a = cam.getLocation();</code> </div>
</ol>
<p>
<p><div>As you see in the examples, you should phrase potentially "customer facing" errors in a neutral way and offer <em>a reason and a solution</em> for the error (if you don't, it has no value to your customer). If your deveopment team uses WARNINGs as replacement for casual printlns, make sure you deactivate them for the release.
<p><div>As you see in the examples, you should phrase potentially “customer facing” errors in a neutral way and offer <em>a reason and a solution</em> for the error (if you don't, it has no value to your customer). If your deveopment team uses WARNINGs as replacement for casual printlns, make sure you deactivate them for the release.
</div></p>
</p>
@ -75,39 +71,34 @@ More details about <object classid="java:org.netbeans.modules.javahelp.BrowserDi
</div>
<!-- EDIT3 SECTION "Logging Like a Pro" [429-2826] -->
<h2><a>Switching the Logger on and off</a></h2>
<h2>Switching the Logger on and off</h2>
<div>
<p>
In the release version you will deactivate the logging output to the terminal.
</p>
<p>
To deactivate the default logger for a release, you set the log level to only report <code>severe</code> messages:
<!-- EDIT4 SECTION "Switching the Logger on and off" [2827-3468] -->
<h2><a>Advanced Error Handling</a></h2>
<h2>Advanced Error Handling</h2>
<div>
<p>
When an uncaught exception reaches certain parts of the jME3 system then the default response is to log the error and then exit the application. This is because an error happening every frame will rapidly fill logs with repeated failings and potentially mask or over-write the original cause of the problem or even the application may continue for a while and then suffer other errors caused by the first and make the root cause hard to determine.
</p>
@ -117,4 +108,4 @@ This behaviour can be partially modified by overriding the method handleError in
<h1><a>Making the Camera Follow a 3rd-Person Character</a></h1>
<h1>Making the Camera Follow a 3rd-Person Character</h1>
<div>
<p>
When players steer a game character with 1st-person view, they directly steer the camera (<code>flyCam.setEnabled(true);</code>), and they never see the walking character itself. In a game with 3rd-person view, however, the players see the character walk, and you (the game developer) want to make the camera follow the character around when it walks.
</p>
@ -18,13 +17,12 @@ There are two ways how the camera can do that:
</ul>
<p>
<strong>Important:</strong> Using third-person view requires you to deactivate the default flyCam (first-person view). This means that you have to configure your own navigation (<ahref="/com/jme3/gde/docs/jme3/advanced/input_handling.html">key inputs and analogListener</a>) that make your player character walk. For moving a physical player character, use <code>player.setWalkDirection()</code>, for a non-physical character you can use <code>player.move()</code>.
</p>
</div>
<!-- EDIT1 SECTION "Making the Camera Follow a 3rd-Person Character" [1-990] -->
<h2><a>Code Samples</a></h2>
<h2>Code Samples</h2>
<div>
<p>
@ -39,7 +37,7 @@ Press the WASD or arrow keys to move. Drag with the left mouse button to rotate.
<strong>Important:</strong> Where the example says <code>camNode.setLocalTranslation(new Vector3f(0, 5, -5));</code>, you have to supply your own start position for the camera. This depends on the size of your target (the player character) and its position in your particular scene. Optimally, you set this to a spot a bit behind and above the target.
</p>
<div><table>
<thead>
<tr>
<th>Methods</th><th>Description</th>
</tr>
</thead>
<tr>
<td>setControlDir(ControlDirection.SpatialToCamera)</td><td>User input steers the target spatial, and the camera follows the spatial.<br/>
The spatial's transformation is copied over the camera's transformation. <br/>
@ -78,21 +77,19 @@ The camera's transformation is copied over the spatial's transformatio
</table></div>
<!-- EDIT4 TABLE [2446-2957] -->
<p>
<strong>Code sample:</strong>
</p>
<ul>
<li><div><objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/input/TestCameraNode.java"><paramname="text"value="<html><u>TestCameraNode.java</u></html>"><paramname="textColor"value="blue"></object>??? Press the WASD or arrow keys to move. Drag with the left mouse button to rotate.</div>
<li><div><objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/input/TestCameraNode.java"><paramname="text"value="<html><u>TestCameraNode.java</u></html>"><paramname="textColor"value="blue"></object>– Press the WASD or arrow keys to move. Drag with the left mouse button to rotate.</div>
</li>
</ul>
</div>
<!-- EDIT3 SECTION "Camera Node" [1373-3198] -->
<h2><a>Chase Camera</a></h2>
<h2>Chase Camera</h2>
<div>
<p>
To activate the chase camera, add the following code to your init method (e.g. <code>simpleInitApp()</code>). The <code>target</code> spatial is typically the player node. You will be able to rotate the target by dragging (keeping the left mouse button pressed and moving the mouse).
ChaseCamera chaseCam = new ChaseCamera(cam, target, inputManager);
chaseCam.setSmoothMotion(true);</pre>
<div><table>
<thead>
<tr>
<th>Method</th><th>Description</th>
</tr>
</thead>
<tr>
<td>setInvertVerticalAxis(true)</td><td>Invert the camera's vertical rotation Axis </td>
</tr>
@ -139,28 +138,27 @@ new KeyTrigger(KeyInput.KEY_SPACE))</td><td>Activate mutiple triggers for the ro
</table></div>
<!-- EDIT6 TABLE [3733-5145] -->
<p>
<strong>Code sample:</strong>
</p>
<ul>
<li><div><objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/input/TestChaseCamera.java"><paramname="text"value="<html><u>TestChaseCamera.java</u></html>"><paramname="textColor"value="blue"></object>??? Press the WASD or arrow keys to move. Drag with the left mouse button to rotate.</div>
<li><div><objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/input/TestChaseCamera.java"><paramname="text"value="<html><u>TestChaseCamera.java</u></html>"><paramname="textColor"value="blue"></object>– Press the WASD or arrow keys to move. Drag with the left mouse button to rotate.</div>
</li>
</ul>
</div>
<!-- EDIT5 SECTION "Chase Camera" [3199-5388] -->
<h2><a>Which to Choose?</a></h2>
<h2>Which to Choose?</h2>
<div>
<p>
What is the difference of the two code samples above?
</p>
<div><table>
<thead>
<tr>
<th>CameraNode</th><th>ChaseCam</th>
</tr>
</thead>
<tr>
<td>Camera follows immediately, flies at same speed as target.</td><td>Camera moves smoothly and accelerates and decelerates, flies more slowly than the target and catches up.</td>
</tr>
@ -174,4 +172,4 @@ What is the difference of the two code samples above?
<h1><a>How to Use Material Definitions (.j3md)</a></h1>
<h1>How to Use Material Definitions (.j3md)</h1>
<div>
<p>
All Geometries need a Material to be visible. Every Material is based on a Material Definition. Material definitions provide the "logic" for the material, and a shader draws the material according to the parameters specified in the definition. The J3MD file abstracts the shader and its configuration away from the user, allowing a simple interface where the user can simply set a few parameters on the material to change its appearance and the way its handled by the shaders.
All Geometries need a Material to be visible. Every Material is based on a Material Definition. Material definitions provide the “logic” for the material, and a shader draws the material according to the parameters specified in the definition. The J3MD file abstracts the shader and its configuration away from the user, allowing a simple interface where the user can simply set a few parameters on the material to change its appearance and the way its handled by the shaders.
</p>
<p>
@ -13,7 +12,6 @@ The most common Material Definitions are included in the engine, advanced users
Material mat = new Material(assetManager, // Create new material and...
@ -28,11 +26,10 @@ myGeometry.setMaterial(mat); // Use material on this Geome
</div>
<!-- EDIT1 SECTION "How to Use Material Definitions (.j3md)" [1-1585] -->
<h2><a>Preparing a Material</a></h2>
<h2>Preparing a Material</h2>
<div>
<p>
In the <ahref="/com/jme3/gde/docs/jme3/advanced/materials_overview.html">Materials Overview</a> list:
</p>
<ol>
@ -42,17 +39,17 @@ In the <a href="/com/jme3/gde/docs/jme3/advanced/materials_overview.html">Materi
</li>
</ul>
</li>
<li><div> Look at the applicable parameters of the Material Definition and determine which parameters you need to achieve the desired effect (e.g. "glow" or "color"). Most parameters are optional! </div>
<li><div> Look at the applicable parameters of the Material Definition and determine which parameters you need to achieve the desired effect (e.g. “glow” or “color”). Most parameters are optional! </div>
</li>
<li><div> Create and save the necessary Texture files to your <code>assets/Textures</code> directory.</div>
<ul>
<li><div> E.g. mytex_diffuse.png as ColorMap / DiffuseMap, mytex_normal.png as NormalMap, mytex_alpha.png as AlphaMap, etc???</div>
<li><div> E.g. mytex_diffuse.png as ColorMap / DiffuseMap, mytex_normal.png as NormalMap, mytex_alpha.png as AlphaMap, etc…</div>
</li>
</ul>
</li>
<li><div> Determine the required values to achieve the effect that you want.</div>
<ul>
<li><div> E.g. set colors, floats, booleans, etc???</div>
<li><div> E.g. set colors, floats, booleans, etc…</div>
</li>
</ul>
</li>
@ -60,11 +57,10 @@ In the <a href="/com/jme3/gde/docs/jme3/advanced/materials_overview.html">Materi
</div>
<!-- EDIT2 SECTION "Preparing a Material" [1586-2329] -->
<h2><a>Using a Material</a></h2>
<h2>Using a Material</h2>
<div>
<p>
In your Java code,
</p>
<ol>
@ -83,36 +79,32 @@ In your Java code,
</ol>
<p>
For details see also: <ahref="/com/jme3/gde/docs/jme3/intermediate/how_to_use_materials.html">How to Use Materials</a>
</p>
</div>
<!-- EDIT3 SECTION "Using a Material" [2330-3036] -->
<h3><a>Examples</a></h3>
<h3>Examples</h3>
<div>
<p>
Here are examples of the methods that set the different data types:
You can test these examples within the following code snippet. It creates a box and applies the material:
</p>
<pre> Box b = new Box(Vector3f.ZERO, 1, 1, 1);
<pre> Box(Vector3f.ZERO, 1, 1, 1);
Geometry geom = new Geometry("Box", b);
// ... insert Material definition...
geom.setMaterial(mat);
rootNode.attachChild(geom);</pre>
<p>
<p><div>You can find these and other common code snippets in the jMonkeyEngine <acronymtitle="Software Development Kit">SDK</acronym> Code Palette. Drag and drop them into your source code.
<p><div>You can find these and other common code snippets in the jMonkeyEngine SDK Code Palette. Drag and drop them into your source code.
</div></p>
</p>
</div>
<!-- EDIT4 SECTION "Examples" [3037-4410] -->
<h2><a>Creating a Custom Material Definition</a></h2>
<h2>Creating a Custom Material Definition</h2>
<div>
<p>
First read the <ahref="/com/jme3/gde/docs/jme3/advanced/material_specification.html">developer specification of the jME3 material system (.j3md,.j3m)</a>. Also check out the <ahref="/com/jme3/gde/docs/jme3/build_from_sources.html">engine source code</a> and have a look at how some Material Definitions are implemented.
</p>
<p>
You can create your own Material Definitions and place them in your project's <code>assets/MatDefs</code> directory.
</p>
<ol>
<li><div> Find the existing MatDefs in <code>engine/src/core-data/Common/MatDefs/</code>. </div>
@ -174,20 +163,17 @@ You can create your own Material Definitions and place them in your project'
</div>
<!-- EDIT5 SECTION "Creating a Custom Material Definition" [4411-5384] -->
<h2><a>Related Links</a></h2>
<h2>Related Links</h2>
<div>
<ul>
<li><div><ahref="/com/jme3/gde/docs/jme3/advanced/material_specification.html">Developer specification of the jME3 material system (.j3md,.j3m)</a></div>
In jMonkeyEngine 3, colors and textures are represented as Material objects.
</p>
<ul>
<li><div> All Geometries must have Materials. To improve performance, reuse Materials for similar models, don't create a new Material object for every Geometry. (E.g. use one bark Material for several tree models.) </div>
@ -15,7 +13,6 @@ In jMonkeyEngine 3, colors and textures are represented as Material objects.
</ul>
<p>
<p><div>Find out quickly <ahref="/com/jme3/gde/docs/jme3/intermediate/how_to_use_materials.html">How to Use Materials</a>, including the most commonly used code samples and RenderStates. <br/>
Or find more background info on <ahref="/com/jme3/gde/docs/jme3/advanced/material_definitions.html">How to use Material Definitions</a>.
</div></p>
@ -23,11 +20,10 @@ Or find more background info on <a href="/com/jme3/gde/docs/jme3/advanced/materi
The following Materials table shows you the Material Definitions that jMonkeyEngine 3 supports.
</p>
@ -45,11 +41,10 @@ Most Material parameters are optional. For example, it is okay to specify solely
</div>
<!-- EDIT2 SECTION "All Materials Definition Properties" [842-1717] -->
<h3><a>Unshaded Coloring and Textures</a></h3>
<h3>Unshaded Coloring and Textures</h3>
<div>
<p>
jMonkeyEngine supports illuminated and unshaded Material Definitions.
</p>
<ul>
@ -60,54 +55,54 @@ jMonkeyEngine supports illuminated and unshaded Material Definitions.
</ul>
<p>
"Unshaded" materials look somewhat abstract because they ignore lighting and shading. Unshaded Materials work even if the scene does not include a light source. These Materials can be single-colored or textured. For example, they are used for cards and tiles, for the sky, billboards and UI elements, for toon-style games, or for testing.
“Unshaded” materials look somewhat abstract because they ignore lighting and shading. Unshaded Materials work even if the scene does not include a light source. These Materials can be single-colored or textured. For example, they are used for cards and tiles, for the sky, billboards and UI elements, for toon-style games, or for testing.
</p>
<div><table>
<thead>
<tr>
<th> Standard Unshaded Material Definition </th><th> Usage </th><th> Material Parameters </th>
<td> Common/MatDefs/Misc/Particle.j3md </td><td> Used with texture masks for particle effects, or for point sprites. <br/>
The Quadratic value scales the particle for perspective view (<objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/core/com/jme3/effect/ParticleEmitter.java"><paramname="text"value="<html><u>formula</u></html>"><paramname="textColor"value="blue"></object>). <br/>
Does support an optional colored glow effect. <br/>
See also: <ahref="/com/jme3/gde/docs/jme3/beginner/hello_effects.html">Hello Effects</a></td><td> setTexture("Texture", assetManager.loadTexture("")); <br/>
<!-- EDIT3 SECTION "Unshaded Coloring and Textures" [1718-5468] -->
<h3><a>Phong Illuminated</a></h3>
<h3>Phong Illuminated</h3>
<div>
<p>
jMonkeyEngine supports illuminated and unshaded Material Definitions.
</p>
<ul>
@ -161,52 +155,54 @@ jMonkeyEngine supports illuminated and unshaded Material Definitions.
</ul>
<p>
Illuminated materials require a <ahref="/com/jme3/gde/docs/jme3/advanced/light_and_shadow.html">light source</a> added to at least one of their parent nodes! (e.g. rootNode.) Illuminated materials are darker on the sides facing away from light sources. They use Phong illumination model (default), or the Ward isotropic gaussian specular shader (WardIso) which looks more like plastic. They do not cast <ahref="/com/jme3/gde/docs/jme3/advanced/light_and_shadow.html">drop shadows</a> unless you use a FilterPostProcessor.
</p>
<div><table>
<thead>
<tr>
<th>Standard Illuminated Material Definition </th><th> Usage </th><th> Material Parameters </th>
</tr>
</thead>
<tr>
<td> Common/MatDefs/Light/Lighting.j3md </td><td> Commonly used Material with Phong illumination. <br/>
Use this material together with DiffuseMap, SpecularMap, BumpMap (NormalMaps, ParalaxMap) textures. <br/>
Supports shininess, transparency, and plain material colors (Diffuse, Ambient, Specular colors). <br/>
See also: <ahref="/com/jme3/gde/docs/jme3/beginner/hello_material.html">Hello Material</a></td><td><strong>Texture Maps</strong><br/>
<th>Special Illuminated Material Definitions </th><th> Usage </th><th> Material Parameters </th>
</tr>
</thead>
<tr>
<td>Common/MatDefs/Terrain/TerrainLighting.j3md</td><td>Same kind of multi-layered splat texture as Terrain.j3md, but with illumination and shading. <br/>
Typically used for terrains, but works on any mesh. <br/>
@ -215,50 +211,52 @@ You can use a total of 11 texture maps in the terrain's splat texture: <br/
Note that diffuse and normal maps all count against that. <br/>
For example, you can use a maximum of 9 diffuse textures, two of which can have normal maps; <br/>
or, five textures with both diffuse and normal maps.</td><td><strong>Texture Splat Maps</strong><br/>
<td> Common/MatDefs/Misc/ShowNormals.j3md </td><td> A color gradient calculated from the model's surface normals. You can use this built-in material to debug the generation of normals in meshes, to preview models that have no material and no lights, or as fall-back default material. This built-in material has no parameters. </td>
<td>getAdditionalRenderState().setBlendMode(BlendMode.Off);</td><td>This is the default, no transparency.</td><td>Use for all opaque objects like walls, floors, people???</td>
<td>getAdditionalRenderState().setBlendMode(BlendMode.Off);</td><td>This is the default, no transparency.</td><td>Use for all opaque objects like walls, floors, people…</td>
</tr>
<tr>
<td>getAdditionalRenderState().setBlendMode(BlendMode.Alpha);</td><td>Interpolates the background pixel with the current pixel by using the current pixel's alpha.</td><td>Use this for normal every-day translucency: Frosted window panes, ice, glass, alpha-blended vegetation textures???</td>
<td>getAdditionalRenderState().setBlendMode(BlendMode.Alpha);</td><td>Interpolates the background pixel with the current pixel by using the current pixel's alpha.</td><td>Use this for normal every-day translucency: Frosted window panes, ice, glass, alpha-blended vegetation textures…</td>
</tr>
<tr>
<td>getAdditionalRenderState().setDepthWrite(false);</td><td>Disables writing of the pixel's depth value to the depth buffer.</td><td>Use this on Materials if you have several transparent/translucent objects obscuring one another, but you want to see through both.</td>
getAdditionalRenderState().setAlphaTest(true)</td><td>Enables Alpha Testing with a "AlphaDiscardThreshold" in the AlphaMap.</td><td>Activate Alpha Testing for (partially) <strong>transparent</strong> objects such as foliage, hair, etc. <br/>
getAdditionalRenderState().setAlphaTest(true)</td><td>Enables Alpha Testing with a “AlphaDiscardThreshold” in the AlphaMap.</td><td>Activate Alpha Testing for (partially) <strong>transparent</strong> objects such as foliage, hair, etc. <br/>
Deactivate Alpha Testing for gradually <strong>translucent</strong> objects, such as colored glass, smoked glass, ghosts.</td>
<strong>Note:</strong> Viewed in front of a white background, Additive textures become fully transparent! </td><td> This is the default for Particle.j3md-based textures that have a black color background. </td>
</tr>
<tr>
<td>getAdditionalRenderState().setBlendMode(BlendMode.AlphaAdditive);</td><td>Same as "Additive", except first it multiplies the current pixel color by the pixel alpha.</td><td>This can be used for particle effects that have alpha as background. </td>
<td>getAdditionalRenderState().setBlendMode(BlendMode.AlphaAdditive);</td><td>Same as “Additive”, except first it multiplies the current pixel color by the pixel alpha.</td><td>This can be used for particle effects that have alpha as background. </td>
</tr>
<tr>
<td>getAdditionalRenderState().setBlendMode(BlendMode.Color);</td><td>Blends by color.</td><td>Generally useless.</td>
<td>getAdditionalRenderState().setBlendMode(BlendMode.Modulate);</td><td>Multiplies the background pixel by the current pixel.</td><td>?</td>
</tr>
<tr>
<td>getAdditionalRenderState().setBlendMode(BlendMode.ModulateX2);</td><td>Same as "Modulate", except the result is doubled.</td><td>?</td>
<td>getAdditionalRenderState().setBlendMode(BlendMode.ModulateX2);</td><td>Same as “Modulate”, except the result is doubled.</td><td>?</td>
</tr>
<tr>
<td>getAdditionalRenderState().setBlendMode(BlendMode.PremultAlpha);</td><td>Pre-multiplied alpha blending. E.g. if the color of the object has already been multiplied by its alpha, this is used instead of "Alpha" blend mode.</td><td>For use with Premult Alpha textures.</td>
<td>getAdditionalRenderState().setBlendMode(BlendMode.PremultAlpha);</td><td>Pre-multiplied alpha blending. E.g. if the color of the object has already been multiplied by its alpha, this is used instead of “Alpha” blend mode.</td><td>For use with Premult Alpha textures.</td>
<td>getAdditionalRenderState().setFaceCullMode(FaceCullMode.Back); </td><td>Activates back-face culling. Mesh faces that are facing away from the camera are not rendered, which saves time. *Backface culling is activated by default as a major optimization.* </td><td>The invisible backsides and insides of models are not calculated. </td>
</tr>
@ -346,7 +346,7 @@ Later, put the Geometry (not the Material!) in the appropriate render queue
<td>getAdditionalRenderState().setFaceCullMode(FaceCullMode.Off); </td><td>No meshes are culled. Both mesh faces are rendered, even if they face away from the camera. Slow.</td><td>Sometimes used to debug custom meshes if you messed up some of the polygon sides, or for special shadow effects.</td>
</tr>
<tr>
<td>getAdditionalRenderState().setFaceCullMode(FaceCullMode.Front); </td><td>Activates front-face culling. Mesh faces facing the camera are not rendered.</td><td>No example ??? Typically not used because you wouldn't see anything meaningful.</td>
<td>getAdditionalRenderState().setFaceCullMode(FaceCullMode.Front); </td><td>Activates front-face culling. Mesh faces facing the camera are not rendered.</td><td>No example – Typically not used because you wouldn't see anything meaningful.</td>
</tr>
<tr>
<td>getAdditionalRenderState().setFaceCullMode(FaceCullMode.FrontAndBack)</td><td>Culls both backfaces and frontfaces.</td><td>Use this as an efficient way to make an object temporarily invisible, while keeping all its other in-game properties (such as node attachment, collision shapes, interactions, etc) active.</td>
@ -355,14 +355,14 @@ Later, put the Geometry (not the Material!) in the appropriate render queue
<!-- EDIT15 TABLE [13361-14503] -->
</div>
<!-- EDIT14 SECTION "Culling" [13342-14504] -->
<h3><a>Miscellaneous</a></h3>
<h3>Miscellaneous</h3>
<div>
<div><table>
<tr>
<td>getAdditionalRenderState().setColorWrite(false);</td><td>Disable writing the color of pixels.</td><td>Use this together with setDepthWrite(true) to write pixels only to the depth buffer, for example. </td>
</tr>
<tr>
<td>getAdditionalRenderState().setPointSprite(true);</td><td>Enables point-sprite mode, e.g. meshes with "Mode.Points" will be rendered as textured sprites. Note that gl_PointCoord must be set in the shader.</td><td>Point sprites are used internally for hardware accelerated particle effects.</td>
<td>getAdditionalRenderState().setPointSprite(true);</td><td>Enables point-sprite mode, e.g. meshes with “Mode.Points” will be rendered as textured sprites. Note that gl_PointCoord must be set in the shader.</td><td>Point sprites are used internally for hardware accelerated particle effects.</td>
</tr>
<tr>
<td>getAdditionalRenderState().setPolyOffset();</td><td>Enable polygon offset.</td><td>Use this when you have meshes that have triangles really close to each over (e.g. <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://en.wikipedia.org/wiki/Coplanarity"><paramname="text"value="<html><u>Coplanar</u></html>"><paramname="textColor"value="blue"></object>), it will shift the depth values to prevent <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://en.wikipedia.org/wiki/Z-fighting"><paramname="text"value="<html><u>Z-fighting</u></html>"><paramname="textColor"value="blue"></object>.</td>
@ -370,23 +370,16 @@ Later, put the Geometry (not the Material!) in the appropriate render queue
</table></div>
<!-- EDIT17 TABLE [14530-15296] -->
<p>
<strong>Related Links</strong>
</p>
<ul>
<li><div><ahref="/com/jme3/gde/docs/jme3/advanced/material_specification.html">Developer specification of the jME3 material system (.j3md,.j3m)</a></div>
All visible game elements in a scene, whether it is a Model or a Shape, are made up of polygon meshes. JME3 has a com.jme3.scene.Mesh class that represents all meshes.
</p>
<ul>
<li><div> Meshes are made up of triangles: <code>getTriangleCount(???)</code> and <code>getTriangle(???)</code></div>
<li><div> Meshes are made up of triangles: <code>getTriangleCount(…)</code> and <code>getTriangle(…)</code></div>
</li>
<li><div> Each mesh has a unique ID: <code>getId()</code></div>
</li>
@ -31,7 +29,6 @@ All visible game elements in a scene, whether it is a Model or a Shape, are made
</ul>
<p>
You have several options when <ahref="/com/jme3/gde/docs/jme3/advanced/spatial.html">creating Geometries from meshes</a>:
</p>
<ul>
@ -45,22 +42,23 @@ You have several options when <a href="/com/jme3/gde/docs/jme3/advanced/spatial.
</div>
<!-- EDIT1 SECTION "Polygon Meshes" [1-1154] -->
<h2><a>Vertex Buffer</a></h2>
<h2>Vertex Buffer</h2>
<div>
<p>
The VertexBuffer contains a particular type of geometry data used by Meshes. Every VertexBuffer set on a Mesh is sent as an attribute to the vertex shader to be processed.
Optionally, custom meshes can have a LOD (level of detail optimization) that renders more or less detail, depending on the distance of the mesh from the camera. You have to specify several vertex buffers, one for each level of detail you want (very far away with few details, close up with all details, and something in the middle). Use <code>setLodLevels(VertexBuffer[] lodLevels)</code>.
@ -10,7 +10,7 @@ MonkeyZone is an multi-player demo game provided by the jME core developer team.
</li>
<li><div><objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://www.youtube.com/watch?v=98yITEoJvqE"><paramname="text"value="<html><u>Watch pre-alpha video footage</u></html>"><paramname="textColor"value="blue"></object> (YouTube Video)</div>
</li>
<li><div><objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://jmonkeyengine.org/2011/02/13/monkeyzone-a-jme3-game-from-the-core/"><paramname="text"value="<html><u>Read "MonkeyZone ??? a jME3 game from the core"</u></html>"><paramname="textColor"value="blue"></object> (news article)</div>
<li><div><objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://jmonkeyengine.org/2011/02/13/monkeyzone-a-jme3-game-from-the-core/"><paramname="text"value="<html><u>Read "MonkeyZone – a jME3 game from the core"</u></html>"><paramname="textColor"value="blue"></object> (news article)</div>
</li>
<li><div><objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://jmonkeyengine.org/groups/user-code-projects/forum/topic/open-game-finder/"><paramname="text"value="<html><u>Related forum thread: Open Game Finder</u></html>"><paramname="textColor"value="blue"></object></div>
</li>
@ -22,20 +22,19 @@ This open-source demo:
<ol>
<li><div> showcases one possible way to implement a game with jME3, and</div>
</li>
<li><div> helps the jME team verify the jME3 <acronymtitle="Application Programming Interface">API</acronym> in terms of usability.</div>
<li><div> helps the jME team verify the jME3 <abbrtitle="Application Programming Interface">API</abbr> in terms of usability.</div>
</li>
</ol>
<p>
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 <acronymtitle="Software Development Kit">SDK</acronym>, 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 <acronymtitle="Software Development Kit">SDK</acronym> 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!)
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!)
@ -44,96 +43,89 @@ When a human user or an AI performs an action (presses a button), the actual log
<br/>
<br/>
<em>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 <acronymtitle="Application Programming Interface">API</acronym> 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.</em>
<em>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 <abbrtitle="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.</em>
The game uses certain terms that might be familiar to you but maybe used in another way, so heres a quick rundown on the terms being used.
</p>
<ul>
<li><div> Player ??? Logical human or AI player that can enter entities and generally act, only exists as PlayerData ???database??? with an id.</div>
<li><div> Player – Logical human or AI player that can enter entities and generally act, only exists as PlayerData “database” with an id.</div>
</li>
<li><div> 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.</div>
<li><div> 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.</div>
</li>
<li><div> User ??? Human player using a client</div>
<li><div> User – Human player using a client</div>
</li>
<li><div> 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.</div>
<li><div> 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.</div>
</li>
<li><div> Client ??? Computer connected to server</div>
<li><div> Client – Computer connected to server</div>
</li>
</ul>
</div>
<!-- EDIT3 SECTION "Terminology" [2672-3492] -->
<h3><a>Manager Classes</a></h3>
<h3>Manager Classes</h3>
<div>
<p>
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.).
<ahref="/com/jme3/gde/docs/jme3/advanced/custom_controls.html">Controls</a> 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.
</p>
</div>
<h4><a>...As entity capabilities</a></h4>
<h4>...As entity capabilities</h4>
<div>
<p>
Controls attached to Spatials are generally used like an ???array of capabilities??? that the entity posesses. So when an entity has a VehicleControl its expected to be a vehicle, when its got a CharacterControl its expected to be a character.
Controls attached to Spatials are generally used like an “array of capabilities” that the entity posesses. 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.
</p>
</div>
<h4><a>... to abstract</a></h4>
<h4>... to abstract</h4>
<div>
<p>
Furthermore theres 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.
</p>
</div>
<h4><a>... for AI functions</a></h4>
<h4>... for AI functions</h4>
<div>
<p>
A special Control called CommandControl handles the Commands that can be executed by user controlled players, see below.
</p>
</div>
<!-- EDIT5 SECTION "Use of Controls" [4263-5866] -->
<h3><a>Artificial Intelligence</a></h3>
<h3>Artificial Intelligence</h3>
<div>
<p>
MonkeyZone includes simple AI functions based on a command queue.
</p>
</div>
<h4><a>Commands</a></h4>
<h4>Commands</h4>
<div>
<p>
@ -164,73 +156,67 @@ To implement autonomous AI players MonkeyZone uses a system of Commands that are
</div>
<h4><a>Triggers</a></h4>
<h4>Triggers</h4>
<div>
<p>
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).
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).
</p>
</div>
<h4><a>NavMesh</a></h4>
<h4>NavMesh</h4>
<div>
<p>
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 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???.
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”.
</p>
</div>
<!-- EDIT7 SECTION "Networking" [7722-8296] -->
<h2><a>Use of jMonkeyEngine SDK tools</a></h2>
<h2>Use of jMonkeyEngine SDK tools</h2>
<div>
<p>
All assets used in the game, like entity models and loaded maps can be preconfigured and edited using the jMonkeyEngine <acronymtitle="Software Development Kit">SDK</acronym>. For example, to add a new vehicle type, a vehicle is created in the jMonkeyEngine <acronymtitle="Software Development Kit">SDK</acronym> 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.
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.
</p>
</div>
<!-- EDIT8 SECTION "Use of jMonkeyEngine SDK tools" [8297-8863] -->
<h3><a>UserData</a></h3>
<h3>UserData</h3>
<div>
<p>
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 <acronymtitle="Software Development Kit">SDK</acronym> allows adding and editing this UserData, so entity properties are editable visually.
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.
</p>
</div>
<!-- EDIT9 SECTION "UserData" [8864-9145] -->
<h3><a>Physics</a></h3>
<h3>Physics</h3>
<div>
<p>
VehicleControls, CharacterControls and RigidBodyControls with mesh collision shape for terrain and objects are generated in the jMonkeyEngine <acronymtitle="Software Development Kit">SDK</acronym> 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.
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.
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 GoogleCode, where you can check out the jMonkeyEngine <acronymtitle="Software Development Kit">SDK</acronym>-ready project via svn:
MonkeyZone is hosted at GoogleCode, where you can check out the jMonkeyEngine SDK-ready project via svn:
</p>
<ol>
<li><div> jMonkeyEngine <acronymtitle="Software Development Kit">SDK</acronym>???Team???Subversion???Checkout,</div>
<li><div> Enter the SVN <acronymtitle="Uniform Resource Locator">URL</acronym><code><objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://monkeyzone.googlecode.com/svn/trunk/"><paramname="text"value="<html><u>http://monkeyzone.googlecode.com/svn/trunk/</u></html>"><paramname="textColor"value="blue"></object></code></div>
<li><div> Enter the SVN <abbrtitle="Uniform Resource Locator">URL</abbr><code><objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://monkeyzone.googlecode.com/svn/trunk/"><paramname="text"value="<html><u>http://monkeyzone.googlecode.com/svn/trunk/</u></html>"><paramname="textColor"value="blue"></object></code></div>
</li>
<li><div> Download, open, and build the project</div>
</li>
@ -322,20 +308,17 @@ MonkeyZone is hosted at GoogleCode, where you can check out the jMonkeyEngine <a
</div>
<!-- EDIT13 SECTION "The Future" [10028-10550] -->
<h2><a>Troubleshooting</a></h2>
<h2>Troubleshooting</h2>
<div>
<ol>
<li><div> 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 </div>
A MotionPath describes the motion of a spatial between waypoints. The path can be linear or rounded. You use MotionPaths to remote-control a spatial, or the camera.
</p>
@ -13,7 +12,7 @@ A MotionPath describes the motion of a spatial between waypoints. The path can b
@ -24,11 +23,10 @@ A MotionPath describes the motion of a spatial between waypoints. The path can b
</div>
<!-- EDIT2 SECTION "Sample Code" [366-689] -->
<h2><a>What Are Way Points?</a></h2>
<h2>What Are Way Points?</h2>
<div>
<p>
When shooting a movie scene, the director tells actors where to walk, for example, by drawing a series of small crosses on the floor. Cameramen often mount the camera on rails (so called dolly track) so they can follow along complex scenes more easily.
</p>
@ -48,13 +46,11 @@ The final shape of the path is computed using a linear interpolation or a <objec
</div>
<!-- EDIT3 SECTION "What Are Way Points?" [690-1498] -->
<h2><a>Create a MotionPath</a></h2>
<h2>Create a MotionPath</h2>
<div>
<p>
Create a Motionpath object and add way points to it.
<td>path.setCycle(true)</td><td>Sets whether the motion along this path should be closed (true) or open-ended (false). </td>
</tr>
@ -95,11 +92,10 @@ removeWayPoint(index)</td><td>Removes a way point from this path. You can specif
<!-- EDIT5 TABLE [1769-2660] -->
</div>
<!-- EDIT4 SECTION "Create a MotionPath" [1499-2661] -->
<h2><a>MotionPathListener</a></h2>
<h2>MotionPathListener</h2>
<div>
<p>
You can hook interactions into a playing MotionPath. Register a MotionPathListener to the MotionPath to track whether way points have been reached, and then trigger a custom action. The onWayPointReach() method of the interface gives you access to the MotionTrack object <code>control</code>, and an integer value representing the current wayPointIndex.
</p>
@ -118,4 +114,4 @@ In this example, you just print the status at every way point. In a game you cou
Mouse picking means that the user clicks an object in the scene to select it, or to interact with it otherwise. Games use picking to implement aiming and shooting, casting spells, picking up objects, selecting targets, dragging and moving objects, etc. Mouse picking can be done using fixed crosshairs, or using the mouse pointer.
</p>
@ -17,13 +16,11 @@ See <a href="/com/jme3/gde/docs/jme3/advanced/input_handling.html">Input Handlin
</div>
<!-- EDIT1 SECTION "Mouse Picking" [1-533] -->
<h2><a>Pick a Target Using Fixed Crosshairs</a></h2>
<h2>Pick a Target Using Fixed Crosshairs</h2>
<div>
<p>
The following <code>pick target</code> input mapping implements an action that determines what a user clicked. It assumes that the mouse pointer is invisible and there are crosshairs painted in the center of the screen. It assumes that the user aims the crosshairs at an object in the scene and clicks. You use Ray Casting to identify the geometry that was picked by the user. Use this method together with a first-person flyCam.
</p>
<ol>
<li><div> Activate the first-person camera: <code>flyCam.setEnabled(true);</code></div>
@ -37,7 +34,7 @@ The following <code>pick target</code> input mapping implements an action that d
</ol>
<p>
The following example rotates Spatials named "Red Box" or "Blue Box" when they are clicked. Modify this code to do whatever your game needs to do with the identified target (shoot it, take it, move it, etc).
The following example rotates Spatials named “Red Box” or “Blue Box” when they are clicked. Modify this code to do whatever your game needs to do with the identified target (shoot it, take it, move it, etc).
</p>
<pre> private AnalogListener analogListener = new AnalogListener(){
public void onAnalog(String name, float intensity, float tpf){
@ -51,7 +48,7 @@ The following example rotates Spatials named "Red Box" or "Blue B
rootNode.collideWith(ray, results);
// Print the results so we see what is going on
for (int i = 0; i < results.size(); i++){
// For each ???hit???, we know distance, impact point, geometry.
// For each “hit”, we know distance, impact point, geometry.
@ -73,17 +70,15 @@ The following example rotates Spatials named "Red Box" or "Blue B
</div>
<!-- EDIT2 SECTION "Pick a Target Using Fixed Crosshairs" [534-3105] -->
<h2><a>Pick a Target Using the Mouse Pointer</a></h2>
<h2>Pick a Target Using the Mouse Pointer</h2>
<div>
<p>
The following <code>pick target</code> input mapping implements an action that determines what a user clicked. It assumes that the mouse pointer is visible, and the user aims the cursor at an object in the scene. You use ray casting to determine the geometry that was picked by the user.
</p>
<p>
<strong>Note:</strong> Picking with a visible mouse pointer implies that your application can no longer use the default flyCam where the MouseAxisTrigger rotates the camera. You have to deactivate the flyCam mappings and provide custom mappings. Either different inputs rotate the camera, or the camera is fixed.
</p>
<ol>
<li><div> Map the <code>pick target</code> action to a MouseButtonTrigger. </div>
@ -97,8 +92,7 @@ The following <code>pick target</code> input mapping implements an action that d
</ol>
<p>
The following example rotates Spatials named "Red Box" or "Blue Box" when they are clicked. Modify this code to do whatever your game needs to do with the identified target (shoot it, take it, move it, etc).
The following example rotates Spatials named “Red Box” or “Blue Box” when they are clicked. Modify this code to do whatever your game needs to do with the identified target (shoot it, take it, move it, etc).
</p>
<pre>private AnalogListener analogListener = new AnalogListener(){
public void onAnalog(String name, float intensity, float tpf){
@ -115,7 +109,7 @@ The following example rotates Spatials named "Red Box" or "Blue B
rootNode.collideWith(ray, results);
// (Print the results so we see what is going on:)
for (int i = 0; i < results.size(); i++){
// (For each ???hit???, we know distance, impact point, geometry.)
// (For each “hit”, we know distance, impact point, geometry.)
You can split the screen and look into the 3D scene from different camera angles at the same time. E.g. you can have two rootnodes with different scene graphs, and two viewPorts, each of which can only see its own subset of the scene with its own subset of port-processing filters, so you get two very different views of the scene.
</p>
@ -13,22 +12,19 @@ The packages used in this example are <code>com.jme3.renderer.Camera</code> and
</div>
<!-- EDIT1 SECTION "Multiple Camera Views" [1-650] -->
<h2><a>How to resize and Position ViewPorts</a></h2>
<h2>How to resize and Position ViewPorts</h2>
<div>
<p>
The default viewPort is as big as the window. If you have several, they must be of different sizes, either overlapping or adjacent to one another. How do you tell jME which of the ViewPorts should appear where on the screen, and how big they should be?
</p>
<p>
Imagine the window as a 1.0f x 1.0f rectangle. The default cam's viewPort is set to
You use the preconfigured Camera <code>cam</code> and <code>viewPort</code> from <code>SimpleApplication</code> for the first view. It's in the bottom right.
</p>
<pre>cam.setViewPort(.5f, 1f, 0f, 0.5f); // Resize the viewPort to half its size, bottom right.</pre>
<p>
Optionally, place the main camera in the scene and rotate it in its start position.
<!-- EDIT4 SECTION "Set up the First View" [2464-2960] -->
<h3><a>Set Up Three More Views</a></h3>
<h3>Set Up Three More Views</h3>
<div>
<p>
Here is the outline for how you create the three other cams and viewPorts (<objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/renderer/TestMultiViews.java"><paramname="text"value="<html><u>Full code sample is here</u></html>"><paramname="textColor"value="blue"></object>.) In the code snippet, <code>cam_n</code> stand for <code>cam_2</code> - <code>cam_4</code>, respectively, same for <code>view_n</code>.
</p>
<ol>
<li><div> Clone the first cam to reuse its settings</div>
@ -130,9 +117,7 @@ The camera doesn't have to look at the rootNode, but that is the most commo
</ol>
<p>
Here is the abstract code sample for camera <code>n</code>:
</p>
<pre>Camera cam_n = cam.clone();
cam_n.setViewPort(...); // resize the viewPort
jME3 is similar to Swing in that, for speed and efficiency, all changes to the scene graph must be made in a single update thread. If you make changes only in Control.update(), AppState.update(), or SimpleApplication.simpleUpdate(), this will happen automatically. However, if you pass work to another thread, you may need to pass results back to the main jME3 thread so that scene graph changes can take place there.
</p>
<pre>public void rotateGeometry(final Geometry geo, final Quaternion rot){
@ -20,16 +19,14 @@ Note that this example does not fetch the returned value by calling <code>get()<
<p>
If the processing thread needs to wait or needs the return value then <code>get()</code> or the other methods in the returned Future object such as <code>isDone()</code> can be used.
</p>
</div>
<!-- EDIT1 SECTION "The jME3 Threading Model" [1-1143] -->
<h1><a>Multithreading Optimization</a></h1>
<h1>Multithreading Optimization</h1>
<div>
<p>
First, make sure you know what <ahref="/com/jme3/gde/docs/jme3/advanced/application_states.html">Application States</a> and <ahref="/com/jme3/gde/docs/jme3/advanced/custom_controls.html">Custom Controls</a> are.
</p>
@ -47,13 +44,11 @@ Effectively, each for-loop in the main update loop might be a chance for multith
The java.util.concurrent package provides a good foundation for multithreading and dividing work into tasks that can be executed concurrently (hence the name). The three basic components are the Executor (supervises threads), Callable Objects (the tasks), and Future Objects (the result). You can <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://download.oracle.com/javase/tutorial/essential/concurrency/"><paramname="text"value="<html><u>read about the concurrent package more here</u></html>"><paramname="textColor"value="blue"></object>, I will give just a short introduction.
</p>
<ul>
<li><div> A Callable is one of the classes that gets executed on a thread in the Executor. The object represents one of several concurrent tasks (e.g, one NPC's path finding task). Each Callable is started from the updateloop by calling a method named <code>call()</code>.</div>
@ -66,11 +61,10 @@ The java.util.concurrent package provides a good foundation for multithreading a
@ -84,11 +78,10 @@ To avoid slowdown, we decide to keep the pathfinding operations in the NPC Contr
</div>
<!-- EDIT4 SECTION "Multithreading in jME3" [3348-4020] -->
<h3><a>Executor</a></h3>
<h3>Executor</h3>
<div>
<p>
You create the executor object in a global AppState (or the initSimpleApp() method), in any case in a high-level place where multiple controls can access it.
</p>
<pre>/* This constructor creates a new executor with a core pool size of 4. */
@ -101,7 +94,6 @@ Pool size means the executor will keep four threads alive at any time. Having mo
<p>
!!! Executor needs to be shut down when the application ends, in order to make the process die properly
In your simple application you can override the destroy method and shutdown the executor:
</p>
<pre> @Override
public void destroy(){
@ -111,11 +103,10 @@ In your simple application you can override the destroy method and shutdown the
</div>
<!-- EDIT5 SECTION "Executor" [4021-5096] -->
<h3><a>Control Class Fields</a></h3>
<h3>Control Class Fields</h3>
<div>
<p>
In the NPC Control, we create the individual objects that the thread manipulates. In our example case (the pathfinding control), the task is about locations and path arrays, so we need the following variables:
</p>
<pre>//The vector to store the desired location in:
@ -131,11 +122,10 @@ Here we also created the Future variable to track the state of this task.
</div>
<!-- EDIT6 SECTION "Control Class Fields" [5097-5687] -->
<h3><a>Control Update() Method</a></h3>
<h3>Control Update() Method</h3>
<div>
<p>
Next let's look at the update() call of the Control where the time-intensive task starts. In our example, the task is the <code>findWay</code> Callable (which contains the pathfinding process). So instead of spelling out the pathfinding process in the Control's update() loop, we start the process via <code>future = executor.submit(findWay);</code>.
</p>
<pre>public void update(float tpf){
@ -174,16 +164,15 @@ Note how this logic makes its decision based on the Future object.
</p>
<p>
Remember not to mess with the class fields after starting the thread, because they are being accessed and modified on the new thread. In more obvious terms: You cannot change the "desired location" of the NPC while the path finder is calculating a different path. You have to cancel the current Future first.
Remember not to mess with the class fields after starting the thread, because they are being accessed and modified on the new thread. In more obvious terms: You cannot change the “desired location” of the NPC while the path finder is calculating a different path. You have to cancel the current Future first.
The next code sample shows the Callable that is dedicated to performing the long-running task (here, wayfinding). This is the task that used to block the rest of the application, and is now executed on a thread of its own. You implement the task in the Callable always in an inner method named <code>call()</code>.
</p>
@ -193,7 +182,6 @@ The task code in the Callable should be self-contained! It should not write or r
<p>
In reality, you might need access to the game state. If you must read or write a current state from the scene graph, you must have a clone of the data in your thread. There are only two ways:
</p>
<ul>
<li><div> Use the execution queue <code>application.enqueue()</code> to create a sub-thread that clones the info. Only disadvantage is, it may be slower. <br/>
@ -205,7 +193,6 @@ The following example gets the object <code>Data data = myWorld.getData();</code
</ul>
<p>
These two ways are thread-safe, they don't mess up the game logic, and keep the Callable code readable.
</p>
<pre>// A self-contained time-intensive task:
@ -214,10 +201,10 @@ private Callable<MyWayList> findWay = new Callable<MyWayList>(&#
//Read or write data from the scene graph -- via the execution queue:
// This world class allows safe access via synchronized methods
@ -231,33 +218,23 @@ private Callable<MyWayList> findWay = new Callable<MyWayList>(&#
</div>
<!-- EDIT8 SECTION "The Callable" [7560-9926] -->
<h2><a>Useful Links</a></h2>
<h2>Useful Links</h2>
<div>
<p>
High level description which describes how to manage the game state and the rendering in different threads - <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://www.altdevblogaday.com/2011/07/03/threading-and-your-game-loop/"><paramname="text"value="<html><u>link</u></html>"><paramname="textColor"value="blue"></object>
High level description which describes how to manage the game state and the rendering in different threads - <del><objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://www.altdevblogaday.com/2011/07/03/threading-and-your-game-loop/"><paramname="text"value="<html><u>link</u></html>"><paramname="textColor"value="blue"></object></del> Outdated link. A C++ example can be found at <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://gamasutra.com/blogs/AndreaMagnorsky/20130527/193087/Multithreading_rendering_in_a_game_engine_with_CDouble_buffer_implementation.php"><paramname="text"value="<html><u>link</u></html>"><paramname="textColor"value="blue"></object>
The cool thing about this approach is that every entity creates one self-contained Callable for the Executor, and they are all executed in parallel. In theory, you can have one thread per entity without changing anything else but the settings of the executor.
This document introduces you to the SpiderMonkey networking <acronymtitle="Application Programming Interface">API</acronym>. You use this <acronymtitle="Application Programming Interface">API</acronym> when you develop games where several players compete with one another in real time. A multi-player game is made up of several clients connecting to a server:
This document introduces you to the SpiderMonkey networking <abbrtitle="Application Programming Interface">API</abbr>. You use this <abbrtitle="Application Programming Interface">API</abbr> when you develop games where several players compete with one another in real time. A multi-player game is made up of several clients connecting to a server:
</p>
<ul>
<li><div> The central server (one headless SimpleApplication) coordinates the game in the background.</div>
@ -15,35 +13,33 @@ This document introduces you to the SpiderMonkey networking <acronym title="Appl
</ul>
<p>
Each Client keeps the Server informed about its player's moves and actions. The Server centrally maintains the game state and broadcasts the state info back to all connected clients. This network synchronization allows all clients to share the same game world. Each client then displays the game state to one player from this player's perspective.
The SpiderMonkey <acronymtitle="Application Programming Interface">API</acronym> is a set of interfaces and helper classes in the 'com.jme3.network' package. For most users, this package and the 'message' package is all they need to worry about. (The 'base' and 'kernel' packages only come into play when implementing custom network transports or alternate client/server protocols, which is now possible).
The SpiderMonkey <abbrtitle="Application Programming Interface">API</abbr> is a set of interfaces and helper classes in the 'com.jme3.network' package. For most users, this package and the 'message' package is all they need to worry about. (The 'base' and 'kernel' packages only come into play when implementing custom network transports or alternate client/server protocols, which is now possible).
</p>
<p>
The SpiderMonkey <acronymtitle="Application Programming Interface">API</acronym> assists you in creating a Server, Clients, and Messages. Once a Server instance is created and started, the Server accepts remote connections from Clients, and you can send and receive Messages. Client objects represent the client-side of the client-server connection. Within the Server, these Client objects are referred to as HostedConnections. HostedConnections can hold application-defined client-specific session attributes that the server-side listeners and services can use to track player information, etc.
The SpiderMonkey <abbrtitle="Application Programming Interface">API</abbr> assists you in creating a Server, Clients, and Messages. Once a Server instance is created and started, the Server accepts remote connections from Clients, and you can send and receive Messages. Client objects represent the client-side of the client-server connection. Within the Server, these Client objects are referred to as HostedConnections. HostedConnections can hold application-defined client-specific session attributes that the server-side listeners and services can use to track player information, etc.
</p>
<div><table>
<thead>
<tr>
<th> Seen from the Client </th><th></th><th> Seen from the Server </th>
You can register several types of listeners to be notified of changes.
</p>
<ul>
@ -59,17 +55,16 @@ You can register several types of listeners to be notified of changes.
</div>
<!-- EDIT2 SECTION "SpiderMonkey API Overview" [842-2609] -->
<h2><a>Client and Server</a></h2>
<h2>Client and Server</h2>
<div>
</div>
<!-- EDIT4 SECTION "Client and Server" [2610-2640] -->
<h3><a>Creating a Server</a></h3>
<h3>Creating a Server</h3>
<div>
<p>
The game server is a "headless" com.jme3.app.SimpleApplication:
The game server is a “headless” com.jme3.app.SimpleApplication:
</p>
<pre>public class ServerMain extends SimpleApplication {
public static void main(String[] args){
@ -99,11 +94,10 @@ When you run this app on a host, the server is ready to accept clients. Let'
</div>
<!-- EDIT5 SECTION "Creating a Server" [2641-3591] -->
<h3><a>Creating a Client</a></h3>
<h3>Creating a Client</h3>
<div>
<p>
A game client is a standard com.jme3.app.SimpleApplication.
</p>
<pre>public class ClientMain extends SimpleApplication {
@ -119,7 +113,6 @@ A game client is a standard com.jme3.app.SimpleApplication.
</p>
<p>
Create a com.jme3.network.Client in the <code>simpleInitApp()</code> method and specify the servers IP address, and the same communication port as for the server, here 6143.
</p>
<pre>public void simpleInitApp(){
@ -129,7 +122,7 @@ Create a com.jme3.network.Client in the <code>simpleInitApp()</code> method and
...</pre>
<p>
The server address can be in the format "localhost" or "127.0.0.1" (for local testing), or an IP address of a remote host in the format ???123.456.78.9???. In this example, we assume the server is running on the localhost.
The server address can be in the format “localhost” or “127.0.0.1” (for local testing), or an IP address of a remote host in the format “123.456.78.9”. In this example, we assume the server is running on the localhost.
</p>
<p>
@ -138,18 +131,18 @@ When you run this client, it connects to the server.
</div>
<!-- EDIT6 SECTION "Creating a Client" [3592-4757] -->
<h3><a>Getting Info About a Client</a></h3>
<h3>Getting Info About a Client</h3>
<div>
<p>
The server refers to a connected client as com.jme3.network.HostedConnection objects. The server can get info about clients as follows:
</p>
<div><table>
<thead>
<tr>
<th>Accessor</th><th>Purpose</th>
</tr>
</thead>
<tr>
<td>myServer.getConnections()</td><td>Server gets a collection of all connected HostedConnection objects (all connected clients).</td>
</tr>
@ -162,34 +155,33 @@ The server refers to a connected client as com.jme3.network.HostedConnection obj
</table></div>
<!-- EDIT8 TABLE [4934-5313] -->
<p>
Your game can define its own game data based on whatever criteria you want, typically these include player ID and state. If the server needs to look up player/client-specific information, you can store this information directly on the HostedConnection object. The following examples read and write a custom Java object <code>MyState</code> in the HostedConnection object <code>conn</code>:
</p>
<div><table>
<thead>
<tr>
<th>Accessor</th><th>Purpose</th>
</tr>
</thead>
<tr>
<td> conn.setAttribute("MyState", new MyState()); </td><td> Server can change an attribute of the HostedConnection. </td>
<td> conn.setAttribute(“MyState”, new MyState()); </td><td> Server can change an attribute of the HostedConnection. </td>
</tr>
<tr>
<td> MyState state = conn.getAttribute("MyState")</td><td> Server can read an attribute of the HostedConnection. </td>
<td> MyState state = conn.getAttribute(“MyState”)</td><td> Server can read an attribute of the HostedConnection. </td>
</tr>
</table></div>
<!-- EDIT9 TABLE [5688-5917] -->
</div>
<!-- EDIT7 SECTION "Getting Info About a Client" [4758-5918] -->
<h2><a>Messaging</a></h2>
<h2>Messaging</h2>
<div>
</div>
<!-- EDIT10 SECTION "Messaging" [5919-5941] -->
<h3><a>Creating Message Types</a></h3>
<h3>Creating Message Types</h3>
<div>
<p>
Each message represents data that you want to transmit between client and server. Common message examples include transformation updates or game actions. For each message type, create a message class that extends com.jme3.network.AbstractMessage. Use the @Serializable annotation from com.jme3.network.serializing.Serializable and create an empty default constructor. Custom constructors, fields, and methods are up to you and depend on the message data that you want to transmit.
</p>
<pre>@Serializable
@ -206,23 +198,20 @@ You must register each message type to the com.jme3.network.serializing.Serializ
After a Message was received, a Listener responds to it. The listener can access fields of the message, and send messages back, start new threads, etc. There are two listeners, one on the server, one on the client. For each message type, you implement the responses in either Listeners??? <code>messageReceived()</code> method.
After a Message was received, a Listener responds to it. The listener can access fields of the message, and send messages back, start new threads, etc. There are two listeners, one on the server, one on the client. For each message type, you implement the responses in either Listeners’ <code>messageReceived()</code> method.
</p>
</div>
<h4><a>ClientListener.java</a></h4>
<h4>ClientListener.java</h4>
<div>
<p>
Create one ClientListener.java and make it extend <code>com.jme3.network.MessageListener</code>.
</p>
<pre>public class ClientListener implements MessageListener<Client>{
public void messageReceived(Client source, Message message){
@ -240,11 +229,10 @@ For each message type, register a client listener to the client.
</div>
<h4><a>ServerListener.java</a></h4>
<h4>ServerListener.java</h4>
<div>
<p>
Create one ServerListener.java and make it extend <code>com.jme3.network.MessageListener</code>.
</p>
<pre>public class ServerListener implements MessageListener<HostedConnection>{
@ -263,11 +251,10 @@ For each message type, register a server listener to the server:
</div>
<!-- EDIT12 SECTION "Responding to Messages" [6895-8639] -->
<h3><a>Creating and Sending Messages</a></h3>
<h3>Creating and Sending Messages</h3>
<div>
<p>
Let's create a new message of type HelloMessage:
</p>
<pre>Message message = new HelloMessage("Hello World!");</pre>
@ -290,7 +277,6 @@ Or the server can send the message to a specific subset of clients (e.g. to Host
<p>
Or the server can send the message to all but a few selected clients (e.g. to all HostedConnections but conn4):
@ -300,11 +286,10 @@ The last two broadcasting methods use com.jme3.network.Filters to select a subse
</div>
<!-- EDIT13 SECTION "Creating and Sending Messages" [8640-9729] -->
<h2><a>Identification and Rejection</a></h2>
<h2>Identification and Rejection</h2>
<div>
<p>
The ID of the Client and HostedConnection are the same at both ends of a connection. The ID is given out authoritatively by the Server.
</p>
<pre>... myClient.getId() ...</pre>
@ -316,21 +301,19 @@ A server has a game version and game name property. Each client expects to commu
<p>
<p><div>Typically, your networked game defines its own attributes (such as player ID) based on whatever criteria you want. If you want to look up player/client-specific information beyond the game version, you can set this information directly on the Client/HostedConnection object (see Getting Info About a Client).
</div></p>
</p>
</div>
<!-- EDIT14 SECTION "Identification and Rejection" [9730-10680] -->
<h2><a>Closing Clients and Server Cleanly</a></h2>
<h2>Closing Clients and Server Cleanly</h2>
<div>
</div>
<!-- EDIT15 SECTION "Closing Clients and Server Cleanly" [10681-10727] -->
<h3><a>Closing a Client</a></h3>
<h3>Closing a Client</h3>
<div>
<p>
You must override the client's destroy() method to close the connection cleanly when the player quits the client:
</p>
<pre> @Override
@ -342,11 +325,10 @@ You must override the client's destroy() method to close the connection cle
</div>
<!-- EDIT16 SECTION "Closing a Client" [10728-11003] -->
<h3><a>Closing a Server</a></h3>
<h3>Closing a Server</h3>
<div>
<p>
You must override the server's destroy() method to close the connection when the server quits:
</p>
<pre> @Override
@ -358,44 +340,42 @@ You must override the server's destroy() method to close the connection whe
</div>
<!-- EDIT17 SECTION "Closing a Server" [11004-11260] -->
<h3><a>Kicking a Client</a></h3>
<h3>Kicking a Client</h3>
<div>
<p>
The server can kick a HostedConnection to make it disconnect. You should provide a String with further info (an explanation to the user what happened, e.g. "Shutting down for maintenance") for the server to send along. This info message can be used (displayed to the user) by a ClientStateListener. (See below)
The server can kick a HostedConnection to make it disconnect. You should provide a String with further info (an explanation to the user what happened, e.g. “Shutting down for maintenance”) for the server to send along. This info message can be used (displayed to the user) by a ClientStateListener. (See below)
<!-- EDIT18 SECTION "Kicking a Client" [11261-11651] -->
<h2><a>Listening to Connection Notification</a></h2>
<h2>Listening to Connection Notification</h2>
<div>
<p>
The server and clients are notified about connection changes.
</p>
</div>
<!-- EDIT19 SECTION "Listening to Connection Notification" [11652-11763] -->
<h3><a>ClientStateListener</a></h3>
<h3>ClientStateListener</h3>
<div>
<p>
The com.jme3.network.ClientStateListener notifies the Client when the Client has fully connected to the server (including any internal handshaking), and when the Client is kicked (disconnected) from the server.
</p>
<p>
<p><div>The ClientStateListener when it receives a network exception applies the default close action. This just stops the client and you'll have to build around it so your application knows what to do. If you need more control when a network exception happens and the client closes, you may want to investigate in a ErrorListener.
The com.jme3.network.ConnectionListener notifies the Server whenever new HostedConnections (clients) come and go. The listener notifies the server after the Client connection is fully established (including any internal handshaking).
<td> public void connectionAdded(Server s, HostedConnection c){} </td><td> Implemenent here what happens after a new HostedConnection has joined the Server. </td>
</tr>
@ -433,19 +412,16 @@ The com.jme3.network.ConnectionListener notifies the Server whenever new HostedC
</table></div>
<!-- EDIT23 TABLE [13184-13582] -->
<p>
First implement the ConnectionListener interface in the Server class. Then register it to myServer in MyGameServer's simpleInitApp() method.
The com.jme3.network.ErrorListener is a listener for when network exception happens. This listener is built so that you can override the default actions when a network exception happens.
</p>
@ -453,19 +429,19 @@ The com.jme3.network.ErrorListener is a listener for when network exception happ
<p><div>If you intend on using the default network mechanics, <strong>don't</strong> use this!
If you do override this, make sure you add a mechanic that can close the client otherwise your client will get stuck open and cause errors.
SpiderMonkey supports both UDP (unreliable, fast) and TCP (reliable, slow) transport of messages.
</p>
<pre>message1.setReliable(true); // TCP
message2.setReliable(false); // UDP</pre>
<ul>
<li><div> Choose reliable and slow transport for messages, if you want to make certain the message is delivered (resent) when lost, and if the order of a series of messages is relevant. E.g. game actions such as "1. wield weapon, 2. attack, 3. dodge".</div>
<li><div> Choose reliable and slow transport for messages, if you want to make certain the message is delivered (resent) when lost, and if the order of a series of messages is relevant. E.g. game actions such as “1. wield weapon, 2. attack, 3. dodge”.</div>
</li>
<li><div> Choose unreliable and fast transport for messages if the next message makes any previously delayed or lost message obsolete and synchronizes the state again. E.g. a series of new locations while walking.</div>
<!-- EDIT26 SECTION "UDP versus TCP" [15195-15865] -->
<h2><a>Important: Use Multi-Threading</a></h2>
<h2>Important: Use Multi-Threading</h2>
<div>
<p>
<p><div><strong>You cannot modify the scenegraph directly from the network thread.</strong> A common example for such a modification is when you synchronize the player's position in the scene. You have to use Java Multithreading.
</div></p>
</p>
@ -531,19 +504,17 @@ For general advice, see the articles <object classid="java:org.netbeans.modules.
</div>
<!-- EDIT27 SECTION "Important: Use Multi-Threading" [15866-17012] -->
<h2><a>Troubleshooting</a></h2>
<h2>Troubleshooting</h2>
<div>
<p>
If you have set up a server in your home network, and the game clients cannot reach the server from the outside, it's time to learn about <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://portforward.com/"><paramname="text"value="<html><u>port forwarding</u></html>"><paramname="textColor"value="blue"></object>.
<h1><a>Creating JME3 User Interfaces with Nifty GUI</a></h1>
<h1>Creating JME3 User Interfaces with Nifty GUI</h1>
<div>
<p>
@ -7,12 +7,11 @@
</p>
<p>
You may want your players to press a button to save a game, you want a scrolling text field for highscores, a text label to display the score, drop-downs to select keymap preferences, or checkboxes to specify multi-media options. Usually you solve these tasks by using Swing controls. Although it is possible to embed a <ahref="/com/jme3/gde/docs/jme3/advanced/swing_canvas.html">jME3 canvas</a> in a Swing <acronymtitle="Graphical User Interface">GUI</acronym>, a 3D game typically runs full-screen, or in a window of its own.
You may want your players to press a button to save a game, you want a scrolling text field for highscores, a text label to display the score, drop-downs to select keymap preferences, or checkboxes to specify multi-media options. Usually you solve these tasks by using Swing controls. Although it is possible to embed a <ahref="/com/jme3/gde/docs/jme3/advanced/swing_canvas.html">jME3 canvas</a> in a Swing <abbrtitle="Graphical User Interface">GUI</abbr>, a 3D game typically runs full-screen, or in a window of its own.
</p>
<p>
This document introduces you to <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://nifty-gui.lessvoid.com/"><paramname="text"value="<html><u>Nifty GUI</u></html>"><paramname="textColor"value="blue"></object>, a Java library for building interactive graphical user interfaces (GUIs) for games or similar applications. Nifty <acronymtitle="Graphical User Interface">GUI</acronym> (the <code>de.lessvoid.nifty</code> package) is well integrated with jME3 through the <code>com.jme3.niftygui</code> package. You define the base <acronymtitle="Graphical User Interface">GUI</acronym> layout in <acronymtitle="Extensible Markup Language">XML</acronym>, and control it dynamically from your Java code. The necessary JAR libraries are included in your jME3 download, you do not need to install anything extra. (Just make sure they are on the classpath.)
This document introduces you to <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://nifty-gui.lessvoid.com/"><paramname="text"value="<html><u>Nifty GUI</u></html>"><paramname="textColor"value="blue"></object>, a Java library for building interactive graphical user interfaces (GUIs) for games or similar applications. Nifty <abbrtitle="Graphical User Interface">GUI</abbr> (the <code>de.lessvoid.nifty</code> package) is well integrated with jME3 through the <code>com.jme3.niftygui</code> package. You define the base <abbrtitle="Graphical User Interface">GUI</abbr> layout in XML, and control it dynamically from your Java code. The necessary JAR libraries are included in your jME3 download, you do not need to install anything extra. (Just make sure they are on the classpath.)
</p>
<ul>
<li><div><objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://vimeo.com/25637085"><paramname="text"value="<html><u>Video demo of Nifty GUI 1.3</u></html>"><paramname="textColor"value="blue"></object></div>
@ -21,12 +20,11 @@ This document introduces you to <object classid="java:org.netbeans.modules.javah
</div>
<!-- EDIT1 SECTION "Creating JME3 User Interfaces with Nifty GUI" [1-1159] -->
<h2><a>Tutorial Overview</a></h2>
<h2>Tutorial Overview</h2>
<div>
<p>
Learn to add a Nifty <acronymtitle="Graphical User Interface">GUI</acronym> to your jME3 game by going through this multi-part tutorial:
Learn to add a Nifty <abbrtitle="Graphical User Interface">GUI</abbr> to your jME3 game by going through this multi-part tutorial:
</p>
<ol>
<li><div><span><ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui.html">Understand the Nifty GUI Concepts</a></span> described on this page.</div>
@ -35,15 +33,15 @@ Learn to add a Nifty <acronym title="Graphical User Interface">GUI</acronym> to
</li>
<li><div> Lay out your graphical user interface:</div>
<ul>
<li><div><ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui_xml_layout.html">Lay out the GUI in XML</a>??? or ???</div>
<li><div><ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui_xml_layout.html">Lay out the GUI in XML</a>– or –</div>
</li>
<li><div><ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui_java_layout.html">Lay out the GUI in Java</a></div>
</li>
</ul>
</li>
<li><div> Integrate the <acronymtitle="Graphical User Interface">GUI</acronym> into the game:</div>
<li><div> Integrate the <abbrtitle="Graphical User Interface">GUI</abbr> into the game:</div>
<ul>
<li><div><ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui_overlay.html">Overlay the User Interface Over the Screen</a>??? or ???</div>
<li><div><ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui_overlay.html">Overlay the User Interface Over the Screen</a>– or –</div>
</li>
<li><div><ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui_projection.html">Project the User Interface Onto a Texture</a></div>
</li>
@ -55,20 +53,18 @@ Learn to add a Nifty <acronym title="Graphical User Interface">GUI</acronym> to
Now that you understand the concepts and know where to find more information, learn how to lay out a simple graphical user interface. Typically, you start doing this in <acronymtitle="Extensible Markup Language">XML</acronym>.
Now that you understand the concepts and know where to find more information, learn how to lay out a simple graphical user interface. Typically, you start doing this in XML.
</p>
<ul>
<li><div><ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui_xml_layout.html">Lay out the GUI in XML</a> (recommended)</div>
@ -182,22 +176,19 @@ Now that you understand the concepts and know where to find more information, le
</div>
<!-- EDIT7 SECTION "Next Steps" [4678-5117] -->
<h2><a>Nifty Logging (Nifty 1.3.1)</a></h2>
<h2>Nifty Logging (Nifty 1.3.1)</h2>
<div>
<p>
If you want to disable the nifty log lines, add this code after you created nifty:
<li><div><ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui_overlay.html">Nifty GUI Overlay</a> or <ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui_projection.html">Nifty GUI Projection</a></div>
</li>
<li><div><strong>Nifty <acronymtitle="Graphical User Interface">GUI</acronym> Java Interaction</strong></div>
<li><div><strong>Nifty <abbrtitle="Graphical User Interface">GUI</abbr> Java Interaction</strong></div>
</li>
</ol>
<p>
In the previous parts of the tutorial, you created a two-screen user interface. But it is still static, and when you click the buttons, nothing happens yet. The purpose of the <acronymtitle="Graphical User Interface">GUI</acronym> is to communicate with your Java classes: Your game needs to know what the users clicked, which settings they chose, which values they entered into a field, etc. Similarly, the user needs to know what the currently game state is (score, health, etc).
In the previous parts of the tutorial, you created a two-screen user interface. But it is still static, and when you click the buttons, nothing happens yet. The purpose of the <abbrtitle="Graphical User Interface">GUI</abbr> is to communicate with your Java classes: Your game needs to know what the users clicked, which settings they chose, which values they entered into a field, etc. Similarly, the user needs to know what the currently game state is (score, health, etc).
</p>
</div>
<!-- EDIT1 SECTION "Interacting with the GUI from Java" [1-791] -->
<h2><a>Connect GUI to Java Controller</a></h2>
<h2>Connect GUI to Java Controller</h2>
<div>
<p>
To let a Nifty screen communicate with the Java application, you register a <code>ScreenController</code> to every NiftyGUI screen. You create a ScreenController by creating a Java class that implements the <code>de.lessvoid.nifty.screen.ScreenController</code> interface and its abstract methods.
</p>
<p>
Create an AppState <strong>MyStartScreen</strong>.java file in your package. ( Rightclick on your package → New → Other… → JME3 Classes → New AppState)
</p>
<p>
<strong>Pro Tip:</strong> Since you are writing a jME3 application, you can additionally make the ScreenController class extend the <ahref="/com/jme3/gde/docs/jme3/advanced/application_states.html">AbstractAppState</a> class! This gives the ScreenController access to the application object and to the update loop!
</p>
<pre>package tutorial;
<p>
Now add <strong>implements ScreenController</strong> to <em>public class MyStartScreen extends AbstractAppState{</em> and add <strong>import de.lessvoid.nifty.screen.ScreenController;</strong>
</p>
<p>
Continue with adding:
</p>
<pre>import de.lessvoid.nifty.screen.Screen;
...
public void bind(Nifty nifty, Screen screen){
throw new UnsupportedOperationException("Not supported yet.");
}
public void onStartScreen(){
throw new UnsupportedOperationException("Not supported yet.");
}
public void onEndScreen(){
throw new UnsupportedOperationException("Not supported yet.");
}</pre>
<pre><span>/*
* To change this template, choose Tools | Templates
public class MyStartScreen extends AbstractAppState implements ScreenController {
private Nifty nifty;
private Screen screen;
private SimpleApplication app;
@Override
public void initialize(AppStateManager stateManager, Application app){
super.initialize(stateManager, app);
//TODO: initialize your AppState, e.g. attach spatials to rootNode
//this is called on the OpenGL thread after the AppState has been attached
}
/** custom methods */
@Override
public void update(float tpf){
//TODO: implement behavior during runtime
}
public MyStartScreen(String data){
/** Your custom constructor, can accept arguments */
}
@Override
public void cleanup(){
super.cleanup();
//TODO: clean up what you initialized in the initialize method,
//e.g. remove all spatials from rootNode
//this is called on the OpenGL thread after the AppState has been detached
}
/** Nifty GUI ScreenControl methods */
public void bind(Nifty nifty, Screen screen){
throw new UnsupportedOperationException("Not supported yet.");
}
public void bind(Nifty nifty, Screen screen){
this.nifty = nifty;
this.screen = screen;
}
public void onStartScreen(){}
public void onEndScreen(){}
/** jME3 AppState methods */
@Override
public void initialize(AppStateManager stateManager, Application app){
super.initialize(stateManager, app);
this.app=(SimpleApplication)app;
}
@Override
public void update(float tpf){
/** jME update loop! */
}
public void onStartScreen(){
throw new UnsupportedOperationException("Not supported yet.");
}
public void onEndScreen(){
throw new UnsupportedOperationException("Not supported yet.");
}
}</pre>
<p>
The name and package of your custom ScreenController class (here <code>tutorial.MyStartScreen</code>) goes into the controller parameter of the respective <acronymtitle="Extensible Markup Language">XML</acronym> screen it belongs to. For example:
The name and package of your custom ScreenController class (here <code>mygame.MyStartScreen</code>) goes into the controller parameter of the respective XML screen it belongs to. For example:
Now the Java class <code>MyStartScreen</code> and this <acronymtitle="Graphical User Interface">GUI</acronym> screen (<code>start</code>) are connected. For this example you can also connect the <code>hud</code> screen to MyStartScreen.
Now the Java class <code>MyStartScreen</code> and this <abbrtitle="Graphical User Interface">GUI</abbr> screen (<code>start</code>) are connected. For this example you can also connect the <code>hud</code> screen to MyStartScreen.
</p>
</div>
<!-- EDIT2 SECTION "Connect GUI to Java Controller" [792-3175] -->
<h2><a>Make GUI and Java Interact</a></h2>
<!-- EDIT2 SECTION "Connect GUI to Java Controller" [792-4282] -->
<h2>Make GUI and Java Interact</h2>
<div>
<p>
In most cases, you will want to pass game data in and out of the ScreenController. Note that you can pass any custom arguments from your Java class into your ScreenController constructor (<code>public MyStartScreen(GameData data) {}</code>).
</p>
<p>
Use any combination of the three following approaches to make Java classes interact with the <acronymtitle="Graphical User Interface">GUI</acronym>.
Use any combination of the three following approaches to make Java classes interact with the <abbrtitle="Graphical User Interface">GUI</abbr>.
</p>
</div>
<!-- EDIT3 SECTION "Make GUI and Java Interact" [3176-3548] -->
<h3><a>GUI Calls a Void Java Method</a></h3>
<!-- EDIT3 SECTION "Make GUI and Java Interact" [4283-4655] -->
<h3>GUI Calls a Void Java Method</h3>
<div>
<p>
This is how you respond to an <acronymtitle="Graphical User Interface">GUI</acronym> interaction such as clicks in <acronymtitle="Extensible Markup Language">XML</acronym> GUIs:
This is how you respond to an <abbrtitle="Graphical User Interface">GUI</abbr> interaction such as clicks in XML GUIs:
</p>
<ol>
<li><div> Add <code>visibleToMouse="true"</code> to the parent element!</div>
<li><div> Add <code>visibleToMouse=“true”</code> to the parent element!</div>
</li>
<li><div> Embed the <code><interact /></code> element into the parent element. </div>
</li>
<li><div> Specify the Java methods that you want to call when the users performs certain actions, such as clicking. <br/>
In the following example, we call the <code>startGame()</code> method when the player clicks the Start button, and <code>quitGame()</code> when the player clicks the Quit button.
@ -206,7 +227,7 @@ Back in the MyStartScreen class, you specify what the <code>startGame()</code> a
}</pre>
<p>
The startGame() example simply switches the <acronymtitle="Graphical User Interface">GUI</acronym> to the <code>hud</code> screen when the user clicks Start. Of course, in a real game, you would perform more steps here: Load the game level, switch to in-game input and navigation handling, set a custom <code>running</code> boolean to true, attach custom in-game AppStates ??? and lots more.
The startGame() example simply switches the <abbrtitle="Graphical User Interface">GUI</abbr> to the <code>hud</code> screen when the user clicks Start. Of course, in a real game, you would perform more steps here: Load the game level, switch to in-game input and navigation handling, set a custom <code>running</code> boolean to true, attach custom in-game AppStates – and lots more.
</p>
<p>
@ -214,13 +235,12 @@ The quitGame() example shows that you have access to the application <code>app</
When the Nifty <acronymtitle="Graphical User Interface">GUI</acronym> is initialized, you can get data from Java. In this example, the Java class <code>getPlayerName()</code> in <code>MyStartScreen</code> defines the Text that is displayed in the textfield before the words <code>'s Cool Game</code>.
When the Nifty <abbrtitle="Graphical User Interface">GUI</abbr> is initialized, you can get data from Java. In this example, the Java class <code>getPlayerName()</code> in <code>MyStartScreen</code> defines the Text that is displayed in the textfield before the words <code>'s Cool Game</code>.
</p>
<p>
@ -249,17 +269,16 @@ Or the same in a Java syntax, respectively:
}});</pre>
<p>
You can use this for Strings and numeric values (e.g. when you read settings from a file, you display the results in the <acronymtitle="Graphical User Interface">GUI</acronym>) and also for methods with side effects.
You can use this for Strings and numeric values (e.g. when you read settings from a file, you display the results in the <abbrtitle="Graphical User Interface">GUI</abbr>) and also for methods with side effects.
</p>
</div>
<!-- EDIT5 SECTION "GUI Gets Return Value from Java Method" [6726-7913] -->
<h3><a>Java Modifies Nifty Elements and Events</a></h3>
<!-- EDIT5 SECTION "GUI Gets Return Value from Java Method" [7833-9020] -->
<h3>Java Modifies Nifty Elements and Events</h3>
<div>
<p>
You can also alter the appearance and functions of your nifty elements from Java. Make certain that the element that you want to alter has its <code>id="name"</code> attribute set, so you can identy and address it.
You can also alter the appearance and functions of your nifty elements from Java. Make certain that the element that you want to alter has its <code>id=“name”</code> attribute set, so you can identy and address it.
</p>
<p>
@ -273,7 +292,7 @@ Element niftyElement = nifty.getCurrentScreen().findElementByName(&q
<!-- EDIT6 SECTION "Java Modifies Nifty Elements and Events" [7914-9330] -->
<h2><a>Next Steps</a></h2>
<!-- EDIT6 SECTION "Java Modifies Nifty Elements and Events" [9021-10437] -->
<h2>Next Steps</h2>
<div>
<p>
You're done with the basic Nifty <acronymtitle="Graphical User Interface">GUI</acronym> for jME3 tutorial. You can proceed to advanced topics and learn how add controls and effects:
You're done with the basic Nifty <abbrtitle="Graphical User Interface">GUI</abbr> for jME3 tutorial. You can proceed to advanced topics and learn how add controls and effects:
@ -307,15 +324,11 @@ You're done with the basic Nifty <acronym title="Graphical User Interface">
<li><div><objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://sourceforge.net/projects/nifty-gui/files/nifty-gui/nifty-gui-the-manual-v1.0.pdf/download"><paramname="text"value="<html><u>Nifty GUI - the Manual</u></html>"><paramname="textColor"value="blue"></object></div>
<li><div><ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui_best_practices.html">Nifty GUI Best Practices</a></div>
</li>
<li><div><ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui_xml_layout.html">Nifty GUI XML Layout</a> or <strong>Nifty <acronymtitle="Graphical User Interface">GUI</acronym> Java Layout</strong></div>
<li><div><ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui_xml_layout.html">Nifty GUI XML Layout</a> or <strong>Nifty <abbrtitle="Graphical User Interface">GUI</abbr> Java Layout</strong></div>
</li>
<li><div><ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui_overlay.html">Nifty GUI Overlay</a> or <ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui_projection.html">Nifty GUI Projection</a></div>
</li>
@ -15,17 +15,15 @@
</ol>
<p>
<strong>Work in progress</strong> You can "draw" the <acronymtitle="Graphical User Interface">GUI</acronym> to the screen by writing Java code ??? alternatively to using <acronymtitle="Extensible Markup Language">XML</acronym>. Typically you lay out the static base <acronymtitle="Graphical User Interface">GUI</acronym> in <acronymtitle="Extensible Markup Language">XML</acronym>, and use Java commands if you need to change the <acronymtitle="Graphical User Interface">GUI</acronym> dynamically at runtime. In theory, you can also lay out the whole <acronymtitle="Graphical User Interface">GUI</acronym> in Java (but we don't cover that here).
<strong>Work in progress</strong> You can “draw” the <abbrtitle="Graphical User Interface">GUI</abbr> to the screen by writing Java code – alternatively to using XML. Typically you lay out the static base <abbrtitle="Graphical User Interface">GUI</abbr> in XML, and use Java commands if you need to change the <abbrtitle="Graphical User Interface">GUI</abbr> dynamically at runtime. In theory, you can also lay out the whole <abbrtitle="Graphical User Interface">GUI</abbr> in Java (but we don't cover that here).
</p>
</div>
<!-- EDIT1 SECTION "Laying Out the GUI in Java" [1-690] -->
The full demo ZIP is based on <code>de.lessvoid.nifty.examples.controls.ControlsDemo.java</code>.</div>
<ol>
<li><div> The demo is a SimpleApplication-based game (use e.g. the BasicGame template in the jMonkeyEngine <acronymtitle="Software Development Kit">SDK</acronym>).</div>
<li><div> The demo is a SimpleApplication-based game (use e.g. the BasicGame template in the jMonkeyEngine SDK).</div>
</li>
<li><div> Copy images and sound files into your project's <code>assets/Interface/</code> directory. (In this example, I copied them from <code>nifty-default-controls-examples/trunk/src/main/resources/</code> to <code>assets/Interface/</code>).</div>
</li>
<li><div> Make sure to use paths relative to your project's <code>assets/</code> directory.</div>
<ul>
<li><div> E.g. for .fnt/.png/.jpg files use <code>filename("Interface/yang.png");</code> ( not <code>filename("yang.png");</code>).</div>
<li><div> E.g. for .fnt/.png/.jpg files use <code>filename(“Interface/yang.png”);</code> ( not <code>filename(“yang.png”);</code>).</div>
</li>
<li><div> E.g. for .wav/.ogg files use <code>filename("Interface/sounds/gong.wav");</code> (not <code>filename("sounds/gong.wav");</code>).</div>
<li><div> E.g. for .wav/.ogg files use <code>filename(“Interface/sounds/gong.wav”);</code> (not <code>filename(“sounds/gong.wav”);</code>).</div>
</li>
</ul>
</li>
@ -52,8 +50,7 @@ The full demo ZIP is based on <code>de.lessvoid.nifty.examples.controls.Controls
</ul>
<p>
Just so you get a quick picture what Nifty <acronymtitle="Graphical User Interface">GUI</acronym>'s Java Syntax looks like, here is the most basic example. It creates a screen with a layer and a panel that contains a button.
Just so you get a quick picture what Nifty <abbrtitle="Graphical User Interface">GUI</abbr>'s Java Syntax looks like, here is the most basic example. It creates a screen with a layer and a panel that contains a button.
</p>
<pre>package mygame;
@ -122,16 +119,15 @@ public class Main extends SimpleApplication {
In this tutorial, you recreate the same screen as in the Nifty <acronymtitle="Graphical User Interface">GUI</acronym><acronymtitle="Extensible Markup Language">XML</acronym> example.
In this tutorial, you recreate the same screen as in the Nifty <abbrtitle="Graphical User Interface">GUI</abbr> XML example.
</p>
<p>
@ -140,11 +136,10 @@ Create an Screen.Java file in the <code>assets/Interfaces/</code> directory of y
</div>
<!-- EDIT3 SECTION "Implement Your GUI Layout" [3959-4495] -->
<h3><a>Make Screens</a></h3>
<h3>Make Screens</h3>
<div>
<p>
The following minimal Java file contains a start screen and a HUD screen. (Neither has been defined yet.)
</p>
<pre>nifty.addScreen("start", new ScreenBuilder("start"){{
@ -158,16 +153,15 @@ nifty.addScreen("hud", new ScreenBuilder("hud")&
}}.build(nifty));</pre>
<p>
Every Nifty <acronymtitle="Graphical User Interface">GUI</acronym> must have a start screen. The others (in this example, the HUD screen) are optional.
Every Nifty <abbrtitle="Graphical User Interface">GUI</abbr> must have a start screen. The others (in this example, the HUD screen) are optional.
</p>
</div>
<!-- EDIT4 SECTION "Make Screens" [4496-5030] -->
<h3><a>Make Layers</a></h3>
<h3>Make Layers</h3>
<div>
<p>
The following Java code shows how we add layers to the start screen and HUD screen:
</p>
<pre>nifty.addScreen("start", new ScreenBuilder("start"){{
@ -206,11 +200,10 @@ In a layer, you can now add panels and arrange them. Panels are containers that
</div>
<!-- EDIT5 SECTION "Make Layers" [5031-5968] -->
<h3><a>Make Panels</a></h3>
<h3>Make Panels</h3>
<div>
<p>
A panel is the inner-most container (that will contain the actual content: text, images, or controls). You place panels inside layers. The following panels go into in the <code>start</code> screen:
</p>
<pre> nifty.addScreen("start", new ScreenBuilder("start"){{
@ -326,7 +319,7 @@ The following panels go into in the <code>hud</code> screen:
}}.build(nifty));</pre>
<p>
Try the sample. Remember to activate a screen using <code>nifty.gotoScreen("start");</code> or <code>hud</code> respectively.
Try the sample. Remember to activate a screen using <code>nifty.gotoScreen(“start”);</code> or <code>hud</code> respectively.
The result should look as follows:
</p>
@ -336,23 +329,20 @@ The result should look as follows:
</div>
<!-- EDIT6 SECTION "Make Panels" [5969-9926] -->
<h2><a>Adding Content to Panels</a></h2>
<h2>Adding Content to Panels</h2>
<div>
<p>
See also <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Layout_Introduction"><paramname="text"value="<html><u>Layout Introduction</u></html>"><paramname="textColor"value="blue"></object> on the Nifty <acronymtitle="Graphical User Interface">GUI</acronym> site.
See also <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Layout_Introduction"><paramname="text"value="<html><u>Layout Introduction</u></html>"><paramname="textColor"value="blue"></object> on the Nifty <abbrtitle="Graphical User Interface">GUI</abbr> site.
</p>
</div>
<!-- EDIT7 SECTION "Adding Content to Panels" [9927-10105] -->
<h3><a>Add Images</a></h3>
<h3>Add Images</h3>
<div>
<p>
The start-background.png image is a fullscreen background picture. In the <code>start</code> screen, add the following image element:
</p>
<pre> nifty.addScreen("start", new ScreenBuilder("start"){{
@ -441,7 +426,7 @@ The game title is a typical example of static text. In the <code>start</code> sc
}});</pre>
<p>
For longer pieces of static text, such as an introduction, you can use wrap="true". Add the following text element to the <code>Start screen</code>:
For longer pieces of static text, such as an introduction, you can use wrap=“true”. Add the following text element to the <code>Start screen</code>:
@ -462,16 +447,15 @@ For longer pieces of static text, such as an introduction, you can use wrap=&quo
}});</pre>
<p>
The font used is jME3's default font "Interface/Fonts/Default.fnt" which is included in the jMonkeyEngine.JAR. You can add your own fonts to your own <code>assets/Interface</code> directory.
The font used is jME3's default font “Interface/Fonts/Default.fnt” which is included in the jMonkeyEngine.JAR. You can add your own fonts to your own <code>assets/Interface</code> directory.
@ -479,11 +463,10 @@ Before you can use any control, you must load a Control Definition first. Add th
</div>
<h4><a>Label Control</a></h4>
<h4>Label Control</h4>
<div>
<p>
Use label controls for text that you want to edit dynamically from Java. One example for this is the score display.
In the <code>hud</code> screen's <code>foreground</code> layer, add the following text element:
</p>
@ -506,12 +489,11 @@ Note that the width and height do not scale the bitmap font, but make indirectly
</div>
<h4><a>Button Control</a></h4>
<h4>Button Control</h4>
<div>
<p>
Our <acronymtitle="Graphical User Interface">GUI</acronym> plan asks for two buttons on the start screen. You add the Start and Quit buttons to the bottom panel of the <code>start</code> screen using the <code><control></code> element:
Our <abbrtitle="Graphical User Interface">GUI</abbr> plan asks for two buttons on the start screen. You add the Start and Quit buttons to the bottom panel of the <code>start</code> screen using the <code><control></code> element:
@ -548,27 +530,25 @@ Our <acronym title="Graphical User Interface">GUI</acronym> plan asks for two bu
}});</pre>
<p>
Note that these controls don't do anything yet ??? we'll get to that soon.
Note that these controls don't do anything yet – we'll get to that soon.
</p>
</div>
<h4><a>Other Controls</a></h4>
<h4>Other Controls</h4>
<div>
<p>
Nifty additionally offers many customizable controls such as check boxes, text fields, menus, chats, tabs, ??? See also <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Elements"><paramname="text"value="<html><u>Elements</u></html>"><paramname="textColor"value="blue"></object> on the Nifty <acronymtitle="Graphical User Interface">GUI</acronym> site.
Nifty additionally offers many customizable controls such as check boxes, text fields, menus, chats, tabs, … See also <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Elements"><paramname="text"value="<html><u>Elements</u></html>"><paramname="textColor"value="blue"></object> on the Nifty <abbrtitle="Graphical User Interface">GUI</abbr> site.
When you preview this code in the jMonkeyEngine <acronymtitle="Software Development Kit">SDK</acronym>, our tutorial demo should looks as follows: A start screen with two buttons, and a game screen with a simple HUD frame and a blue cube (which stands for any jME3 game content).
When you preview this code in the jMonkeyEngine SDK, our tutorial demo should looks as follows: A start screen with two buttons, and a game screen with a simple HUD frame and a blue cube (which stands for any jME3 game content).
</p>
<p>
@ -581,25 +561,26 @@ When you preview this code in the jMonkeyEngine <acronym title="Software Develop
Integrate the <acronymtitle="Graphical User Interface">GUI</acronym> into the game. Typically, you will overlay the <acronymtitle="Graphical User Interface">GUI</acronym>.
Integrate the <abbrtitle="Graphical User Interface">GUI</abbr> into the game. Typically, you will overlay the <abbrtitle="Graphical User Interface">GUI</abbr>.
<li><div><ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui_xml_layout.html">Nifty GUI XML Layout</a> or <ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui_java_layout.html">Nifty GUI Java Layout</a></div>
</li>
<li><div><strong>Nifty <acronymtitle="Graphical User Interface">GUI</acronym> Overlay</strong> or <ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui_projection.html">Nifty GUI Projection</a></div>
<li><div><strong>Nifty <abbrtitle="Graphical User Interface">GUI</abbr> Overlay</strong> or <ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui_projection.html">Nifty GUI Projection</a></div>
</li>
<li><div><ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui_java_interaction.html">Interact with the GUI from Java</a></div>
Typically, you define a key (for example escape) that switches the <acronymtitle="Graphical User Interface">GUI</acronym> on and off. The <acronymtitle="Graphical User Interface">GUI</acronym> can be a StartScreen, OptionsScreen, CharacterCreationScreen, etc. While the <acronymtitle="Graphical User Interface">GUI</acronym> is up, you pause the running game, and then overlay the <acronymtitle="Graphical User Interface">GUI</acronym>. You also must switch to a different set of user inputs while the game is paused, so the player can use the mouse pointer and keyboard to interact with the <acronymtitle="Graphical User Interface">GUI</acronym>.
Typically, you define a key (for example escape) that switches the <abbrtitle="Graphical User Interface">GUI</abbr> on and off. The <abbrtitle="Graphical User Interface">GUI</abbr> can be a StartScreen, OptionsScreen, CharacterCreationScreen, etc. While the <abbrtitle="Graphical User Interface">GUI</abbr> is up, you pause the running game, and then overlay the <abbrtitle="Graphical User Interface">GUI</abbr>. You also must switch to a different set of user inputs while the game is paused, so the player can use the mouse pointer and keyboard to interact with the <abbrtitle="Graphical User Interface">GUI</abbr>.
</p>
<p>
You can also <ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui_projection.html">project</a> the <acronymtitle="Graphical User Interface">GUI</acronym> as a texture onto a mesh texture (but then you cannot click to select).
You can also <ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui_projection.html">project</a> the <abbrtitle="Graphical User Interface">GUI</abbr> as a texture onto a mesh texture (but then you cannot click to select).
On this page, we look at the overlay variant, which is more commonly used in games.
@ -39,12 +38,11 @@ On this page, we look at the overlay variant, which is more commonly used in gam
</div>
<!-- EDIT2 SECTION "Sample Code" [1044-1206] -->
<h2><a>Overlaying the User Interface Over the Screen</a></h2>
<h2>Overlaying the User Interface Over the Screen</h2>
<div>
<p>
This code shows you how to overlay anything on the screen with the <acronymtitle="Graphical User Interface">GUI</acronym>. This is the most common usecase.
This code shows you how to overlay anything on the screen with the <abbrtitle="Graphical User Interface">GUI</abbr>. This is the most common usecase.
</p>
<pre>NiftyJmeDisplay niftyDisplay = new NiftyJmeDisplay(
Currently you do not have a ScreenController ??? we will create one in the next exercise. As soon as you have a screen controller, you will use the commented variant of the <acronymtitle="Extensible Markup Language">XML</acronym> loading method:
Currently you do not have a ScreenController – we will create one in the next exercise. As soon as you have a screen controller, you will use the commented variant of the XML loading method:
</p>
<pre>nifty.fromXml("Interface/helloworld.xml", "start", new MySettingsScreen());</pre>
<p>
The <code>MySettingsScreen</code> class is a custom de.lessvoid.nifty.screen.ScreenController in which you will implement your <acronymtitle="Graphical User Interface">GUI</acronym> behaviour.
The <code>MySettingsScreen</code> class is a custom de.lessvoid.nifty.screen.ScreenController in which you will implement your <abbrtitle="Graphical User Interface">GUI</abbr> behaviour.
</p>
<p>
If you have many screens or you want to keep them organized in separate files there is a method available that will just load an additional XML file. The content of the files are
simply added to whatever XML data has been loaded before.
<!-- EDIT3 SECTION "Overlaying the User Interface Over the Screen" [1207-2372] -->
<h2><a>Next Steps</a></h2>
<!-- EDIT3 SECTION "Overlaying the User Interface Over the Screen" [1207-2675] -->
<h2>Next Steps</h2>
<div>
<p>
Now that you have layed out and integrated the <acronymtitle="Graphical User Interface">GUI</acronym> in your app, you want to respond to user input and display the current game. Time to create a ScreenController!
Now that you have layed out and integrated the <abbrtitle="Graphical User Interface">GUI</abbr> in your app, you want to respond to user input and display the current game. Time to create a ScreenController!
</p>
<ul>
<li><div><ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui_java_interaction.html">Interact with the GUI from Java</a></div>
Even though you create and populate the popup menu in Java, you still need a "placeholder" in your <acronymtitle="Extensible Markup Language">XML</acronym> file.
Even though you create and populate the popup menu in Java, you still need a “placeholder” in your XML file.
The popup element needs to be placed <em>outside</em> of any screen!
new menuItem("menuItemid", "blah blah")); // menuItem is a custom class
@ -60,7 +58,7 @@ public void showMenu() { // the method to trigger the menu
private class menuItem {
public String id;
public String name;
public menuItem(String id, String name){
public menuItem(String name){
this.id= id;
this.name = name;
}
@ -75,7 +73,6 @@ private class menuItem {
</ul>
<p>
To handle menu item events (i.e. calling a method when you click on a menu item), you register (subscribe) a EventTopicSubscriber<MenuItemActivatedEvent> class implementation to a nifty screen and element.
</p>
<pre> private class MenuItemActivatedEventSubscriber
@ -91,4 +88,4 @@ To handle menu item events (i.e. calling a method when you click on a menu item)
<li><div><ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui_xml_layout.html">Nifty GUI XML Layout</a> or <ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui_java_layout.html">Nifty GUI Java Layout</a></div>
</li>
<li><div><ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui_overlay.html">Nifty GUI Overlay</a> or <strong>Nifty <acronymtitle="Graphical User Interface">GUI</acronym> Projection</strong></div>
<li><div><ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui_overlay.html">Nifty GUI Overlay</a> or <strong>Nifty <abbrtitle="Graphical User Interface">GUI</abbr> Projection</strong></div>
</li>
<li><div><ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui_java_interaction.html">Interact with the GUI from Java</a></div>
Typically you define a key (for example escape) to switch the <acronymtitle="Graphical User Interface">GUI</acronym> on and off. Then you <ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui_overlay.html">overlay</a> the running game with the <acronymtitle="Graphical User Interface">GUI</acronym> (you will most likely pause the game then).
Typically you define a key (for example escape) to switch the <abbrtitle="Graphical User Interface">GUI</abbr> on and off. Then you <ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui_overlay.html">overlay</a> the running game with the <abbrtitle="Graphical User Interface">GUI</abbr> (you will most likely pause the game then).
</p>
<p>
Alternatively, you can also project the <acronymtitle="Graphical User Interface">GUI</acronym> as a texture onto a mesh textures inside the game. Allthough this looks cool and "immersive", this approach is rarely used since it is difficult to record clicks this way. You can only interact with this projected <acronymtitle="Graphical User Interface">GUI</acronym> by keyboard, or programmatically. You can select input fields using the arrow keys, and trigger actions using the return key.
Alternatively, you can also project the <abbrtitle="Graphical User Interface">GUI</abbr> as a texture onto a mesh textures inside the game. Allthough this looks cool and “immersive”, this approach is rarely used since it is difficult to record clicks this way. You can only interact with this projected <abbrtitle="Graphical User Interface">GUI</abbr> by keyboard, or programmatically. You can select input fields using the arrow keys, and trigger actions using the return key.
</p>
<p>
This <acronymtitle="Graphical User Interface">GUI</acronym> projection variant is less commonly used than the <acronymtitle="Graphical User Interface">GUI</acronym> overlay variant. Usecases for <acronymtitle="Graphical User Interface">GUI</acronym> projection are, for example, a player avatar using an in-game computer screen.
This <abbrtitle="Graphical User Interface">GUI</abbr> projection variant is less commonly used than the <abbrtitle="Graphical User Interface">GUI</abbr> overlay variant. Usecases for <abbrtitle="Graphical User Interface">GUI</abbr> projection are, for example, a player avatar using an in-game computer screen.
@ -42,12 +41,11 @@ This <acronym title="Graphical User Interface">GUI</acronym> projection variant
</div>
<!-- EDIT2 SECTION "Sample Code" [1193-1360] -->
<h2><a>Projecting the User Interface Onto a Texture</a></h2>
<h2>Projecting the User Interface Onto a Texture</h2>
<div>
<p>
You can project the Nifty <acronymtitle="Graphical User Interface">GUI</acronym> onto a texture, load the texture into a material, and assign it to a Geometry (Quads or Boxes are best).
You can project the Nifty <abbrtitle="Graphical User Interface">GUI</abbr> onto a texture, load the texture into a material, and assign it to a Geometry (Quads or Boxes are best).
</p>
<pre>/** Create a special viewport for the Nifty GUI */
ViewPort niftyView = renderManager.createPreView("NiftyView", new Camera(1024, 768));
Geometry geom = new Geometry("Box", b);
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mat.setTexture("m_ColorMap", niftytex); /** Here comes the texture! */
@ -78,34 +76,30 @@ geom.setMaterial(mat);
rootNode.attachChild(geom);</pre>
<p>
The MySettingsScreen class is a custom de.lessvoid.nifty.screen.ScreenController in which you implement your <acronymtitle="Graphical User Interface">GUI</acronym> behaviour. The variable <code>data</code> contains an object that you use to exchange state info with the game. See <ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui_java_interaction.html">Nifty GUI Java Interaction</a> for details on how to create this class.
The MySettingsScreen class is a custom de.lessvoid.nifty.screen.ScreenController in which you implement your <abbrtitle="Graphical User Interface">GUI</abbr> behaviour. The variable <code>data</code> contains an object that you use to exchange state info with the game. See <ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui_java_interaction.html">Nifty GUI Java Interaction</a> for details on how to create this class.
</p>
<p>
Run the code sample. You select buttons on this <acronymtitle="Graphical User Interface">GUI</acronym> with the arrow keys and then press return. Note that clicking on the texture will not work!
Run the code sample. You select buttons on this <abbrtitle="Graphical User Interface">GUI</abbr> with the arrow keys and then press return. Note that clicking on the texture will not work!
</p>
</div>
<!-- EDIT3 SECTION "Projecting the User Interface Onto a Texture" [1361-3239] -->
<h2><a>Next Steps</a></h2>
<h2>Next Steps</h2>
<div>
<p>
Now that you have layed out and integrated the <acronymtitle="Graphical User Interface">GUI</acronym> in your app, you want to respond to user input and display the current game.
Now that you have layed out and integrated the <abbrtitle="Graphical User Interface">GUI</abbr> in your app, you want to respond to user input and display the current game.
</p>
<ul>
<li><div><ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui_java_interaction.html">Interact with the GUI from Java</a></div>
This document contains typical NiftyGUI usecase scenarios, such as adding effects, game states, and creating typical game screens.
</p>
<p>
Requirements: These tips assume that you have read and understood the <ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui.html">Creating JME3 User Interfaces with Nifty GUI</a> tutorial, and have already laid out a basic <acronymtitle="Graphical User Interface">GUI</acronym> that interacts with your JME3 application. Here you learn how you integrate the <acronymtitle="Graphical User Interface">GUI</acronym> better, and add effects and advanced controls.
Requirements: These tips assume that you have read and understood the <ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui.html">Creating JME3 User Interfaces with Nifty GUI</a> tutorial, and have already laid out a basic <abbrtitle="Graphical User Interface">GUI</abbr> that interacts with your JME3 application. Here you learn how you integrate the <abbrtitle="Graphical User Interface">GUI</abbr> better, and add effects and advanced controls.
In a JME game, you typically have three game states:
</p>
<ol>
@ -30,7 +28,6 @@ In a JME game, you typically have three game states:
</ol>
<p>
(Aside: Additionally, the Stopped state often contains a LoadScreen, LogonScreen, OptionsScreen, CharacterCreationScreen, HighScoreScreen, CreditsScreen, etc. Some games let you access the OptionsScreen in the Paused state as well. The Running state can also contain an InventoryScreen, ItemShopScreen, StatsScreen, SkillScreen, etc.)
</p>
@ -42,22 +39,20 @@ In JME, game states are implemented as custom <a href="/com/jme3/gde/docs/jme3/a
When the player switches between game states, you detach one set of AppStates, and attach another. For example, when the player pauses the running game, you use a boolean switch to pause the game loop and deactivate the game inputs (shooting, navigation). The screen is overlayed with a PausedScreen, which contains a visible mouse pointer and a Continue button. When the player clicks Continue, the mouse pointer is deactivated, the in-game input and navigational mappings are activated, and the game loop continues.
</p>
</div>
<!-- EDIT2 SECTION "Switch Game States" [507-2043] -->
<h2><a>Get Access to Application and Update Loop</a></h2>
<h2>Get Access to Application and Update Loop</h2>
<div>
<p>
Since you are writing a jME3 application, you can additionally make any ScreenController class extend the <ahref="/com/jme3/gde/docs/jme3/advanced/application_states.html">AbstractAppState</a> class.
This gives the ScreenController access to the application object and to the update loop!
</p>
@ -81,6 +76,11 @@ public StartScreenState(SimpleApplication app){
@Override
public void initialize(AppStateManager stateManager, Application app){
public void stateDetached(AppStateManager stateManager){
public void cleanup(){
rootNode.detachChild(localRootNode);
guiNode.detachChild(localGuiNode);
super.cleanup();
}
}</pre>
<p>
<p><div>It is not sufficient to just inherit from AbstractAppState. You need to instantiate your controller class, register it with app's stateManager and then pass it to nifty. See code sample below.
</div></p>
</p>
@ -119,13 +113,15 @@ public StartScreenState(SimpleApplication app){
}</pre>
</div>
<!-- EDIT3 SECTION "Get Access to Application and Update Loop" [2044-4243] -->
<h2><a>Know Your Variables</a></h2>
<!-- EDIT3 SECTION "Get Access to Application and Update Loop" [2044-4170] -->
<h2>Know Your Variables</h2>
<div>
<div><table>
<thead>
<tr>
<th>Variable</th><th>Description</th>
</tr>
</thead>
<tr>
<td>${CALL.myMethod()} </td><td> Calls a method in the current ScreenController and gets the method's return String. The method can also be void and have a side effect, e.g. play a sound etc.</td>
</tr>
@ -133,25 +129,23 @@ public StartScreenState(SimpleApplication app){
<td>${ENV.HOME}</td><td> Returns the path to user's home directory.</td>
</tr>
<tr>
<td>${ENV.key} </td><td> Looks up <code>key</code> in the environment variables. Use it like Java's System.getEnv("key").</td>
<td>${ENV.key} </td><td> Looks up <code>key</code> in the environment variables. Use it like Java's System.getEnv(“key”).</td>
</tr>
<tr>
<td>${PROP.key}</td><td> looks up <code>key</code> in the Nifty properties. Use Nifty.setGlobalproperties(properties) and Nifty.getGlobalproperties("key"). Or SystemGetProperties(key);</td>
<td>${PROP.key}</td><td> looks up <code>key</code> in the Nifty properties. Use Nifty.setGlobalproperties(properties) and Nifty.getGlobalproperties(“key”). Or SystemGetProperties(key);</td>
</tr>
</table></div>
<!-- EDIT5 TABLE [4276-4807] -->
<!-- EDIT5 TABLE [4203-4734] -->
<p>
See also: <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=MarkUp"><paramname="text"value="<html><u>http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=MarkUp</u></html>"><paramname="textColor"value="blue"></object>
</p>
</div>
<!-- EDIT4 SECTION "Know Your Variables" [4244-4890] -->
<h2><a>Use ScreenControllers for Mutally Exclusive Functionality</a></h2>
<!-- EDIT4 SECTION "Know Your Variables" [4171-4817] -->
<h2>Use ScreenControllers for Mutally Exclusive Functionality</h2>
<div>
<p>
Technically you are free to create one ScreenController class for each screen, or reuse the same ScreenController for all or some of them. In the end it may be best to create individual ScreenControllers for functionality that is mutually exclusive.
</p>
@ -166,32 +160,29 @@ For example, create a <code>MyHudScreen.java</code> for the <code>hud</code> scr
Playing sounds using Nifty is also possible with a <code>playSound</code> effect as trigger. Remember to first register the sound that you want to play:
After a mouse click, you may want to record the 2D clickLoc and send this info to your Java application. Typical ScreenController methods however only have a String argument. You'd have to convert the String to ints.
</p>
<p>
To pass the clickLoc as two ints, you can use the special <code>(int x, int y)</code> syntax in the ScreenController:
</p>
<pre> public void clicked(int x, int y){
// here you can use the x and y of the clickLoc
}</pre>
<p>
In the Nifty <acronymtitle="Graphical User Interface">GUI</acronym> screen code (e.g. <acronymtitle="Extensible Markup Language">XML</acronym> file) you must call the <code>(int x, int y)</code> method <em>without</em> any parameters!
In the Nifty <abbrtitle="Graphical User Interface">GUI</abbr> screen code (e.g. XML file) you must call the <code>(int x, int y)</code> method <em>without</em> any parameters!
You can name the method (here <code>clicked</code>) what ever you like, as long as you keep the argument syntax.
</p>
</div>
<!-- EDIT11 SECTION "Pass ClickLoc From Nifty to Java" [7558-8319] -->
<h2><a>Load Several XML Files</a></h2>
<!-- EDIT11 SECTION "Pass ClickLoc From Nifty to Java" [7485-8246] -->
<h2>Load Several XML Files</h2>
<div>
<p>
The basic Nifty <acronymtitle="Graphical User Interface">GUI</acronym> example showed how to use the <code>nifty.fromXML()</code> method to load one <acronymtitle="Extensible Markup Language">XML</acronym> file containing all Nifty <acronymtitle="Graphical User Interface">GUI</acronym> screens.
The following code sample shows how you can load several <acronymtitle="Extensible Markup Language">XML</acronym> files into one nifty object. Loading several files with <code>nifty.addXml()</code> allows you to split up each screen into one <acronymtitle="Extensible Markup Language">XML</acronym> file, instead of all into one hard-to-read <acronymtitle="Extensible Markup Language">XML</acronym> file.
The basic Nifty <abbrtitle="Graphical User Interface">GUI</abbr> example showed how to use the <code>nifty.fromXML()</code> method to load one XML file containing all Nifty <abbrtitle="Graphical User Interface">GUI</abbr> screens.
The following code sample shows how you can load several XML files into one nifty object. Loading several files with <code>nifty.addXml()</code> allows you to split up each screen into one XML file, instead of all into one hard-to-read XML file.
</p>
<pre>NiftyJmeDisplay niftyDisplay = new NiftyJmeDisplay(assetManager, inputManager, audioRenderer, viewPort);
In addition to the <code>nifty.addXml()</code> methods to attach many nifty <acronymtitle="Extensible Markup Language">XML</acronym> files, there exists a <code>nifty.registerScreenController()</code> method to explicitly attach more screen controllers.
In addition to the <code>nifty.addXml()</code> methods to attach many nifty XML files, there exists a <code>nifty.registerScreenController()</code> method to explicitly attach more screen controllers.
</p>
<p>
The following code sample shows how you can explicitly attach several screen controllers before adding the <acronymtitle="Extensible Markup Language">XML</acronym> file to nifty, which would otherwise cause nifty to implicitly instantiate the screen controller class.
The following code sample shows how you can explicitly attach several screen controllers before adding the XML file to nifty, which would otherwise cause nifty to implicitly instantiate the screen controller class.
</p>
<pre>NiftyJmeDisplay niftyDisplay = new NiftyJmeDisplay(assetManager, inputManager, audioRenderer, viewPort);
Learn more about how to create styles by looking at the <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Build_from_Source"><paramname="text"value="<html><u>Nifty GUI source code</u></html>"><paramname="textColor"value="blue"></object> for ???nifty-style-black???. Copy it as a template and change it to create your own style.
Learn more about how to create styles by looking at the <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Build_from_Source"><paramname="text"value="<html><u>Nifty GUI source code</u></html>"><paramname="textColor"value="blue"></object> for “nifty-style-black”. Copy it as a template and change it to create your own style.
</p>
<hr/>
@ -346,18 +326,11 @@ Learn more from the NiftyGUI page:
<li><div><ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui_best_practices.html">Nifty GUI Best Practices</a></div>
</li>
<li><div><strong>Nifty <acronymtitle="Graphical User Interface">GUI</acronym><acronymtitle="Extensible Markup Language">XML</acronym> Layout</strong> or <ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui_java_layout.html">Nifty GUI Java Layout</a></div>
<li><div><strong>Nifty <abbrtitle="Graphical User Interface">GUI</abbr> XML Layout</strong> or <ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui_java_layout.html">Nifty GUI Java Layout</a></div>
</li>
<li><div><ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui_overlay.html">Nifty GUI Overlay</a> or <ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui_projection.html">Nifty GUI Projection</a></div>
</li>
@ -15,22 +15,20 @@
</ol>
<p>
You can "draw" the <acronymtitle="Graphical User Interface">GUI</acronym> to the screen by writing <acronymtitle="Extensible Markup Language">XML</acronym> code (alternatively you can also use Java).
You can “draw” the <abbrtitle="Graphical User Interface">GUI</abbr> to the screen by writing XML code (alternatively you can also use Java).
</p>
</div>
<!-- EDIT1 SECTION "Laying out the GUI in XML" [1-478] -->
In this tutorial, you want to create two game screens: An out-of-game StartScreen that the players see before the game starts; and an in-game <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://en.wikipedia.org/wiki/HUD_%28video_gaming%29"><paramname="text"value="<html><u>HUD</u></html>"><paramname="textColor"value="blue"></object> that displays info during the game. Before writing code, you plan the <acronymtitle="Graphical User Interface">GUI</acronym> layout, either on paper or in a graphic application.
In this tutorial, you want to create two game screens: An out-of-game StartScreen that the players see before the game starts; and an in-game <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://en.wikipedia.org/wiki/HUD_%28video_gaming%29"><paramname="text"value="<html><u>HUD</u></html>"><paramname="textColor"value="blue"></object> that displays info during the game. Before writing code, you plan the <abbrtitle="Graphical User Interface">GUI</abbr> layout, either on paper or in a graphic application.
</p>
<p>
@ -58,7 +56,6 @@ The StartScreen contains:
</ul>
<p>
The HUD contains:
</p>
<ul>
@ -76,31 +73,32 @@ The HUD contains:
</div>
<!-- EDIT2 SECTION "Plan Your GUI Layout" [479-1663] -->
Create an empty screen.xml file in the <code>assets/Interfaces/</code> directory of your project. One <acronymtitle="Extensible Markup Language">XML</acronym> file can contain several, or even all screens. As a reminder: Nifty displays one screen at a time; a screen contains several layers on top of one another; each layer contains panels that are embedded into another; the panels contain the actual content (text, images, or controls).
Create an empty <strong>screen</strong>.xml file in the <code>assets/Interface/</code> directory of your project. ( Rightclick on Interface → New → Other… → <abbrtitle="Graphical User Interface">GUI</abbr> → Empty NiftyGui file)
Afterwards create the directory <code>assets/Interface/Fonts</code> and add a new font e.g. Arial. ( <strong>Rightclick on Interface → New → Other… →</strong> Other → Folder and <abbrtitle="Graphical User Interface">GUI</abbr> → Font)
</p>
<p>
One XML file can contain several, or even all screens. As a reminder: Nifty displays one screen at a time; a screen contains several layers on top of one another; each layer contains panels that are embedded into another; the panels contain the actual content (text, images, or controls).
</p>
</div>
<!-- EDIT3 SECTION "Implement Your GUI Layout" [1664-2139] -->
<h3><a>Make Screens</a></h3>
<!-- EDIT3 SECTION "Implement Your GUI Layout" [1664-2394] -->
<h3>Make Screens</h3>
<div>
<p>
The following minimal <acronymtitle="Extensible Markup Language">XML</acronym> file contains a start screen and a HUD screen. (Neither has been defined yet.)
The following minimal XML file contains a start screen and a HUD screen. (Neither has been defined yet.)
@ -110,21 +108,21 @@ The following minimal <acronym title="Extensible Markup Language">XML</acronym>
<span><span></nifty></span></span></pre>
<p>
Every Nifty <acronymtitle="Graphical User Interface">GUI</acronym> must have a start screen. The others (in this example, the HUD screen) are optional.
Every Nifty <abbrtitle="Graphical User Interface">GUI</abbr> must have a start screen. The others (in this example, the HUD screen) are optional.
</p>
<p>
<strong>Note:</strong> In the following examples, the <acronymtitle="Extensible Markup Language">XML</acronym> schema header is abbreviated to just <code><nifty></code>.
<strong>Note:</strong> In the following examples, the XML schema header is abbreviated to just <code><nifty></code>.
</p>
</div>
<!-- EDIT4 SECTION "Make Screens" [2140-2825] -->
<h3><a>Make Layers</a></h3>
<!-- EDIT4 SECTION "Make Screens" [2395-3123] -->
<h3>Make Layers</h3>
<div>
<p>
The following minimal <acronymtitle="Extensible Markup Language">XML</acronym> file shows how we added layers to the start screen and HUD screen:
The following minimal XML file shows how we added layers to the start screen and HUD screen.
Delete all from the file and add following code:
</p>
<pre><span><span><nifty></span></span>
<span><screen id="start"></span>
@ -150,12 +148,11 @@ In a layer, you can now add panels and arrange them. Panels are containers that
</p>
</div>
<!-- EDIT5 SECTION "Make Layers" [2826-3599] -->
<h3><a>Make Panels</a></h3>
<!-- EDIT5 SECTION "Make Layers" [3124-3946] -->
<h3>Make Panels</h3>
<div>
<p>
A panel is the inner-most container (that will contain the actual content: text, images, or controls). You place panels inside layers. The following panels go into in the <code>start</code> screen's <code>foreground</code> layer:
@ -203,76 +200,67 @@ The result should look as follows:
</p>
</div>
<!-- EDIT6 SECTION "Make Panels" [3600-5482] -->
<h2><a>Adding Content to Panels</a></h2>
<!-- EDIT6 SECTION "Make Panels" [3947-5829] -->
<h2>Adding Content to Panels</h2>
<div>
<p>
See also <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Layout_Introduction"><paramname="text"value="<html><u>Layout Introduction</u></html>"><paramname="textColor"value="blue"></object> on the Nifty <acronymtitle="Graphical User Interface">GUI</acronym> site.
See also <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Layout_Introduction"><paramname="text"value="<html><u>Layout Introduction</u></html>"><paramname="textColor"value="blue"></object> on the Nifty <abbrtitle="Graphical User Interface">GUI</abbr> site.
</p>
</div>
<!-- EDIT7 SECTION "Adding Content to Panels" [5483-5661] -->
<h3><a>Add Images</a></h3>
<!-- EDIT7 SECTION "Adding Content to Panels" [5830-6008] -->
<h3>Add Images</h3>
<div>
<p>
The start-background.png image is a fullscreen background picture. In the <code>start</code> screen, add the following image element:
The <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://hub.jmonkeyengine.org/wikinbdocs:/com/jme3/gde/docs/jme3:advanced:start-background.png"><paramname="text"value="<html><u>start-background.png</u></html>"><paramname="textColor"value="blue"></object> image is a fullscreen background picture. Add it to <code>Interface</code>. In the <code>start</code> screen, add the following image element:
The hud-frame.png image is a transparent frame that we use as HUD decoration. In the <code>hud</code> screen, add the following image element:
The <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://hub.jmonkeyengine.org/wikinbdocs:/com/jme3/gde/docs/jme3:advanced:hud-frame.png"><paramname="text"value="<html><u>hud-frame.png</u></html>"><paramname="textColor"value="blue"></object> image is a transparent frame that we use as HUD decoration. Add it to <code>Interface</code>. In the <code>hud</code> screen, add the following image element:
In order to make the hud-frame.png independent of the screen resolution you are using, you could use the <code>imageMode</code> attribute on the image element <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Resizable_Images_(ImageMode%3Dresize)_explained"><paramname="text"value="<html><u> Resizable Images (ImageMode=resize) explained</u></html>"><paramname="textColor"value="blue"></object>
The face1.png image is an image that you want to use as a status icon.
The <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://hub.jmonkeyengine.org/wikinbdocs:/com/jme3/gde/docs/jme3:advanced:face1.png"><paramname="text"value="<html><u>face1.png</u></html>"><paramname="textColor"value="blue"></object> image is an image that you want to use as a status icon. Add it to <code>Interface</code>.
In the <code>hud</code> screen's <code>foreground</code> layer, add the following image element:
For longer pieces of static text, such as an introduction, you can use wrap="true". Add the following text element to the <code>Start screen</code>:
For longer pieces of static text, such as an introduction, you can use wrap=“true”. Add the following text element to the <code>Start screen</code>:
<span><text text="Here goes some text describing the game and the rules and stuff. Incidentally,
@ -281,16 +269,16 @@ For longer pieces of static text, such as an introduction, you can use wrap=&quo
<span><span></panel></span></span></pre>
<p>
The font used is jME3's default font "Interface/Fonts/Default.fnt" which is included in the jMonkeyEngine.JAR. You can add your own fonts to your own <code>assets/Interface</code> directory.
The font used is jME3's default font “Interface/Fonts/Default.fnt” which is included in the jMonkeyEngine.JAR. You can add your own fonts to your own <code>assets/Interface/Fonts</code> directory.
@ -302,11 +290,10 @@ Note that the useStyles tag must be the first child of the nifty tag, otherwise
</div>
<h4><a>Label Control</a></h4>
<h4>Label Control</h4>
<div>
<p>
Use label controls for text that you want to edit dynamically from Java. One example for this is the score display.
In the <code>hud</code> screen's <code>foreground</code> layer, add the following text element:
</p>
@ -320,12 +307,11 @@ Note that the width and height do not scale the bitmap font, but indirectly make
</div>
<h4><a>Button Control</a></h4>
<h4>Button Control</h4>
<div>
<p>
Our <acronymtitle="Graphical User Interface">GUI</acronym> plan asks for two buttons on the start screen. You add the Start and Quit buttons to the bottom panel of the <code>start</code> screen using the <code><control></code> element:
Our <abbrtitle="Graphical User Interface">GUI</abbr> plan asks for two buttons on the start screen. You add the Start and Quit buttons to the bottom panel of the <code>start</code> screen using the <code><control></code> element:
<span><text text="Here goes some text describing the game and the rules and stuff. Incidentally, the text is quite long and needs to wrap at the end of lines. ..." font="Interface/Fonts/Default.fnt" width="100%" height="100%" wrap="true" /></span>
Nifty additionally offers many customizable controls such as check boxes, text fields, menus, chats, tabs, ??? See also <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Elements"><paramname="text"value="<html><u>Elements</u></html>"><paramname="textColor"value="blue"></object> on the Nifty <acronymtitle="Graphical User Interface">GUI</acronym> site.
Nifty additionally offers many customizable controls such as check boxes, text fields, menus, chats, tabs, … See also <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Elements"><paramname="text"value="<html><u>Elements</u></html>"><paramname="textColor"value="blue"></object> on the Nifty <abbrtitle="Graphical User Interface">GUI</abbr> site.
When you preview this code in the jMonkeyEngine <acronymtitle="Software Development Kit">SDK</acronym>, our tutorial demo should looks as follows: A start screen with two buttons, and a game screen with a simple HUD frame and a blue cube (which stands for any jME3 game content).
When you preview this code in the jMonkeyEngine SDK, our tutorial demo should looks as follows: A start screen with two buttons, and a game screen with a simple HUD frame and a blue cube (which stands for any jME3 game content).
</p>
<p>
@ -369,13 +404,12 @@ Compare this result with the layout draft above.
Integrate the <acronymtitle="Graphical User Interface">GUI</acronym> into the game. Typically, you will overlay the <acronymtitle="Graphical User Interface">GUI</acronym>.
Integrate the <abbrtitle="Graphical User Interface">GUI</abbr> into the game. Typically, you will overlay the <abbrtitle="Graphical User Interface">GUI</abbr>.
<h1><a>Working Blender and OgreXML Versions</a></h1>
<h1>Working Blender and OgreXML Versions</h1>
<div>
<p>
Here you can find working combinations of Blender and the OgreXML exporter, with any tips or bugs associated with each.
</p>
<div><table>
<thead>
<tr>
<th> Blender Version </th><th> OgreXML Exporter Version </th><th> Notes </th>
</tr>
</thead>
<tr>
<td> 2.6.3 </td><td><objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://code.google.com/p/blender2ogre/downloads/list"><paramname="text"value="<html><u>0.5.8</u></html>"><paramname="textColor"value="blue"></object></td><td> Root bone, no transforms on object, no envelopes </td>
</tr>
@ -26,11 +27,10 @@ Here you can find working combinations of Blender and the OgreXML exporter, with
<!-- EDIT2 TABLE [173-518] -->
</div>
<!-- EDIT1 SECTION "Working Blender and OgreXML Versions" [1-519] -->
<h1><a>Tips</a></h1>
<h1>Tips</h1>
<div>
<p>
Tips for exporting animations through OgreXML correctly:
</p>
<ul>
@ -47,7 +47,6 @@ Tips for exporting animations through OgreXML correctly:
</ul>
<p>
Test Character - <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://dl.dropbox.com/u/26887202/123/jme_blender/characterOgre26.zip"><paramname="text"value="<html><u>http://dl.dropbox.com/u/26887202/123/jme_blender/characterOgre26.zip</u></html>"><paramname="textColor"value="blue"></object>
</p>
@ -58,11 +57,10 @@ Test Character - <object classid="java:org.netbeans.modules.javahelp.BrowserDisp
</div>
<!-- EDIT3 SECTION "Tips" [520-996] -->
<h1><a>Troubleshooting</a></h1>
<h1>Troubleshooting</h1>
<div>
<p>
<strong>Q:</strong><em>My animation is stretched.</em>
</p>
@ -72,4 +70,4 @@ Test Character - <object classid="java:org.netbeans.modules.javahelp.BrowserDisp
@ -13,13 +13,12 @@ The Open Game Finder (OGF) by Mark Schrijver can be plugged into any Java game.
</ul>
<p>
Both on the client and the server side of OGF is written purely in Java. OGF has a pluggable architecture and comes with a full set of plugins to get the job done. You can add your own plugins, or replace existing plugins to make them more in line with your game. OGF uses NiftyGUI as the main <acronymtitle="Graphical User Interface">GUI</acronym> plugin.
Both on the client and the server side of OGF is written purely in Java. OGF has a pluggable architecture and comes with a full set of plugins to get the job done. You can add your own plugins, or replace existing plugins to make them more in line with your game. OGF uses NiftyGUI as the main <abbrtitle="Graphical User Interface">GUI</abbr> plugin.
</p>
</div>
<!-- EDIT1 SECTION "Open Game Finder" [1-629] -->
<h2><a>Installation</a></h2>
<h2>Installation</h2>
<div>
<ol>
<li><div> Go to <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://code.google.com/p/open-game-finder/downloads/list"><paramname="text"value="<html><u>http://code.google.com/p/open-game-finder/downloads/list</u></html>"><paramname="textColor"value="blue"></object></div>
@ -32,23 +31,23 @@ Both on the client and the server side of OGF is written purely in Java. OGF has
</div>
<!-- EDIT2 SECTION "Installation" [630-849] -->
<h2><a>Setting up the Database</a></h2>
<h2>Setting up the Database</h2>
<div>
<p>
The OGF server uses an embedded Apache Derby database. You have to install the database, this means creating the data files and adding the tables. You can do this straight from the command line by running a script file.
</p>
<ul>
<li><div> On Windows, use installServer.bat to create a new database from scratch. On Mac <acronymtitle="Operating System">OS</acronym> or Linux, run <code>java -jar lib/Server-0.1.jar install</code> in the Terminal.</div>
<li><div> On Windows, use installServer.bat to create a new database from scratch. On Mac <abbrtitle="Operating System">OS</abbr> or Linux, run <code>java -jar lib/Server-0.1.jar install</code> in the Terminal.</div>
</li>
<li><div> On Windows, use updateServer.bat to update the difference between the current state of the database and the way it should be. On Mac <acronymtitle="Operating System">OS</acronym> and Linux, run <code>java -jar lib/Server-0.1.jar update</code> in the Terminal. <br/>
<li><div> On Windows, use updateServer.bat to update the difference between the current state of the database and the way it should be. On Mac <abbrtitle="Operating System">OS</abbr> and Linux, run <code>java -jar lib/Server-0.1.jar update</code> in the Terminal. <br/>
<strong>This new feature is currently untested.</strong></div>
</li>
</ul>
</div>
<!-- EDIT3 SECTION "Setting up the Database" [850-1523] -->
<h2><a>Running the server</a></h2>
<h2>Running the server</h2>
<div>
<p>
@ -65,12 +64,11 @@ Change into the OGF-Server directory and run the server:
The server is now running and ready to accept connections. <br/>
<strong>Note:</strong> In the alpha release, the server runs on localhost. In the final release, you will be able to configure the host!
</p>
</div>
<!-- EDIT4 SECTION "Running the server" [1524-1913] -->
<h2><a>Running the client</a></h2>
<h2>Running the client</h2>
<div>
<ol>
<li><div> Change into the OGF-Client directory and run the client:</div>
@ -89,12 +87,11 @@ The server is now running and ready to accept connections. <br/>
A client is now running, connects to the server, and displays a registration/login window.
The chat window shows a list of all users logged in to the server. Logged-in users can send public messages, and can receive public messages from others.
You cannot create a 3D model for delicate things like fire, smoke, or explosions. Particle Emitters are quite an efficient solution to create these kinds of effects: The emitter renders a series of flat orthogonal images and manipulates them in a way that creates the illusion of a anything from a delicate smoke cloud to individual flames, etc.
Creating an effect involves some trial and error to get the settings <em>just right</em>, and it's worth exploring the expressiveness of the options described below.
</p>
@ -19,11 +18,11 @@ Creating an effect involves some trial and error to get the settings <em>just ri
<td> number </td><td><code>setNumParticles()</code></td><td></td><td> The maximum number of particles visible at the same time. Specified by user in constructor. </td>
</tr>
@ -82,8 +83,8 @@ Set both to different colors for a gradient effect (e.g. fire). </td>
</tr>
<tr>
<td> fanning out </td><td><code>getParticleInfluencer(). setVelocityVariation(variation)</code></td><td> 0.2f </td><td> How much the direction (<code>setInitialVelocity()</code>) can vary among particles. Use a value between 1 and 0 to create a directed swarm-like cloud of particles. <br/>
1 = Maximum variation, particles emit in random 360?? directions (e.g. explosion, butterflies). <br/>
0.5f = particles are emitted within 180?? of the initial direction. <br/>
1 = Maximum variation, particles emit in random 360° directions (e.g. explosion, butterflies). <br/>
0.5f = particles are emitted within 180° of the initial direction. <br/>
0 = No variation, particles fly in a straight line in direction of start velocity (e.g. lasergun blasts). </td>
</tr>
<tr>
@ -115,23 +116,22 @@ false = Particles fly straight like you drew them in the sprite texture (e.g. in
<td> start area </td><td><code>setShape(new EmitterSphereShape( Vector3f.ZERO, 2f));</code></td><td>EmitterPointShape()</td><td>By default, particles are emitted from the emitters location (a point). You can increase the emitter shape to occupy a sphere, so that the start point of new particles can be anywhere inside the sphere, which makes the effect a bit more irregular.</td>
</tr>
</table></div>
<!-- EDIT4 TABLE [1638-5412] -->
<!-- EDIT4 TABLE [1599-5373] -->
<p>
Build up you effect by specifying one parameter after the other. If you change several parameters at the same time, it's difficult to tell which of the values caused which outcome.
Use the common Particle.j3md Material Definition and a texture to specify the shape of the particles. The shape is defined by the texture you provide and can be anything ??? debris, flames, smoke, mosquitoes, leaves, butterflies??? be creative.
Use the common Particle.j3md Material Definition and a texture to specify the shape of the particles. The shape is defined by the texture you provide and can be anything – debris, flames, smoke, mosquitoes, leaves, butterflies… be creative.
@ -143,7 +143,7 @@ Use the common Particle.j3md Material Definition and a texture to specify the sh
flash.setSelectRandomImage(true);</pre>
<p>
The effect texture can be one image, or contain a sprite animation ??? a series of slightly different pictures in equally spaced rows and columns. If you choose the sprite animation:
The effect texture can be one image, or contain a sprite animation – a series of slightly different pictures in equally spaced rows and columns. If you choose the sprite animation:
</p>
<ul>
<li><div> Specify the number of rows and columns using setImagesX(2) and setImagesY().</div>
@ -153,13 +153,12 @@ The effect texture can be one image, or contain a sprite animation ??? a series
</ul>
<p>
<strong>Examples:</strong> Have a look at the following default textures and you will see how you can create your own sprite textures after the same fashion.
</p>
</div>
<!-- EDIT5 SECTION "Create an Effect Material" [5595-6915] -->
<h3><a>Default Particle Textures</a></h3>
<!-- EDIT5 SECTION "Create an Effect Material" [5556-6876] -->
<h3>Default Particle Textures</h3>
<div>
<p>
@ -167,45 +166,46 @@ The Material is used together with grayscale texture: The black parts will be tr
The following effect textures are available by default from <code>test-data.jar</code>. You can also load your own textures from your assets directory.
<strong>Tip:</strong> Use the <code>setStartColor()</code>/<code>setEndColor()</code> settings described above to colorize the white and gray parts of textures.
@ -222,20 +222,18 @@ The following effect textures are available by default from <code>test-data.jar<
rootNode.attachChild(fire);</pre>
<p>
Browse the full source code of all <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://code.google.com/p/jmonkeyengine/source/browse/#svn%2Ftrunk%2Fengine%2Fsrc%2Ftest%2Fjme3test%2Feffect"><paramname="text"value="<html><u>effect examples</u></html>"><paramname="textColor"value="blue"></object> here.
</p>
<hr/>
<p>
See also: <ahref="/com/jme3/gde/docs/jme3/advanced/effects_overview.html">Effects Overview</a>
A physics simulation is used in games and applications where objects are exposed to physical forces: Think of games like pool billiard and car racing simulators. Massive objects are pulled by gravity, forces cause objects to gain momentum, friction slows them down, solid objects collide and bounce off one another, etc. Action and Adventure games also make use of physics to implement solid obstacles, falling, and jumping.
</p>
@ -17,11 +16,11 @@ If you are looking for info on how to respond to physics events such as collisio
jME3 has a complete, slightly adapted but fully wrapped Bullet <acronymtitle="Application Programming Interface">API</acronym> that uses normal jME math objects (Vector3f, Quaternion etc) as input/output data. All normal bullet objects like RigidBodies, Constraints (called "Joints" in jME3) and the various collision shapes are available, all mesh formats can be converted from jME to bullet.
jME3 has a complete, slightly adapted but fully wrapped Bullet <abbrtitle="Application Programming Interface">API</abbr> that uses normal jME math objects (Vector3f, Quaternion etc) as input/output data. All normal bullet objects like RigidBodies, Constraints (called “Joints” in jME3) and the various collision shapes are available, all mesh formats can be converted from jME to bullet.
</p>
<p>
@ -29,7 +28,7 @@ The PhysicsSpace object is the central object in bullet and all objects have to
</p>
<p>
The base bullet objects are also available as simple to use controls that can be attached to spatials to directly control these by physics forces and influences. The RigidBodyControl for example includes a simple constructor that automatically creates a hull collision shape or a mesh collision shape based on the given input mass and the mesh of the spatial it is attached to. This makes enabling physics on a Geometry as simple as "spatial.addControl(new RigidBodyControl(1));"
The base bullet objects are also available as simple to use controls that can be attached to spatials to directly control these by physics forces and influences. The RigidBodyControl for example includes a simple constructor that automatically creates a hull collision shape or a mesh collision shape based on the given input mass and the mesh of the spatial it is attached to. This makes enabling physics on a Geometry as simple as “spatial.addControl(new RigidBodyControl(1));”
</p>
<p>
@ -75,7 +74,6 @@ Due to some differences in how bullet and jME handle the scene and other objects
</ul>
<p>
When you use this physics simulation, values correspond to the following units:
</p>
<ul>
@ -88,7 +86,6 @@ When you use this physics simulation, values correspond to the following units:
</ul>
<p>
Bullet physics runs internally at 60fps by default. This rate is not dependent on the actual framerate and it does not lock the framerate at 60fps. Instead, when the actual fps is higher than the physics framerate the system will display interpolated positions for the physics objects. When the framerate is lower than the physics framerate, the physics space will be stepped multiple times per frame to make up for the missing calculations.
</p>
@ -108,11 +105,10 @@ Internally, the updating and syncing of the actual physics objects in the Bullet
A CollisionShape is a simplified shape for which physics are easier to calculate than for the true shape of the model. This simplication approach speeds up the simulation greatly.
</p>
<p>
Before you can create a Physics Control, you must create a CollisionShape from the <code>com.jme3.bullet.collision.shapes</code> package. (Read the tip under "PhysicsControls Code Samples" how to use default CollisionShapes for Boxes and Spheres.)
Before you can create a Physics Control, you must create a CollisionShape from the <code>com.jme3.bullet.collision.shapes</code> package. (Read the tip under “PhysicsControls Code Samples” how to use default CollisionShapes for Boxes and Spheres.)
<td> MeshCollisionShape </td><td> A mesh-accurate shape for static or kinematic Spatials. Can have complex shapes with openings and appendages. <br/>
<strong>Limitations:</strong> Collisions between two mesh-accurate shapes cannot be detected, only non-mesh shapes can collide with this shape. This Shape does not work with dynamic Spatials. </td><td> A whole static game level model. </td>
@ -256,13 +249,14 @@ All non-mesh CollisionShapes can be used for dynamic, kinematic, as well as stat
</table></div>
<!-- EDIT7 TABLE [9719-11236] -->
<p>
On a CollisionShape, you can apply a few properties
<td> setScale(new Vector3f(2f,2f,2f)) </td><td> You can change the scale of collisionshapes (whether it be, Simple or Mesh). You cannot change the scale of a CompoundCollisionShape however. A sphere collision shape, will change its radius based on the X component of the vector passed in. You must scale a collision shape before attaching it to the physicsSpace, or you must readd it to the physicsSpace each time the scale changes. </td><td> Scale a player in the Y axis by 2: <br/>
<code>new Vector3f(1f,2f,1f)</code></td>
@ -270,7 +264,6 @@ On a CollisionShape, you can apply a few properties
</table></div>
<!-- EDIT8 TABLE [11290-11827] -->
<p>
The mesh-accurate shapes can use a CollisionShapeFactory as constructor (code samples see below).
</p>
@ -286,7 +279,7 @@ The mesh-accurate shapes can use a CollisionShapeFactory as constructor (code sa
</div>
<!-- EDIT5 SECTION "Create a CollisionShape" [7743-12497] -->
<h3><a>CollisionShape Code Samples</a></h3>
<h3>CollisionShape Code Samples</h3>
<div>
<ul>
<li><div> One way of using a constructor and a Geometry's mesh for static Spatials:<pre>MeshCollisionShape level_shape =
@ -317,54 +310,54 @@ The mesh-accurate shapes can use a CollisionShapeFactory as constructor (code sa
BulletPhysics are available in jME3 through PhysicsControls classes from the com.jme3.bullet.control package. jME3's PhysicsControl classes directly extend BulletPhysics objects and are the recommended way to use physics in a jME3 application. PhysicsControls are flexible and can be added to any Spatial to make it act according to physical properties.
<td>RigidBodyControl</td><td>The most commonly used PhysicsControl. You can use it for dynamic objects (solid objects that freely affected by collisions, forces, or gravity), for static objects (solid but not affected by any forces), or kinematic objects (remote-controlled solid objects). </td><td>Impacting projectiles, moving obstacles like crates, rolling and bouncing balls, elevators, flying aircaft or space ships. <br/>
<td>GhostControl</td><td>Use for collision and intersection detection between physical objects. A GhostControl itself is <em>non-solid</em> and invisible. GhostControl moves with the Spatial it is attached to. Use GhostControls to <ahref="/com/jme3/gde/docs/jme3/advanced/physics_listeners.html">implement custom game interactions</a> by adding it to a visible Geometry. </td><td>A monster's "aggro radius", CharacterControl collisions, motion detectors, photo-electric alarm sensors, poisonous or radioactive perimeters, life-draining ghosts, etc. </td>
<td>GhostControl</td><td>Use for collision and intersection detection between physical objects. A GhostControl itself is <em>non-solid</em> and invisible. GhostControl moves with the Spatial it is attached to. Use GhostControls to <ahref="/com/jme3/gde/docs/jme3/advanced/physics_listeners.html">implement custom game interactions</a> by adding it to a visible Geometry. </td><td>A monster's “aggro radius”, CharacterControl collisions, motion detectors, photo-electric alarm sensors, poisonous or radioactive perimeters, life-draining ghosts, etc. </td>
PhysicsVehicleWheel</td><td> Special Control used for <ahref="/com/jme3/gde/docs/jme3/advanced/vehicles.html">"terrestrial" vehicles with suspension and wheels</a>. </td><td>Cars, tanks, hover crafts, ships, motorcycles???</td>
PhysicsVehicleWheel</td><td> Special Control used for <ahref="/com/jme3/gde/docs/jme3/advanced/vehicles.html">"terrestrial" vehicles with suspension and wheels</a>. </td><td>Cars, tanks, hover crafts, ships, motorcycles…</td>
</tr>
<tr>
<td>CharacterControl</td><td>Special Control used for <ahref="/com/jme3/gde/docs/jme3/advanced/walking_character.html">Walking Character</a>s.</td><td>Upright walking persons, animals, robots???</td>
<td>CharacterControl</td><td>Special Control used for <ahref="/com/jme3/gde/docs/jme3/advanced/walking_character.html">Walking Character</a>s.</td><td>Upright walking persons, animals, robots…</td>
</tr>
<tr>
<td>RagDollControl</td><td>Special Control used for <ahref="/com/jme3/gde/docs/jme3/advanced/ragdoll.html">collapsing, flailing, or falling characters</a></td><td>Falling persons, animals, robots, "Rag dolls"</td>
<td>RagDollControl</td><td>Special Control used for <ahref="/com/jme3/gde/docs/jme3/advanced/ragdoll.html">collapsing, flailing, or falling characters</a></td><td>Falling persons, animals, robots, “Rag dolls”</td>
</tr>
</table></div>
<!-- EDIT12 TABLE [14997-15509] -->
<p>
Click the links for details on the special PhysicsControls. This article is about RigidBodyControl.
The most commonly used physics control is RigidBodyControl. The RigidBodyControl constructor takes up to two parameters: a collision shape and a mass (a float in kilograms). The mass parameter also determines whether the object is dynamic (movable) or static (fixed). For a static object such as a floor or wall, specify zero mass.
</p>
<pre>RigidBodyControl myThing_phys =
@ -380,14 +373,12 @@ The most commonly used physics control is RigidBodyControl. The RigidBodyContro
<p>
The following creates a box Geometry with the correct default BoxCollisionShape:
</p>
<pre>Box b = new Box(1,1,1);
<pre>Box(1,1,1);
Geometry box_geo = new Geometry("Box", b);
The following creates a MeshCollisionShape for a whole loaded (static) scene:
</p>
<pre>...
gameLevel.addControl(new RigidBodyControl(0.0f)); // explicit zero mass, implicit MeshCollisionShape</pre>
@ -395,16 +386,14 @@ gameLevel.addControl(new RigidBodyControl(0.0f)); // explicit ze
<p>
<p><div>Spheres and Boxes automatically fall back on the correct default CollisionShape if you do not specify a CollisionShape in the RigidBodyControl constructor. Complex static objects can fall back on MeshCollisionShapes, unless it is a Node, in which case it will become a CompoundCollisionShape containing a MeshCollisionShape
</div></p>
</p>
</div>
<!-- EDIT13 SECTION "Physics Control Code Samples" [15612-17129] -->
<h2><a>Add PhysicsControl to Spatial</a></h2>
<h2>Add PhysicsControl to Spatial</h2>
<div>
<p>
For each physical Spatial in the scene:
</p>
<ol>
@ -417,13 +406,11 @@ For each physical Spatial in the scene:
</div>
<!-- EDIT14 SECTION "Add PhysicsControl to Spatial" [17130-17377] -->
<h2><a>Add PhysicsControl to PhysicsSpace</a></h2>
<h2>Add PhysicsControl to PhysicsSpace</h2>
<div>
<p>
The PhysicsSpace is an object in BulletAppState that is like a rootNode for Physics Controls.
</p>
<ul>
<li><div> Just like you add the Geometry to the rootNode, you add its PhysicsControl to the PhysicsSpace. <pre>bulletAppState.getPhysicsSpace().add(myThing_phys);
<p><div>You can either add the <em>PhysicsControl</em> to the PhysicsSpace, or add the PhysicsControl to the Geometry and then add the <em>Geometry</em> to the PhysicsSpace. jME3 understands both and the outcome is the same.
</div></p>
</p>
</div>
<!-- EDIT15 SECTION "Add PhysicsControl to PhysicsSpace" [17378-18193] -->
<h2><a>Changing the Scale of a PhysicsControl</a></h2>
<!-- EDIT16 SECTION "Changing the Scale of a PhysicsControl" [18194-19944] -->
<h3><a>PhysicsSpace Code Samples</a></h3>
<h3>PhysicsSpace Code Samples</h3>
<div>
<p>
The PhysicsSpace also manages global physics settings. Typically, you can leave the defaults, and you don't need to change the following settings, but it's good to know what they are for:
<td>setGravity(new Vector3f(0, -9.81f, 0));</td><td>Specifies the global gravity.</td>
</tr>
<tr>
<td>setAccuracy(1f/60f);</td><td>Specifies physics accuracy. The higher the accuracy, the slower the game. Increase value if objects are passing through one another, or bounce oddly.</td>
<td>setAccuracy(1f/60f);</td><td>Specifies physics accuracy. The higher the accuracy, the slower the game. Decrease value if objects are passing through one another, or bounce oddly. (e.g. Change value from 1f/60f to something like 1f/80f.) </td>
</tr>
<tr>
<td>setMaxSubSteps(4);</td><td>Compensates low FPS: Specifies the maximum amount of extra steps that will be used to step the physics when the game fps is below the physics fps. This maintains determinism in physics in slow (low-fps) games. For example a maximum number of 2 can compensate for framerates as low as 30 fps (physics has a default accuracy of 60 fps). Note that setting this value too high can make the physics drive down its own fps in case its overloaded.</td>
@ -512,25 +497,25 @@ setWorldMin(new Vector3f(-10000f, -10000f, -10000f));</td><td>Specifies the size
<td>setCcdMotionThreshold()</td><td>The amount of motion in 1 physics tick to trigger the continuous motion detection in moving objects that push one another. Rarely used, but necessary if your moving objects get stuck or roll through one another.</td>
<td> setGravity(new Vector3f(0f,-9.81f,0f)) </td><td> You can change the gravity of individual physics objects after they were added to the PhysicsSpace. Gravity is a vector pointing from this Spatial towards the source of gravity. The longer the vector, the stronger is gravity. <br/>
If gravity is the same absolute direction for all objects (e.g. on a planet surface), set this vector globally on the PhysicsSpace object and not individually. <br/>
@ -554,16 +539,16 @@ This setting has an impact on performance, so use it sparingly. </td><td> Brick:
Rubber ball: 1.0f </td>
</tr>
</table></div>
<!-- EDIT20 TABLE [21604-23114] -->
<!-- EDIT20 TABLE [21663-23173] -->
<p>
On a RigidBodyControl, you can apply the following physical forces:
<td> setPhysicsLocation()</td><td>Positions the objects. Do not use setLocalTranslation() for physical objects. Important: Make certain not to make CollisionShapes overlap when positioning them. </td>
</tr>
@ -575,15 +560,14 @@ On a RigidBodyControl, you can apply the following physical forces:
<li><div> Kinematics are solid and characters can "stand" on them.</div>
<li><div> Kinematics are solid and characters can “stand” on them.</div>
</li>
<li><div> When they collide, Kinematics push dynamic objects, but a dynamic object never pushes a Kinematic. </div>
</li>
<li><div> You can hang kinematics up "in mid-air" and attach other PhysicsControls to them using <ahref="/com/jme3/gde/docs/jme3/advanced/hinges_and_joints.html">hinges and joints</a>. Picture them as "air hooks" for flying aircraft carriers, floating islands in the clouds, suspension bridges, swings, chains???</div>
<li><div> You can hang kinematics up “in mid-air” and attach other PhysicsControls to them using <ahref="/com/jme3/gde/docs/jme3/advanced/hinges_and_joints.html">hinges and joints</a>. Picture them as “air hooks” for flying aircraft carriers, floating islands in the clouds, suspension bridges, swings, chains…</div>
</li>
<li><div> You can use Kinematics to create mobile remote-controlled physical objects, such as moving elevator platforms, flying blimps/airships. You have full control how Kinematics move, they never "fall" or "topple over".</div>
<li><div> You can use Kinematics to create mobile remote-controlled physical objects, such as moving elevator platforms, flying blimps/airships. You have full control how Kinematics move, they never “fall” or “topple over”.</div>
</li>
</ul>
<p>
<p><div>The position of a kinematic RigidBodyControl is updated automatically depending on its spatial's translation. You move Spatials with a kinematic RigidBodyControl programmatically, that means you write translation and rotation code in the update loop. You describe the motion of kinematic objects either by using methods such as <code>setLocalTranslation()</code> or <code>move()</code>, or by using a <ahref="/com/jme3/gde/docs/jme3/advanced/motionpath.html">MotionPath</a>.
</div></p>
</p>
</div>
<!-- EDIT22 SECTION "Kinematic vs Dynamic vs Static" [23796-26197] -->
<h2><a>Forces: Moving Dynamic Objects</a></h2>
<!-- EDIT22 SECTION "Kinematic vs Dynamic vs Static" [23855-26256] -->
<h2>Forces: Moving Dynamic Objects</h2>
<div>
<p>
Use the following methods to move dynamic physical objects.
</p>
<div><table>
<thead>
<tr>
<th> PhysicsControl Method </th><th> Motion </th>
</tr>
</thead>
<tr>
<td> setLinearVelocity(new Vector3f(0f,0f,1f)) </td><td> Set the linear speed of this object. </td>
</tr>
@ -670,39 +655,39 @@ Use the following methods to move dynamic physical objects.
<td> setAngularVelocity(new Vector3f(0f,0f,1f)) </td><td> Set the rotational speed of the object; the x, y and z component are the speed of rotation around that axis. </td>
</tr>
<tr>
<td> applyCentralForce(???) </td><td> Move (push) the object once with a certain moment, expressed as a Vector3f. </td>
<td> applyCentralForce(…) </td><td> Move (push) the object once with a certain moment, expressed as a Vector3f. </td>
</tr>
<tr>
<td> applyForce(???) </td><td> Move (push) the object once with a certain moment, expressed as a Vector3f. Optionally, you can specify where on the object the pushing force hits. </td>
<td> applyForce(…) </td><td> Move (push) the object once with a certain moment, expressed as a Vector3f. Optionally, you can specify where on the object the pushing force hits. </td>
</tr>
<tr>
<td> applyTorque(???) </td><td> Rotate (twist) the object once around its axes, expressed as a Vector3f. </td>
<td> applyTorque(…) </td><td> Rotate (twist) the object once around its axes, expressed as a Vector3f. </td>
</tr>
<tr>
<td> applyImpulse(???) </td><td> An idealised change of momentum. This is the kind of push that you would use on a pool billiard ball. </td>
<td> applyImpulse(…) </td><td> An idealised change of momentum. This is the kind of push that you would use on a pool billiard ball. </td>
</tr>
<tr>
<td> applyTorqueImpulse(???) </td><td> An idealised change of momentum. This is the kind of push that you would use on a pool billiard ball. </td>
<td> applyTorqueImpulse(…) </td><td> An idealised change of momentum. This is the kind of push that you would use on a pool billiard ball. </td>
</tr>
<tr>
<td> clearForces()</td><td>Cancels out all forces (force, torque) etc and stops the motion.</td>
</tr>
</table></div>
<!-- EDIT25 TABLE [26303-27292] -->
<!-- EDIT25 TABLE [26362-27351] -->
<p>
<p><div>It is technically possible to position PhysicsControls using setLocalTranslation(), e.g. to place them in their start position in the scene. However you must be very careful not to cause an "impossible state" where one physical object overlaps with another! Within the game, you typically use the setters shown here exclusively.
<p><div>It is technically possible to position PhysicsControls using setLocalTranslation(), e.g. to place them in their start position in the scene. However you must be very careful not to cause an “impossible state” where one physical object overlaps with another! Within the game, you typically use the setters shown here exclusively.
</div></p>
</p>
<p>
PhysicsControls also support the following advanced features:
<td> setCollisionShape(collisionShape)</td><td>Changes the collision shape after creation.</td>
</tr>
@ -710,7 +695,7 @@ PhysicsControls also support the following advanced features:
<td> setCollideWithGroups() <br/>
setCollisionGroup() <br/>
addCollideWithGroup(COLLISION_GROUP_01) <br/>
removeCollideWithGroup(COLLISION_GROUP_01)</td><td>Collision Groups are integer bit masks ??? enums are available in the CollisionObject. All physics objects are by default in COLLISION_GROUP_01. Two objects collide when the collideWithGroups set of one contains the Collision Group of the other. Use this to improve performance by grouping objects that will never collide in different groups (the the engine saves times because it does not need to check on them).</td>
removeCollideWithGroup(COLLISION_GROUP_01)</td><td>Collision Groups are integer bit masks – enums are available in the CollisionObject. All physics objects are by default in COLLISION_GROUP_01. Two objects collide when the collideWithGroups set of one contains the Collision Group of the other. Use this to improve performance by grouping objects that will never collide in different groups (the the engine saves times because it does not need to check on them).</td>
</tr>
<tr>
<td> setDamping(float, float)</td><td>The first value is the linear threshold and the second the angular. This simulates dampening of forces, for example for underwater scenes.</td>
@ -725,23 +710,22 @@ removeCollideWithGroup(COLLISION_GROUP_01)</td><td>Collision Groups are integer
<td> setCcdMotionThreshold(0f) </td><td>Sets the amount of motion that has to happen in one physics tick to trigger the continuous motion detection in moving objects that push one another. This avoids the problem of fast objects moving through other objects. Set to zero to disable (default).</td>
</tr>
<tr>
<td> setCcdSweptSphereRadius(.5f)</td><td>Bullet does not use the full collision shape for continuous collision detection, instead it uses a "swept sphere" shape to approximate a motion, which can be imprecise and cause strange behaviors such as objects passing through one another or getting stuck. Only relevant for fast moving dynamic bodies. </td>
<td> setCcdSweptSphereRadius(.5f)</td><td>Bullet does not use the full collision shape for continuous collision detection, instead it uses a “swept sphere” shape to approximate a motion, which can be imprecise and cause strange behaviors such as objects passing through one another or getting stuck. Only relevant for fast moving dynamic bodies. </td>
</tr>
</table></div>
<!-- EDIT26 TABLE [27710-29665] -->
<!-- EDIT26 TABLE [27769-29724] -->
<p>
<p><div> You can <code>setApplyPhysicsLocal(true)</code> for an object to make it move relatively to its local physics space. You would do that if you need a physics space that moves with a node (e.g. a spaceship with artificial gravity surrounded by zero-g space). By default, it's set to false, and all movement is relative to the world.
<li><div><strong>Multiple Objects Too Slow?</strong> Do not overuse PhysicsControls. Although PhysicsControls are put to ???sleep??? when they are not moving, creating a world solely out of dynamic physics objects will quickly bring you to the limits of your computer's capabilities. <br/>
<strong>Solution:</strong> Improve performance by replacing some physical Spatials with non-physical Spatials. Use the non-physical ones for non-solid things for which you do not need to detect collisions ??? foliage, plants, effects, ghosts, all remote or unreachable objects.</div>
<li><div><strong>Multiple Objects Too Slow?</strong> Do not overuse PhysicsControls. Although PhysicsControls are put to “sleep” when they are not moving, creating a world solely out of dynamic physics objects will quickly bring you to the limits of your computer's capabilities. <br/>
<strong>Solution:</strong> Improve performance by replacing some physical Spatials with non-physical Spatials. Use the non-physical ones for non-solid things for which you do not need to detect collisions – foliage, plants, effects, ghosts, all remote or unreachable objects.</div>
</li>
</ul>
<ul>
@ -750,7 +734,7 @@ removeCollideWithGroup(COLLISION_GROUP_01)</td><td>Collision Groups are integer
</li>
</ul>
<ul>
<li><div><strong>Eject?</strong> If you have physical nodes jittering wildy and being ejected "for no apparent reason", it means you have created an impossible state ??? solid objects overlapping. This can happen when you position solid spatials too close to other solid spatials, e.g. when moving them with setLocalTranslation(). <br/>
<li><div><strong>Eject?</strong> If you have physical nodes jittering wildy and being ejected “for no apparent reason”, it means you have created an impossible state – solid objects overlapping. This can happen when you position solid spatials too close to other solid spatials, e.g. when moving them with setLocalTranslation(). <br/>
<strong>Solution:</strong> Use the debug mode to make CollisionShapes visible and verify that CollisionShapes do not overlap. <pre>bulletAppState.getPhysicsSpace().enableDebug(assetManager);</pre>
</div>
</li>
@ -765,15 +749,14 @@ removeCollideWithGroup(COLLISION_GROUP_01)</td><td>Collision Groups are integer
<strong>Solution:</strong> To specify how the game responds to collisions, you use <ahref="/com/jme3/gde/docs/jme3/advanced/physics_listeners.html">Physics Listeners</a>.</div>
@ -21,11 +21,10 @@ You can control physical objects (push them around) by applying physical forces
</div>
<!-- EDIT2 SECTION "Sample Code" [330-809] -->
<h2><a>PhysicsGhostObjects</a></h2>
<h2>PhysicsGhostObjects</h2>
<div>
<p>
Attach a com.jme3.bullet.control.GhostControl to any Spatial to turn it into a PhysicsGhostObject. Ghost objects automatically follow their spatial and detect collisions. The attached ghost itself is invisible and non-solid (!) and doesn't interfere with your game otherwise, it only passively reports collisions.
</p>
@ -34,7 +33,7 @@ You can leave the GhostControl non-solid and invisible and attach it to an (invi
</p>
<p>
The shape of the ghost depends on the CollisionShape that you gave the GhostControl. This means that the GhostControl's shape can be different from the RigidBodyControl's shape. For example, the non-solid ghost shape can be bigger than the solid shape of the Spatial (so you can "feel" ahead).
The shape of the ghost depends on the CollisionShape that you gave the GhostControl. This means that the GhostControl's shape can be different from the RigidBodyControl's shape. For example, the non-solid ghost shape can be bigger than the solid shape of the Spatial (so you can “feel” ahead).
</p>
<pre>GhostControl ghost = new GhostControl(
new BoxCollisionShape(new Vector3f(1,1,1))); // a box-shaped ghost
@ -46,9 +45,11 @@ node.addControl(ghost); // the ghost follows thi
The jBullet Physics implementation is stepped at a constant 60 physics ticks per second frame rate.
Applying forces or checking for overlaps only has an effect right at a physics update cycle, which is not every frame. If you do physics interactions at arbitrary spots in the simpleUpdate() loop, calls will be dropped at irregular intervals, because they happen out of cycle.
When you write game mechanics that apply forces, you must implement a tick listener (com.jme3.bullet.PhysicsTickListener) for it. The tick listener makes certain the forces are not dropped, but applied in time for the next physics tick.
</p>
@ -91,11 +90,10 @@ When your game mechanics however just poll the current state (e.g. getPhysicsLoc
</div>
<!-- EDIT6 SECTION "When (Not) to Use Tick Listener?" [2980-3836] -->
<h3><a>How to Listen to Physics Ticks</a></h3>
<h3>How to Listen to Physics Ticks</h3>
<div>
<p>
Here's is the declaration of an examplary Physics Control that listens to ticks. (The example shows a RigidBodyControl, but it can also be GhostControl.)
</p>
<pre>public class MyCustomControl
@ -125,17 +123,16 @@ public void physicsTick(PhysicsSpace space, float tpf){
</div>
<!-- EDIT7 SECTION "How to Listen to Physics Ticks" [3837-4856] -->
<h3><a>When (Not) to Use Collision Listener</a></h3>
<h3>When (Not) to Use Collision Listener</h3>
<div>
<p>
If you do not implement the Collision Listener interface (com.jme3.bullet.collision.PhysicsCollisionListener), a collisions will just mean that physical forces between solid objects are applied automatically. If you just want "Balls rolling, bricks falling" you do not need a listener.
If you do not implement the Collision Listener interface (com.jme3.bullet.collision.PhysicsCollisionListener), a collisions will just mean that physical forces between solid objects are applied automatically. If you just want “Balls rolling, bricks falling” you do not need a listener.
</p>
<p>
@ -150,17 +147,16 @@ If however you want to respond to a collision event (com.jme3.bullet.collision.P
</li>
<li><div> Playing a sound (e.g. explosion, ouch)</div>
</li>
<li><div>??? and countless more, depending on your game</div>
<li><div>… and countless more, depending on your game</div>
</li>
</ul>
</div>
<!-- EDIT9 SECTION "When (Not) to Use Collision Listener" [4897-5699] -->
<h3><a>How to Listen to Collisions</a></h3>
<h3>How to Listen to Collisions</h3>
<div>
<p>
You need to add the PhysicsCollisionListener to the physics space before collisions will be listened for. Here's an example of a Physics Control that uses a collision listener. (The example shows a RigidBodyControl, but it can also be GhostControl.)
</p>
<pre>public class MyCustomControl extends RigidBodyControl
@ -188,24 +184,24 @@ After you identify the colliding nodes, specify the action to trigger when this
}</pre>
<p>
<p><div>Note that after the collision() method ends, the PhysicsCollisionEvent is cleared. You must get all objects and values you need within the collision() method.
</div></p>
</p>
</div>
<!-- EDIT10 SECTION "How to Listen to Collisions" [5700-7311] -->
<h3><a>Reading Details From a PhysicsCollisionEvent</a></h3>
<h3>Reading Details From a PhysicsCollisionEvent</h3>
<div>
<p>
The PhysicsCollisionEvent <code>event</code> gives you access to detailed information about the collision. You already know the event objects can identify which nodes collided, but it even knows how hard they collided:
</p>
<div><table>
<thead>
<tr>
<th>Method </th><th>Purpose</th>
</tr>
</thead>
<tr>
<td> getObjectA() <br/>
getObjectB() </td><td> The two participants in the collision. You cannot know in advance whether some node will be recorded as A or B, you always have to consider both cases. </td>
@ -233,11 +229,10 @@ Note that after the collision method has been called the object is not valid any
</div>
<!-- EDIT11 SECTION "Reading Details From a PhysicsCollisionEvent" [7312-8416] -->
<h3><a>Collision Groups</a></h3>
<h3>Collision Groups</h3>
<div>
<p>
You can improve performance by resricting the number of tests that collision detection has to perform. If you have a case where you are only interested in collisions between certain objects but not others, you can assign sets of physical obejcts to different collision groups.
</p>
@ -246,14 +241,11 @@ For example, for a click-to-select, you only care if the selection ray collides
<h1><a>Rendering Water as Post-Process Effect</a></h1>
<h1>Rendering Water as Post-Process Effect</h1>
<div>
<p>
The awesome SeaMonkey WaterFilter is highly configurable. It can render any type of water and also simulates the underwater part of the effect, including light effects called caustics. The effect is based on <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://www.gamedev.net/page/reference/index.html/_//feature/fprogramming/rendering-water-as-a-post-process-effect-r2642"><paramname="text"value="<html><u>Wojciech Toman???s Rendering Water as a Post-process Effect</u></html>"><paramname="textColor"value="blue"></object> published on gamedev.net. Here's a video:
The awesome SeaMonkey WaterFilter is highly configurable. It can render any type of water and also simulates the underwater part of the effect, including light effects called caustics. The effect is based on <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://www.gamedev.net/page/reference/index.html/_//feature/fprogramming/rendering-water-as-a-post-process-effect-r2642"><paramname="text"value="<html><u>Wojciech Toman’s Rendering Water as a Post-process Effect</u></html>"><paramname="textColor"value="blue"></object> published on gamedev.net. Here's a video:
</p>
<p>
@ -18,16 +17,15 @@ The awesome SeaMonkey WaterFilter is highly configurable. It can render any type
</div>
<!-- EDIT1 SECTION "Rendering Water as Post-Process Effect" [1-855] -->
<h2><a>The Theory</a></h2>
<h2>The Theory</h2>
<div>
<p>
The effect is part of a deferred rendering process, taking advantage of the pre-computed position buffer and back buffer (a texture representing the screen???s pixels position in view space, and a texture of the rendered scene).
The effect is part of a deferred rendering process, taking advantage of the pre-computed position buffer and back buffer (a texture representing the screen’s pixels position in view space, and a texture of the rendered scene).
</p>
<p>
After some calculation, this allows to reconstruct the position in world space for each pixel on the screen. "If a pixel is under a given water height, let???s render it as a blue pixel!" Blue pixel? Not exactly, we want waves, we want ripples, we want foam, we want reflection and refraction.
After some calculation, this allows to reconstruct the position in world space for each pixel on the screen. “If a pixel is under a given water height, let’s render it as a blue pixel!” Blue pixel? Not exactly, we want waves, we want ripples, we want foam, we want reflection and refraction.
</p>
<p>
@ -36,11 +34,10 @@ The GameDev.net article describes how those effects are achieved, but the main i
</div>
<!-- EDIT2 SECTION "The Theory" [856-1971] -->
<h2><a>How Did We Implement it in jME3?</a></h2>
<h2>How Did We Implement it in jME3?</h2>
<div>
<p>
jME3 default behavior is to use a forward rendering process, so there is no position buffer rendered that we can take advantage of. But while rendering the main scene to a frame buffer in the FilterPostPorcessor, we can write the hardware depth buffer to a texture, with nearly no additional cost.
</p>
@ -49,22 +46,20 @@ There are several ways of reconstructing the world space position of a pixel fro
</p>
<p>
Now we have the rendered scene in a texture, and we can reconstruct the position in world space of each pixel. We???re good to go!
Now we have the rendered scene in a texture, and we can reconstruct the position in world space of each pixel. We’re good to go!
</p>
<p>
??? Nehon
– Nehon
</p>
</div>
<!-- EDIT3 SECTION "How Did We Implement it in jME3?" [1972-2707] -->
@ -77,11 +72,10 @@ There are two test cases in the jME3 repository:
</div>
<!-- EDIT4 SECTION "Sample Code" [2708-3399] -->
<h3><a>Using the Water Filter</a></h3>
<h3>Using the Water Filter</h3>
<div>
<p>
In the <code>simpleInitApp()</code> method, you attach your scene to the rootNode, typically a terrain with a sky. Remember to add a directional light, since the water relies on the light direction vector. The WaterFilter constructor expects a node with the scene attached that should be reflected in the water, and vector information from the light source's direction.
</p>
@ -110,11 +104,10 @@ Usually you make the water reflect everything attached to the rootNode. But you
</div>
<!-- EDIT5 SECTION "Using the Water Filter" [3400-4704] -->
<h3><a>Optional: Waves</a></h3>
<h3>Optional: Waves</h3>
<div>
<p>
If you want waves, set the water height in the update loop. We reuse the initialWaterHeight variable, and repeatedly reset the waterHeight value according to time. This causes the waves.
</p>
<pre>private float time = 0.0f;
@ -130,22 +123,22 @@ public void simpleUpdate(float tpf) {
All these effects are optional. Every setter also has a getter.
</p>
<div><table>
<thead>
<tr>
<th> Water method example</th><th>Effects: Waves </th><th>Default</th>
</tr>
</thead>
<tr>
<td>water.setWaterHeight(-6);</td><td>Use this waterheight method for causing waves.</td><td>0.0f</td>
</tr>
@ -163,11 +156,11 @@ All these effects are optional. Every setter also has a getter.
</tr>
<tr>
<td>water.setHeightTexture( (Texture2D) <br/>
manager.loadTexture("Textures/waveheight.png") )</td><td>This height map describes the shape of the waves</td><td>"Common/MatDefs/Water/Textures/heightmap.jpg"</td>
manager.loadTexture(“Textures/waveheight.png”) )</td><td>This height map describes the shape of the waves</td><td>“Common/MatDefs/Water/Textures/heightmap.jpg”</td>
</tr>
<tr>
<td>water.setNormalTexture( (Texture2D) <br/>
manager.loadTexture("Textures/wavenormals.png") )</td><td>This normal map describes the shape of the waves</td><td>"Common/MatDefs/Water/Textures/gradient_map.jpg"</td>
manager.loadTexture(“Textures/wavenormals.png”) )</td><td>This normal map describes the shape of the waves</td><td>“Common/MatDefs/Water/Textures/gradient_map.jpg”</td>
</tr>
<tr>
<td>water.setUseRipples(false);</td><td>Switches the ripples effect on or off.</td><td>true</td>
@ -177,9 +170,11 @@ manager.loadTexture("Textures/wavenormals.png") )</td><td>This normal
</tr>
</table></div>
<!-- EDIT8 TABLE [5396-6560] --><div><table>
<thead>
<tr>
<th> Water method example</th><th> Effects: Color</th><th>Default</th>
</tr>
</thead>
<tr>
<td>water.setLightDirection(new Vector3f(-0.37f,-0.50f,-0.78f))</td><td>Usually you set this to the same as the light source's direction. Use this to set the light direction if the sun is moving.</td><td>Value given to WaterFilter() constructor.</td>
<td>water.setWaterTransparency(0.2f);</td><td>Sets how fast colors fade out. use this to control how clear (e.g. 0.05f) or muddy (0.2f) water is.</td><td> 0.1f </td>
</tr>
<tr>
<td>water.setColorExtinction(new Vector3f(10f,20f,30f));</td><td>Sets At what depth the refraction color extincts. The three values are RGB (red, green, blue) in this order. Play with these parameters to "muddy" the water.</td><td>Vector3f(5f,20f,30f)</td>
<td>water.setColorExtinction(new Vector3f(10f,20f,30f));</td><td>Sets At what depth the refraction color extincts. The three values are RGB (red, green, blue) in this order. Play with these parameters to “muddy” the water.</td><td>Vector3f(5f,20f,30f)</td>
</tr>
</table></div>
<!-- EDIT9 TABLE [6562-7568] --><div><table>
<thead>
<tr>
<th> Water method example</th><th> Effects: Shore</th><th>Default</th>
</tr>
</thead>
<tr>
<td>water.setCenter(Vector3f.ZERO); <br/>
water.setRadius(260);</td><td>Limit the water filter to a semisphere with the given center and radius. Use this for lakes and smaller bodies of water. Skip this for oceans.</td><td>unused</td>
@ -217,9 +214,11 @@ water.setRadius(260);</td><td>Limit the water filter to a semisphere with the gi
</tr>
</table></div>
<!-- EDIT10 TABLE [7570-8068] --><div><table>
<thead>
<tr>
<th> Water method example</th><th> Effects: Foam</th><th>Default</th>
</tr>
</thead>
<tr>
<td>water.setUseFoam(false);</td><td>Switches the white foam on or off</td><td>true</td>
</tr>
@ -231,13 +230,15 @@ water.setRadius(260);</td><td>Limit the water filter to a semisphere with the gi
</tr>
<tr>
<td>water.setFoamTexture( (Texture2D) <br/>
manager.loadTexture("Textures/foam.png") )</td><td>This foam texture will be used with WrapMode.Repeat</td><td>"Common/MatDefs/Water/Textures/foam.jpg"</td>
manager.loadTexture(“Textures/foam.png”) )</td><td>This foam texture will be used with WrapMode.Repeat</td><td>“Common/MatDefs/Water/Textures/foam.jpg”</td>
</tr>
</table></div>
<!-- EDIT11 TABLE [8070-8715] --><div><table>
<thead>
<tr>
<th> Water method example</th><th> Effects: Light</th><th>Default</th>
</tr>
</thead>
<tr>
<td>water.setSunScale(1f);</td><td>Sets how big the sun should appear in the light's specular effect on the water.</td><td>3.0f</td>
</tr>
@ -263,11 +264,10 @@ manager.loadTexture("Textures/foam.png") )</td><td>This foam texture w
<!-- EDIT12 TABLE [8717-9632] -->
</div>
<!-- EDIT7 SECTION "Optional: Water Wave and Color Effects" [5230-9634] -->
<h3><a>Sound Effects</a></h3>
<h3>Sound Effects</h3>
<div>
<p>
You should also add audio nodes with water sounds to complete the effect.
</p>
<pre>AudioNode waves = new AudioNode(assetManager, "Sounds/Environment/Ocean Waves.ogg", false);
The jMonkeyEngine3 has built-in support for <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://jbullet.advel.cz"><paramname="text"value="<html><u>jBullet physics</u></html>"><paramname="textColor"value="blue"></object> via the <code>com.jme3.bullet</code> package. Physics are not only responsible for handing collisions, but they also make <ahref="/com/jme3/gde/docs/jme3/advanced/hinges_and_joints.html">hinges and joints</a> possible. One special example of physical joints are ragdoll physics, shown here.
</p>
@ -13,18 +12,18 @@ The jMonkeyEngine3 has built-in support for <object classid="java:org.netbeans.m
</div>
<!-- EDIT1 SECTION "Ragdoll Physics" [1-385] -->
<h2><a>Sample Code</a></h2>
<h2>Sample Code</h2>
<div>
<ul>
<li><div><objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/bullet/TestRagDoll.java"><paramname="text"value="<html><u>TestRagDoll.java</u></html>"><paramname="textColor"value="blue"></object> (Tip: Click to pull the ragdoll up)</div>
</li>
<li><div><objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/bullet/TestBoneRagdoll.java"><paramname="text"value="<html><u>TestBoneRagdoll.java</u></html>"><paramname="textColor"value="blue"></object>??? This ragdoll replaces a rigged model of a character in the moment it is "shot" to simulate a collapsing person. (Also note DoF of the limbs.)</div>
<li><div><objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/bullet/TestBoneRagdoll.java"><paramname="text"value="<html><u>TestBoneRagdoll.java</u></html>"><paramname="textColor"value="blue"></object>– This ragdoll replaces a rigged model of a character in the moment it is “shot” to simulate a collapsing person. (Also note DoF of the limbs.)</div>
</li>
</ul>
</div>
<!-- EDIT2 SECTION "Sample Code" [386-867] -->
<h2><a>Preparing the Physics Game</a></h2>
<h2>Preparing the Physics Game</h2>
<div>
<ol>
<li><div> Create a SimpleApplication with a <ahref="/com/jme3/gde/docs/jme3/advanced/physics.html">BulletAppState</a></div>
@ -39,21 +38,19 @@ The jMonkeyEngine3 has built-in support for <object classid="java:org.netbeans.m
</div>
<!-- EDIT3 SECTION "Preparing the Physics Game" [868-1106] -->
<h2><a>Creating the Ragdoll</a></h2>
<h2>Creating the Ragdoll</h2>
<div>
<p>
A ragdoll is a simple "person" (dummy) that you build out of cylinder collision shapes. The ragdoll has 11 limbs: 1 for shoulders, 1 for the body, 1 for hips; plus 2 arms and 2 legs that are made up of two limbs each. In your game, you will likely replace the cylinders with your own (better looking) limb models. In this example here we just use simple cylinders.
A ragdoll is a simple “person” (dummy) that you build out of cylinder collision shapes. The ragdoll has 11 limbs: 1 for shoulders, 1 for the body, 1 for hips; plus 2 arms and 2 legs that are made up of two limbs each. In your game, you will likely replace the cylinders with your own (better looking) limb models. In this example here we just use simple cylinders.
</p>
</div>
<!-- EDIT4 SECTION "Creating the Ragdoll" [1107-1506] -->
<h3><a>Limbs</a></h3>
<h3>Limbs</h3>
<div>
<p>
Since you're just creating the ragdoll for this example, all the limbs have the same shape, and you can write a simple helper method to create them. The function returns a PhysicsControl with CollisionShape with the width, height, location, and rotation (vertical or horizontal) that you specify. You choose a CapsuleCollisionShape (a cylinder with rounded top and bottom) so the limbs collide smoothly against one another.
Node lLegR = createLimb(0.2f, 0.5f, new Vector3f( 0.25f,-2.2f, 0), false);</pre>
<p>
You now have the outline of a person. But if you ran the application now, the individual limbs would fall down independently of one another ??? the ragdoll is still lacking joints.
You now have the outline of a person. But if you ran the application now, the individual limbs would fall down independently of one another – the ragdoll is still lacking joints.
</p>
</div>
<!-- EDIT5 SECTION "Limbs" [1507-3921] -->
<h3><a>Joints</a></h3>
<h3>Joints</h3>
<div>
<p>
As before, you write a small helper method. This time its purpose is to quickly join two limbs A and B at the connection point that we specify.
</p>
<ul>
@ -123,7 +119,6 @@ As before, you write a small helper method. This time its purpose is to quickly
</ul>
<p>
Use the helper method to connect all limbs with joints where they belong, at one end of the limb.
</p>
<pre>join(body, shoulders, new Vector3f( 0.00f, 1.4f, 0));
@ -143,11 +138,10 @@ Now the ragdoll is connected. If you ran the app now, the doll would collapse, b
</div>
<!-- EDIT6 SECTION "Joints" [3922-5767] -->
<h3><a>Attaching Everything to the Scene</a></h3>
<h3>Attaching Everything to the Scene</h3>
<div>
<p>
We create one (non-physical) Node named ragDoll, and attach all other nodes to it.
We can use the action to pick the doll up and put it back on its feet, or what ever. Read more about <ahref="/com/jme3/gde/docs/jme3/advanced/physics#forcesmoving_physical_objects.html">Forces</a> here.
We can use the action to pick the doll up and put it back on its feet, or what ever. Read more about <ahref="/com/jme3/gde/docs/jme3/advanced/physics.html#forcesmoving_physical_objects">Forces</a> here.
Read the <ahref="/com/jme3/gde/docs/jme3/advanced/physics#responding_to_a_physicscollisionevent.html">Responding to a PhysicsCollisionEvent</a> chapter in the general physics documentation on how to detect collisions. You can detect collisions between limbs or between limbs and the floor, and trigger game events.
Read the <ahref="/com/jme3/gde/docs/jme3/advanced/physics.html#responding_to_a_physicscollisionevent">Responding to a PhysicsCollisionEvent</a> chapter in the general physics documentation on how to detect collisions. You can detect collisions between limbs or between limbs and the floor, and trigger game events.
If you experience weird behaviour in a ragdoll – such as exploding into pieces and then reassembling – check your collision shapes. Verify you did not position the limbs too close to one another when assmebling the ragdoll. You typically see physical nodes being ejected when their collision shapes intersect, which puts physics in an impossible state.
</p>
If you experience weird behaviour in a ragdoll ??? such as exploding into pieces and then reassembling ??? check your collision shapes. Verify you did not position the limbs too close to one another when assmebling the ragdoll. You typically see physical nodes being ejected when their collision shapes intersect, which puts physics in an impossible state.
When different people test your new game, you may get feedback that the game doesn't run on their hardware, or that some details don't look as expected. You need to detect which fetaures the user's hardware supports, and offer a replacement for non-supported features on olde hardware (or deactivate them automatically).
</p>
@ -11,7 +10,7 @@ When different people test your new game, you may get feedback that the game doe
You can read (and print) the capabilities of the user's graphic card using the <code>com.jme3.renderer.Caps</code> class:
This next example is lacking <code>NonPowerOfTwoTextures</code>, this tells you that this user's graphic card cannot handle textures with sizes that are not square powers of two (such as "128x128").
This next example is lacking <code>NonPowerOfTwoTextures</code>, this tells you that this user's graphic card cannot handle textures with sizes that are not square powers of two (such as “128×128”).
<!-- EDIT1 SECTION "Remote-Controlling the Camera" [1-45] -->
<h2><a>Positioning the Camera</a></h2>
<h2>Positioning the Camera</h2>
<div>
<p>
You can steer the camera using <ahref="/com/jme3/gde/docs/jme3/advanced/cinematics.html">Cinematics</a>:
</p>
<ol>
@ -19,14 +18,14 @@ You can steer the camera using <a href="/com/jme3/gde/docs/jme3/advanced/cinemat
</li>
<li><div> Position the camera node in its start location.</div>
</li>
<li><div> Use activateCamera() to give the control of the camera to this node. You now see the scene from this camera's point of view. For example to see through the camera node named "topView", 6 seconds after the start of the cinematic, you'd write <pre>cinematic.activateCamera(6, "topView");</pre>
<li><div> Use activateCamera() to give the control of the camera to this node. You now see the scene from this camera's point of view. For example to see through the camera node named “topView”, 6 seconds after the start of the cinematic, you'd write <pre>cinematic.activateCamera(6, "topView");</pre>
</div>
</li>
</ol>
</div>
<!-- EDIT2 SECTION "Positioning the Camera" [46-714] -->
<h3><a>Code Sample</a></h3>
<h3>Code Sample</h3>
<div>
<pre>flyCam.setEnabled(false);
Cinematic cinematic = new Cinematic(rootNode, 20);
If desired, attach the camNode to a MotionTrack to let it travel along waypoints. This is demonstrated in the <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/animation/TestCinematic.java"><paramname="text"value="<html><u>TestCameraMotionPath.java example</u></html>"><paramname="textColor"value="blue"></object>.
Spatials (that is Nodes and Geometries) can contain audio and light nodes, particle emitters, controls, and user data (player score, health, inventory, etc). For your game distribution, you must convert all original models to a faster binary format. You save individual Spatials as well as scenes using <code>com.jme3.export.binary.BinaryExporter</code>.
</p>
<p>
The jMonkeyEngine's binary file format is called <code>.j3o</code>. You can convert, view and edit .j3o files and their materials in the jMonkeyEngine <ahref="/com/jme3/gde/docs/sdk.html">SDK</a> and compose scenes (this does not include editing meshes). For the conversion, you can either use the BinaryExporters, or a context menu in the <acronymtitle="Software Development Kit">SDK</acronym>.
The jMonkeyEngine's binary file format is called <code>.j3o</code>. You can convert, view and edit .j3o files and their materials in the jMonkeyEngine <ahref="/com/jme3/gde/docs/sdk.html">SDK</a> and compose scenes (this does not include editing meshes). For the conversion, you can either use the BinaryExporters, or a context menu in the SDK.
</p>
<p>
<p><div>The jMonkeyEngine's serialization system is the <code>com.jme3.export.Savable</code> interface. JME3's BinaryExporter can write standard Java objects, JME3 objects, and primitive data types that are included in a <ahref="/com/jme3/gde/docs/jme3/advanced/spatial.html">spatial's user data</a>. If you use custom game data classes, see below how to make them "Savable".
<p><div>The jMonkeyEngine's serialization system is the <code>com.jme3.export.Savable</code> interface. JME3's BinaryExporter can write standard Java objects, JME3 objects, and primitive data types that are included in a <ahref="/com/jme3/gde/docs/jme3/advanced/spatial.html">spatial's user data</a>. If you use custom game data classes, see below how to make them “Savable”.
</div></p>
</p>
<p>
There is also a com.jme3.export.xml.XMLExporter and com.jme3.export.xml.XMLImporter that similarly converts jme3 spatials to an <acronymtitle="Extensible Markup Language">XML</acronym> format. But you wouldn't use that to load models at runtime (quite slow).
There is also a com.jme3.export.xml.XMLExporter and com.jme3.export.xml.XMLImporter that similarly converts jme3 spatials to an XML format. But you wouldn't use that to load models at runtime (quite slow).
</p>
</div>
<!-- EDIT1 SECTION "Saving and Loading Games (.j3o)" [1-1239] -->
@ -31,24 +30,23 @@ There is also a com.jme3.export.xml.XMLExporter and com.jme3.export.xml.XMLImpor
</div>
<!-- EDIT2 SECTION "Sample Code" [1240-1397] -->
<h2><a>Saving a Node</a></h2>
<h2>Saving a Node</h2>
<div>
<p>
The following example overrides <code>stop()</code> in SimpleApplication to save the rootNode to a file when the user quits the application. The saved rootNode is a normal .j3o binary file that you can open in the <ahref="/com/jme3/gde/docs/sdk.html">SDK</a>.
</p>
<p>
<p><div>Note that when you save a model that has textures, the references to those textures are stored as absolute paths, so when loading the j3o file again, the textures have to be accessible at the exact location (relative to the assetmanager root, by default the <code>assets</code> directory) they were loaded from. This is why the <acronymtitle="Software Development Kit">SDK</acronym> manages the conversion on the project level.
<p><div>Note that when you save a model that has textures, the references to those textures are stored as absolute paths, so when loading the j3o file again, the textures have to be accessible at the exact location (relative to the assetmanager root, by default the <code>assets</code> directory) they were loaded from. This is why the SDK manages the conversion on the project level.
</div></p>
</p>
<pre> /* This is called when the user quits the app. */
@ -59,16 +57,15 @@ The following example overrides <code>stop()</code> in SimpleApplication to save
</div>
<!-- EDIT3 SECTION "Saving a Node" [1398-2548] -->
<h2><a>Loading a Node</a></h2>
<h2>Loading a Node</h2>
<div>
<p>
The following example overrides <code>simpleInitApp()</code> in SimpleApplication to load <code>Models/MyModel.j3o</code> when the game is initialized.
@ -77,26 +74,24 @@ The following example overrides <code>simpleInitApp()</code> in SimpleApplicatio
</pre>
<p>
<p><div>Here you see why we save user data inside spatials ??? so it can be saved and loaded together with the .j3o file. If you have game data outside Spatials, you have to remember to save() and load(), and get() and set() it yourself.
<p><div>Here you see why we save user data inside spatials – so it can be saved and loaded together with the .j3o file. If you have game data outside Spatials, you have to remember to save() and load(), and get() and set() it yourself.
</div></p>
</p>
</div>
<!-- EDIT4 SECTION "Loading a Node" [2549-3302] -->
<h2><a>Custom Savable Class</a></h2>
<h2>Custom Savable Class</h2>
<div>
<p>
JME's BinaryExporter can write standard Java objects (String, ArrayList, buffers, etc), JME objects (Savables, such as Material), and primitive data types (int, float, etc). If you are using any custom class together with a Spatial, then the custom class must implement the <code>com.jme3.export.Savable</code> interface. There are two common cases where this is relevant:
</p>
<ul>
<li><div> The Spatial is carrying any <ahref="/com/jme3/gde/docs/jme3/advanced/custom_controls.html">Custom Controls</a>. <br/>
Example: You used something like <code>mySpatial.addControl(myControl);</code></div>
</li>
<li><div> The Spatial's user data can contain a custom Java object. <br/>
Example: You used something like <code>mySpatial.setUserData("inventory", myInventory);</code></div>
Example: You used something like <code>mySpatial.setUserData(“inventory”, myInventory);</code></div>
</li>
</ul>
@ -153,11 +148,11 @@ To make a custom class savable:
</li>
</ul>
</li>
<li><div> Add one line that <code>read???()</code>s the data to the JmeImport input capsule. </div>
<li><div> Add one line that <code>read…()</code>s the data to the JmeImport input capsule. </div>
<ul>
<li><div> On the left side of the assignment, specify the class field that you are restoring</div>
</li>
<li><div> On the right side, use the appropriate <code>capsule.read???()</code> method for the data type. Specify the String name of the variable (must be the same as you used in the <code>write() method</code>), and again specify a default value.</div>
<li><div> On the right side, use the appropriate <code>capsule.read…()</code> method for the data type. Specify the String name of the variable (must be the same as you used in the <code>write() method</code>), and again specify a default value.</div>
</li>
</ul>
</li>
@ -166,28 +161,14 @@ To make a custom class savable:
</ol>
<p>
<p><div>As with all serialization, remember that if you ever change data types in custom classes, the updated read() methods will no longer be able to read your old files. Also there has to be a constructor that takes no Parameters.
The default screenshot key is KeyInput.KEY_SYSRQ, alos known as "System Request / Print Screen" key. On Mac keyboards, this key does not exist, so on Mac <acronymtitle="Operating System">OS</acronym> you take screenshots using Command+Shift+3 (fullscreen) or Command+Shift+4 (windowed: press space to select a window and then click).
The default screenshot key is KeyInput.KEY_SYSRQ, alos known as “System Request / Print Screen” key. On Mac keyboards, this key does not exist, so on Mac <abbrtitle="Operating System">OS</abbr> you take screenshots using Command+Shift+3 (fullscreen) or Command+Shift+4 (windowed: press space to select a window and then click).