@ -13,23 +13,46 @@ Place audio files in the <code>assets/Sound/</code> directory of your project. j
</div>
<h2><a>Creating Audio Nodes</a></h2>
<h2><a>Creating Audio Nodes: Streamed or Buffered</a></h2>
<div>
<p>
The main class to look at is <code>com.jme3.audio.AudioNode</code>.
By default, a new audio node is buffered, i.e. JME loads the whole file into memory before playing:
</p>
<pre>AudioNode boom = new AudioNode(assetManager, "Sound/boom.wav");</pre>
<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. 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");</pre>
</div>
</li>
<li><div><strong>Streamed:</strong> If it is a long file, you stream the audio, that means, you load and play in parallel until the sound is done. You create a streamed sound by setting the boolean to true:<pre>AudioNode music = new AudioNode(assetManager, "Sound/music.wav", true);</pre>
</div>
</li>
</ul>
<p>
</div>
If it is a long file, you set the boolean to true to stream the audio.
<h2><a>Getting AudioNode Properties</a></h2>
<div>
<div><table>
<tr>
<th>AudioNode Method</th><th>Usage</th>
</tr>
<tr>
<td>getStatus()</td><td>Returns either Status.Playing, Status.Stopped, or Status.Paused. </td>
</tr>
<tr>
<td>getVolume()</td><td>Returns the volume. </td>
</tr>
<tr>
<td>getPitch()</td><td>Returns the pitch. </td>
</tr>
</table></div>
<!-- EDIT1 TABLE [1068-1240] -->
<p>
There are other obvious getters to poll the status of corresponding setters below.
</p>
<pre>AudioNode music = new AudioNode(assetManager, "Sound/music.wav", true);</pre>
</div>
@ -40,24 +63,22 @@ If it is a long file, you set the boolean to true to stream the audio.
<th>AudioNode Method</th><th>Usage</th>
</tr>
<tr>
<td>getStatus()</td><td>Returns either Status.Playing, Status.Stopped, or Status.Paused.</td>
</tr>
<tr>
<td>setVolume(1)</td><td>Sets the volume gain. 1 is the default volume, 2 is twice as loud, 0 is mute. </td>
<td>setVolume(1)</td><td>Sets the volume gain. 1 is the default volume, 2 is twice as loud, etc. 0 is silent/mute. </td>
</tr>
<tr>
<td>setPitch(1)</td><td>Makes the sound play in a higher or lower pitch. Default is 1.</td>
<td>setPitch(1)</td><td>Makes the sound play in a higher or lower pitch. Default is 1. 2 is twice as high, .5f is half as low. </td>
</tr>
</table></div>
<!-- EDIT1 TABLE [814-1088] --><div><table>
<!-- EDIT2 TABLE [1368-1616] --><div><table>
<tr>
<th>AudioNode Method</th><th>Usage</th>
</tr>
<tr>
<td>setLooping(false)</td><td>Configures the sound that, if it is played, it plays once and stops. This is the default.</td>
<td>setLooping(false)</td><td>Configures the sound so that, if it is played, it plays once and stops. This is the default.</td>
</tr>
<tr>
<td>setLooping(true)</td><td>Configures the sound that, if it is played, it plays repeats from the beginning, until stop() or pause() are called. Good for ambient background noises. </td>
<td>setLooping(true)</td><td>Configures the sound so that, if it is played, it plays repeats from the beginning, until stop() or pause() are called. Good for ambient background noises. <br/>
Does not work for streamed sounds! </td>
</tr>
<tr>
<td>setPositional(false) <br/>
@ -70,7 +91,7 @@ setDirectional(false)</td><td>All 3D effects switched off. This sound is global
<td>setMaxDistance(100f)</td><td>Maximum distance the sound can be heard, in world units. Default is 20.</td>
</tr>
</table></div>
<!-- EDIT2 TABLE [1090-1781] --><div><table>
<!-- EDIT3 TABLE [1618-2352] --><div><table>
<tr>
<th>AudioNode Method</th><th>Usage</th>
</tr>
@ -82,7 +103,7 @@ setLocalTranslation(…)</td><td>Activates 3D audio: The sound appears to come f
<td>setReverbEnabled(true)</td><td>A 3D echo effect that only makes sense to use with positional AudioNodes. The reverb effect is influenced by the environment that the audio renderer is in. See "Setting Environment Properties" below. </td>
</tr>
</table></div>
<!-- EDIT3 TABLE [1783-2255] --><div><table>
<!-- EDIT4 TABLE [2354-2826] --><div><table>
<tr>
<th>AudioNode Method</th><th>Usage</th>
</tr>
@ -95,7 +116,7 @@ setDirection(…) </td><td>Activates 3D audio: This sound can only be heard from
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>
<!-- EDIT4 TABLE [2257-2784] -->
<!-- EDIT5 TABLE [2828-3355] -->
</div>
<h2><a>Play, Pause, Stop</a></h2>
@ -164,7 +185,7 @@ Optionally, You can choose from the following environmental presets from <code>c
You can find more info about OpenAL and its advanced 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>
You can find more info about OpenAL and its advanced 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>. 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>)
@ -90,12 +90,17 @@ If you want to create a Control that also extends an existing class, then create
</p>
<pre>public class ControlledThing extends MyThing implements MyControl {
protected Spatial spatial;
protected boolean enabled = true;
public ControlledThing(){}
public ControlledThing(int x){
public ControlledThing(){} // empty serialization constructor
public ControlledThing(int x){ // custom constructor
super(x);
}
@Override
public void update(float tpf){
if (enabled && spatial != null){
@ -103,30 +108,36 @@ If you want to create a Control that also extends an existing class, then create
// Write custom code to control the spatial here!
}
}
@Override
public void render(RenderManager rm, ViewPort vp){
// optional, e.g. to display a debug shape
// optional for advanced users, e.g. to display a debug shape
}
@Override
public Control cloneForSpatial(Spatial spatial){
ControlledThing control = new ControlledThing(y);
// ... // set custom properties
// set custom properties
spatial.setControl(control);
return control;
}
@Override
public void setEnabled(boolean enabled){
this.enabled = enabled;
// ...
}
@Override
public boolean isEnabled(){
return enabled;
}
@Override
public void setSomething(int z){
// your custom method ...
// You can add custom methods ...
}
@Override
public void write(JmeExporter ex) throws IOException {
super.write(ex);
@ -151,6 +162,7 @@ If you want to create a Control that also extends an existing class, then create
<div>
<p>
This class can be found under <code>com.jme3.scene.control.AbstractControl</code>.
</p>
<ul>
@ -163,43 +175,59 @@ This class can be found under <code>com.jme3.scene.control.AbstractControl</code
</ul>
<p>
Usage: Your custom subclass implements the three methods <code>controlUpdate()</code>, <code>controlRender()</code>, and <code>cloneForSpatial()</code> as shown here:
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 {
private Thing thing; // some custom class of yours
private Thing thing; // some custom field of yours
public MyControl(){} // empty serialization constructor
public MyControl(thing){ // some custom constructor
super(spatial);
this.thing = thing;
// Note: you can not access spatial here
}
@Override
public void setSpatial(Spatial spatial){
super.setSpatial(spatial);
// optional init method
// you can get and set user data in the spatial here
@ -146,18 +146,23 @@ You create the PhysicsHingeJoint after you have created the nodes that are to be
joint=new HingeJoint(hookNode.getControl(RigidBodyControl.class), // A
pendulumNode.getControl(RigidBodyControl.class), // B
new Vector3f(0f, 0f, 0f), // pivot point of A
new Vector3f(0f,-1f, 0f), // pivot point of B
new Vector3f(0f, 0f, 0f), // pivot point local to A
new Vector3f(0f, 1f, 0f), // pivot point local to B
Vector3f.UNIT_Z, // DoF Axis of A (Z axis)
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>
<p>
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>
<li><div> Vector3f pivot A and pivot B – coordinates of the two attachment points</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>
@ -22,11 +22,11 @@ If you are looking for info on how to respond to physics events, read about <a h
<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.
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 entities. 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>
<p>
A bullet physics space can be created with a BulletAppState. The updating and syncing of the actual physics objects happens in the following way:
A bullet physics space can be created with a BulletAppState. The updating and syncing of the actual physics entities happens in the following way:
</p>
<p>
@ -138,49 +138,51 @@ Before you can create a Physics Control, you must create a Collision Shape from
</p>
<div><table>
<tr>
<th> Shape </th><th>Purpose</th>
<th> Shape </th><th>Usage </th><th> Examples</th>
</tr>
<tr>
<td> BoxCollisionShape </td><td> Box shaped objects such as bricks, crates, simple obstacles. Does not roll.</td>
<td> BoxCollisionShape </td><td> Box shaped entities Does not roll.</td><td> Bricks, crates, simple oblong entities. </td>
</tr>
<tr>
<td> SphereCollisionShape </td><td> Spherical objects such as balls. Can roll. </td>
<td> CylinderCollisionShape </td><td> Tube-shaped pillars, disc-shaped wheels. Can roll on one side. </td>
<td> CylinderCollisionShape </td><td> Tube-shaped and disc-shaped entities. Can roll on one side. </td><td> Pillars, wheels. </td>
</tr>
<tr>
<td> CapsuleCollisionShape </td><td> A compound of a cylinder plus two spheres at the top and bottom. Rotated upright, this shape is optimal for CharacterControls: A cylinder-shaped body does not get stuck at corners and vertical obstacles; the rounded top and bottom do not get stuck on stair steps and ground obstacles. Is locked to stay upright, does not roll. </td>
<td> CapsuleCollisionShape </td><td> A compound of a cylinder plus two spheres at the top and bottom. Is locked to stay upright, does not roll. </td><td> Optimized for CharacterControls: A cylinder-shaped body does not get stuck at corners and vertical obstacles; the rounded top and bottom do not get stuck on stair steps and ground obstacles. </td>
</tr>
<tr>
<td> CompoundCollisionShape </td><td> A CompoundCollisionShape allows custom combinations of box/sphere/cylinder shapes to form another more complex shape. </td>
<td> CompoundCollisionShape </td><td> A CompoundCollisionShape allows custom combinations of box/sphere/cylinder shapes to form another more complex shape. </td><td> Complex shapes. </td>
</tr>
<tr>
<td> MeshCollisionShape </td><td> A free-form mesh-accurate shape that wraps itself around a mesh. <br/>
<strong>Limitations:</strong> Only non-mesh collision shapes (sphere, box, cylinder, compound) can collide with mesh-accurate collision shapes. The Mesh Collision Shape only works for static obstacles, e.g. for a game level model. </td>
<td> MeshCollisionShape </td><td> A free-form mesh-accurate shape that wraps itself around a static entity. <br/>
<strong>Limitations:</strong> Only non-mesh collision shapes (sphere, box, cylinder, compound) can collide with mesh-accurate collision shapes. Only works for static obstacles. </td><td> A whole static game level model. </td>
</tr>
<tr>
<td> GImpactCollisionShape </td><td> This free-form Mesh Collision Shape can be used for moving objects. Uses <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://gimpact.sourceforge.net/"><paramname="text"value="<html><u>http://gimpact.sourceforge.net/</u></html>"><paramname="textColor"value="blue"></object>. <strong>Limitations:</strong> CPU intensive, use sparingly! We recommend using HullCollisionShapes or CompoundShapes made of simple shapes if you need improved performance. </td>
<td> GImpactCollisionShape </td><td> This free-form Mesh Collision Shape that wraps itself around dynamically moving entities. Uses <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://gimpact.sourceforge.net/"><paramname="text"value="<html><u>http://gimpact.sourceforge.net/</u></html>"><paramname="textColor"value="blue"></object>. <br/>
<strong>Limitations:</strong> CPU intensive, use sparingly! We recommend using HullCollisionShapes or CompoundShapes made of simple shapes if you need improved performance. </td><td> Physics simulation of a complex object. </td>
</tr>
<tr>
<td> HeightFieldCollisionShape </td><td> Optimized Mesh Collision Shape for static terrains. This shape is much faster than a other Free-Form Mesh Shapes. Requires heightmap data.</td>
<td> HeightFieldCollisionShape </td><td> Optimized Mesh Collision Shape for static terrains. This shape is much faster than a other Free-Form Mesh Shapes. Requires heightmap data.</td><td>Optimized for terrains.</td>
</tr>
<tr>
<td> HullCollisionShape </td><td> A collision shape that is based on a mesh but is a simplified convex version. </td>
<td> HullCollisionShape </td><td> A collision shape that is based on a mesh but is a simplified convex version. </td><td> …</td>
</tr>
<tr>
<td> SimplexCollisionShape </td><td>A physical point, line, triangle, or quad Collision Shape, defined by one to four points.</td>
<td> SimplexCollisionShape </td><td>A physical point, line, triangle, or quad Collision Shape, defined by one to four points.</td><td>Guardrails</td>
</tr>
<tr>
<td> PlaneCollisionShape </td><td> A 2D plane that can be used as flat solid floor or wall. </td>
<td> PlaneCollisionShape </td><td> A 2D plane </td><td> Flat solid floor or wall. </td>
</tr>
</table></div>
<!-- EDIT1 TABLE [3692-5610] -->
<!-- EDIT1 TABLE [3694-5743] -->
<p>
<strong>Tip:</strong> Pick the right shape for the mesh for what you want to do: If you give a box a sphere collision shape, it will roll; if you give a ball a box collision shape, it will sit on a slope. Make collision shapes visible by adding the following line after the bulletAppState initialization:
<p><div>Pick the right shape for the mesh for what you want to do: If you give a box a sphere collision shape, it will roll; if you give a ball a box collision shape, it will sit on a slope. Make collision shapes visible by adding the following line after the bulletAppState initialization: <br/>
Let's look at examples of how to use the CollisionShape constructor:
@ -193,7 +195,7 @@ Let's look at examples of how to use the CollisionShape constructor:
<p>
MeshCompoundShape and MeshCollisionShape are both mesh-accurate and are intended for immobile scene objects, such as terrains, buildings, or whole shooter levels. Limitation: Only collisions of non-mesh-accurate shapes (sphere, box, etc) shapes can be detected against mesh-accurate shapes.
MeshCompoundShape and MeshCollisionShape are both mesh-accurate and are intended for immobile scene entities, such as terrains, buildings, or whole shooter levels. Limitation: Only collisions of non-mesh-accurate shapes (sphere, box, etc) shapes can be detected against mesh-accurate shapes.
</p>
<pre>CompoundCollisionShape myComplexShape =
@ -218,7 +220,7 @@ SphereCollisionShape, BoxCollisionShape, CapsuleCollisionShape are also not mesh
<p>
BulletPhysics are available in jME3 through Bullet Physics Controls from the com.jme3.bullet.control package. PhysicsControls 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. These Control classes directly extend Bullet Physics Objects.
BulletPhysics are available in jME3 through Bullet Physics Controls from the com.jme3.bullet.control package. PhysicsControls 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. jME's PhysicsControl classes directly extend Bullet Physics objects.
</p>
<div><table>
@ -226,23 +228,23 @@ BulletPhysics are available in jME3 through Bullet Physics Controls from the com
<th>Physics Control</th><th>Purpose</th>
</tr>
<tr>
<td>RigidBodyControl</td><td>Use for physical objects in the scene, e.g. projectiles and obstacles – things that are freely affected by physical forces, be it by collision or falling.</td>
<td>RigidBodyControl</td><td>Use for dynamic physical entities in the scene – things that are freely affected by physical forces such as collisions, forces, or changing gravity. For example: Impacting projectiles, moving obstacles like crates, rolling and bouncing balls, space ships…</td>
</tr>
<tr>
<td>CharacterControl</td><td>Use for characters (persons, animals) that stand upright, orthogonally to the X/Z plane. When directional forces are applied to a CharacterControl'ed Spatial, it does not tip over (as a RigidBodyControl'ed Spatial would), but it moves upright (as a walking character would).</td>
<td>CharacterControl</td><td>Use for upright characters (persons, animals) that moves and stands orthogonally to the X/Z plane. It is not affected by directional forces or gravity and it does not fall over (as a RigidBodyControl'ed spatial would), a CharacterControl's spatial is permanently locked locked upright (as a walking character would). </td>
</tr>
<tr>
<td>GhostControl</td><td>A GhostControl is a PhysicsControl that detects overlaps with other physical objects. A GhostControl is <em>non-solid</em> and moves with the Spatial it is attached to. Use this for game elements that do not have a visible solid Geometry: Aggro radius, motion detectors, photoelectric sensors, radioactive areas, life-draining ghosts, etc. </td>
<td>GhostControl</td><td>Use for collision and intersection detection between physical entities. A GhostControl is <em>non-solid</em> and invisible, and it moves with the Spatial it is attached to. Use this for interactive game elements that do not have a visible solid Geometry: A monster's "aggro radius", motion detectors, photoelectric alarm sensors, poisonous or radioactive perimeters, life-draining ghosts, etc. </td>
<td>RagDollControl</td><td>Use for collapsing, flailing, or loosely falling characters or with a<ahref="/com/jme3/gde/core/docs/jme3/advanced/ragdoll.html">Ragdoll</a> (or puppet-on-strings) behaviour.</td>
<strong>Tip:</strong> Spheres and Boxes can fall back to the correct default Collision Shape if you do not specify a Collision Shape in the RigidBodyControl constructor. For example, the following creates a box with the correct Box Collision Shape:
<p><div>Spheres and Boxes can fall back to the correct default CollisionShape if you do not specify a CollisionShape in the RigidBodyControl constructor.
</div></p>
</p>
<p>
For example, the following creates a box with the correct Box Collision Shape:
The Physics Space is an object in BulletAppState that is like a rootNode for Physics Controls.
The Physics Space is an object in BulletAppState that is like a rootNode for Physics Controls. It manages global settings.
</p>
<ol>
<li><div> You can specify parameters such as gravity and accuracy.<pre>bulletAppState.getPhysicsSpace().setGravity(new Vector3f(0f,-1f,0f));
<td> setGravity(new Vector3f(0f,-10f,0f)) </td><td>You can change the gravity of individual physics entities after they were added to the physics space. Gravity is a vector pointing towards the center of gravity. The longer the vector, the stronger is gravity. If gravity is the same absolute direction for all entities, set this vector globally on the physics space. If the center of gravity is relative (e.g. towards a planet's core or towards a black hole) then you have to use this method to adjust the vectors of all entities at each tick of the update loop.</td>
</tr>
<tr>
<td> setMass(1f) </td><td> Sets the mass. Dynamic objects have masses > 0.0f. <br/>
Static immobile obstacles (including buildings and terrains) have mass 0.0f. </td>
<td> setFriction(1f) </td><td> Friction. Ice and slides have low friction, the are slippery. Soil, concrete and rock have high friction. </td>
</tr>
<tr>
<td> setPhysicsLocation()</td><td>Positions the object. Do not use setLocalTranslation().</td>
<td> setMass(1f) </td><td> Sets the mass. Dynamic entities have masses > 0.0f. Heavy dynamic entities need more force to be moved and light ones move with small amounts of force. <br/>
Static immobile entities (obstacles, including buildings and terrains) must have mass = 0.0f. </td>
</tr>
<tr>
<td> setPhysicsRotation()</td><td>Rotates the object. Do not use setLocalRotate().</td>
<td> setPhysicsLocation()</td><td>Positions the entity. Do not use setLocalTranslation() for physical entities.. Important: Make certain not to make CollisionShapes overlap when positioning them (Use the debug mode to check the shapes). </td>
</tr>
<tr>
<td> setRestitution(0.0f) </td><td> How bouncy the object is. For a rubber object set this > 0.0f. This setting has an impact on performance. </td>
<td> setPhysicsRotation()</td><td>Rotates the entity. Do not use setLocalRotate() for physical entities.</td>
</tr>
<tr>
<td> setKinematic(true) </td><td> A kinematic Spatial is not affected by gravity, but it is solid and affects other physics objects. It has a mass its position is updated from the spatials translation. You can attach joints to it. </td>
<td> setRestitution(0.0f) </td><td> How bouncy an entity is, normally 0.0f. <br/>
For a bouncy, such as rubber balls, set this > 0.0f. This setting has an impact on performance, so use it sparingly. </td>
</tr>
<tr>
<td> setGravity(new Vector3f(0f,-1f,0f)) </td><td> You can change the gravity of a physics object after it was added to the physics space. </td>
<td> setKinematic(true) </td><td> A kinematic RigidBodyControl'ed entity is not affected by gravity or other forces! You write translation and rotation code in the update loop to describe the motion of physical entities. A kinematic has a mass and is solid (e.g. characters can stand on it), this means a kinematic affects other physics entities that bump into it (e.g. pushes them away). You also can attach <ahref="/com/jme3/gde/core/docs/jme3/advanced/joints_and_hinges.html">joints and hinges</a> to it ("air hook"). The position of a kinematic RigidBodyControl is updated depending on its spatial's translation. <br/>
By default, PhysicsControls are not kinematic.</td>
</tr>
<tr>
<td> setCcdMotionThreshold(0.1f) </td><td> The amount of motion in 1 physics tick to trigger the continuous motion detection. </td>
<td> setCcdMotionThreshold(0.1f) </td><td> The amount of motion in 1 physics tick to trigger the continuous motion detection. Rarely used, but necessary if you need to fiddle with details. </td>
<td> setJumpSpeed(1f) </td><td> Jump speed (movement along up axis) </td>
</tr>
<tr>
<td> setMaxSlope(1.5f) </td><td>How steep the slopes are that the character can still climb.</td>
<td> setFallSpeed(1f)</td><td>Fall speed (movement along negative up axis)</td>
</tr>
<tr>
<td> setUpAxis(1)</td><td>0 = X axis , 1 = Y axis , 2 = Z axis. E.g. for characters and vehicle, up is usually along the the Y axis.</td>
<td> setMaxSlope(1.5f) </td><td>How steep the slopes and steps are that the character can climb without considering them an obstacle. Higher obstacles need to be jumped. In world units. </td>
</tr>
<tr>
<td> setGravity(1f) </td><td>You can change the Gravity of a physics object after it was added to the physics space</td>
<td> setGravity(1f) </td><td>The intensity of gravity for this CharacterControl'ed entity. To change the direction of gravity for a character, modify the up axis.</td>
</tr>
</table></div>
<!-- EDIT3 TABLE [10696-12109] -->
<!-- EDIT4 TABLE [13533-14261] -->
</div>
<h3><a>Kinematic vs Dynamic vs Static</a></h3>
@ -377,75 +390,83 @@ Static immobile obstacles (including buildings and terrains) have mass 0.0f. </t
<p>
All physical objects…
All physical entities…
</p>
<ul>
<li><div> must not overlap.</div>
</li>
<li><div> can detect collisions and report several values about the impact.</div>
</li>
<li><div> can respond dynamically or statically or kinematically to collisions.</div>
<li><div> can respond dynamically, or statically, or kinematically to collisions.</div>
<th>Does it have a mass?</th><td>no, 0f</td><td>yes, >0f</td><td>yes, >0f (Inertia is calculated for kinematic objects you need mass to do that)</td>
<th>Examples</th><td>Immobile obstacles: Floors, walls, buildings, …</td><td>Remote-controlled entities: Airships, meteorites, doors; networked or remote-controlled NPCs; invisible "airhooks" for hinges and joints.</td><td>Interactive entities: Rolling balls, movable crates, falling pillar, space ship…</td>
</tr>
<tr>
<th>How does it move?</th><td>never</td><td>setWalkDirection(), setLinearVelocity(), applyForce(), etc</td><td>setLocalTranslation(), move()</td>
<th>Does it have a mass?</th><td>no, 0.0f</td><td>yes<sup><ahref="#fn__1">1)</a></sup>, >0.0f </td><td>yes, >0.0f</td>
</tr>
<tr>
<th> Can it move and push others?</th><td>no</td><td>yes</td><td>yes</td>
<th> How does it move?</th><td>never</td><td>setLocalTranslation();</td><td>setLinearVelocity(); applyForce(); <br/>
setWalkDirection(); for CharacterControl</td>
</tr>
<tr>
<th> Is is affected by forces? <br/>
(Falls when it mid-air? Can be pushed by others?)</th><td>no</td><td>yes</td><td>no</td>
<th> How to place in scene?</th><td>setPhysicsLocation(); <br/>
(Falls when it mid-air? Can be pushed by others?)</th><td>no</td><td>no</td><td>yes</td>
</tr>
<tr>
<th> How to activate? </th><td>setMass(0f), (By default, objects are not kinematics)</td><td>setMass(1f), setKinematic(false)</td><td>setMass(1f), setKinematic(true)</td>
<th> How to activate? </th><td>setMass(0f); <br/>
setKinematic(false); </td><td>setMass(1f); <br/>
setKinematic(false);</td><td>setMass(1f); <br/>
setKinematic(true);</td>
</tr>
</table></div>
<!-- EDIT4 TABLE [12344-13135] -->
<!-- EDIT5 TABLE [14499-15521] -->
<p>
<strong>Tip:</strong> Typically, Spatials with a kinematic RigidBodyControl are moved programmatically, e.g. using setLocalTranslation() or move() in the update() loop, or by an Animation Path. You can also "hang them up in mid-air" and attach other PhysicsControls to them using <ahref="/com/jme3/gde/core/docs/jme3/advanced/hinges_and_joints.html">hinges and joints</a>.
<p><div>You move Spatials with a kinematic RigidBodyControl programmatically, that is by using setLocalTranslation() or move() in the update() loop, or using a <ahref="/com/jme3/gde/core/docs/jme3/advanced/motionpath.html">MotionPath</a>. You can also "hang them up in mid-air" and attach other PhysicsControls to them using <ahref="/com/jme3/gde/core/docs/jme3/advanced/hinges_and_joints.html">hinges and joints</a>.
</div></p>
</p>
<pre>airhook.setKinematic(true);</pre>
</div>
<h2><a>Forces: Moving Physical Objects</a></h2>
<h2><a>Forces: Moving Physical Entities</a></h2>
<div>
<p>
Use the following methods to move physics objects.
Use the following methods to move physics entities.
</p>
<div><table>
<tr>
<th> PhysicsControl Method </th><th> Motion </th>
</tr>
<tr>
<td> setLinearVelocity(new Vector3f(0f,0f,1f))</td><td> Set the linear speed of this object. </td>
<td> setLinearVelocity(new Vector3f(0f,0f,1f))</td><td> Set the linear speed of this entity. </td>
</tr>
<tr>
<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>
<td> setAngularVelocity(new Vector3f(0f,0f,1f)) </td><td> Set the rotational speed of the entity; 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 entity 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 entity once with a certain moment, expressed as a Vector3f. Optionally, you can specify where on the entity 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 entity 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>
@ -460,10 +481,11 @@ Use the following methods to move physics objects.
<td>clearForces()</td><td>Cancels out all forces (force, torque) etc and stops the motion.</td>
</tr>
</table></div>
<!-- EDIT5 TABLE [13584-14809] -->
<!-- EDIT6 TABLE [15937-17161] -->
<p>
<strong>Note:</strong> 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 entity overlaps with another! Within the game, you typically use the setters shown here exclusively.
</div></p>
</p>
<p>
@ -480,7 +502,7 @@ PhysicsControls also supports the following 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 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.</td>
removeCollideWithGroup(COLLISION_GROUP_01)</td><td>Collision Groups are integer bit masks – enums are available in CollisionObject. All physics entities are by default in COLLISION_GROUP_01. Two entities collide when the collideWithGroups set of one contains, the Collision Group of the other.</td>
</tr>
<tr>
<td> setDamping(float, float)</td><td>The first value is the linear threshold and the second the angular.</td>
@ -492,10 +514,10 @@ removeCollideWithGroup(COLLISION_GROUP_01)</td><td>Collision Groups are integer
<td> setCcdSweptSphereRadius()</td><td>?</td>
</tr>
<tr>
<td> setSleepingThreshold(float,float)</td><td>Sets the sleeping thresholds wich define when the object gets deactivated to save ressources. Low values keep the object active when it barely moves. The first value is the linear threshold and the second the angular.</td>
<td> setSleepingThreshold(float,float)</td><td>Sets the sleeping thresholds which define when the entity gets deactivated to save resources. Low values keep the entity active when it barely moves. The first value is the linear threshold and the second the angular.</td>
</tr>
</table></div>
<!-- EDIT6 TABLE [15205-16200] -->
<!-- EDIT7 TABLE [17570-18567] -->
</div>
<h2><a>Best Practices</a></h2>
@ -517,7 +539,7 @@ removeCollideWithGroup(COLLISION_GROUP_01)</td><td>Collision Groups are integer
</li>
</ul>
<ul>
<li><div> For large static meshes like shooter levels or terrain it is best to divide the scene model into multiple physics objects, with each its own CollisionShape. A huge city level should not be one huge mesh (model) of pavement and streets and buildings. Instead, you make individual models for buildings, for pieces of pavement, for pieces of streets, etc. Position them next to one another to form the whole city, and give each piece its own optimal CollisionShape. E.g. streets can use a fast PlaneCollisionShape if you keep them separate for buildings. Breaking the level into manageable pieces helps the engine improve performance: The less CPU-intensive <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://en.wikipedia.org/wiki/Sweep_and_prune"><paramname="text"value="<html><u>broadphase</u></html>"><paramname="textColor"value="blue"></object> can now filter out parts of the scene that are behind you or out of reach, and it only calculates the details of collisions for parts that are actually close to the action.</div>
<li><div> For large static meshes like shooter levels or terrain it is best to divide the scene model into multiple physics entities, with each its own CollisionShape. A huge city level should not be one huge mesh (model) of pavement and streets and buildings. Instead, you make individual models for buildings, for pieces of pavement, for pieces of streets, etc. Position them next to one another to form the whole city, and give each piece its own optimal CollisionShape. E.g. streets can use a fast PlaneCollisionShape if you keep them separate for buildings. Breaking the level into manageable pieces helps the engine improve performance: The less CPU-intensive <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://en.wikipedia.org/wiki/Sweep_and_prune"><paramname="text"value="<html><u>broadphase</u></html>"><paramname="textColor"value="blue"></object> can now filter out parts of the scene that are behind you or out of reach, and it only calculates the details of collisions for parts that are actually close to the action.</div>
</li>
</ul>
<div><span>
@ -526,5 +548,9 @@ removeCollideWithGroup(COLLISION_GROUP_01)</td><td>Collision Groups are integer
You can save and load scenes and individual Nodes using com.jme3.export.binary.BinaryExporter and com.jme3.export.binary.BinaryImporter. Use standard Java serialization to load game data. The jMonkeyEngine binary file format is .j3o. You can open, view, and edit .j3o files in the jMonkeyEngine <ahref="/com/jme3/gde/core/docs/jme3/advanced/sdk.html">SDK</a>.
You can save and load scenes and individual Nodes using com.jme3.export.binary.BinaryExporter and com.jme3.export.binary.BinaryImporter. Use standard Java serialization to load game data or use the Savable interface. The jMonkeyEngine binary file format is .j3o. You can open, view, and edit .j3o files in the jMonkeyEngine <ahref="/com/jme3/gde/core/docs/jme3/advanced/sdk.html">SDK</a>.
</p>
</div>
@ -53,5 +53,66 @@ You can save and load scenes and individual Nodes using com.jme3.export.binary.B
...
</pre>
</div>
<h2><a>Custom Savable</a></h2>
<div>
<p>
If you have a custom class that you want to save or assign using <code>setUserData()</code>, the class must implement the <code>com.jme3.export.Savable</code> interface.
</p>
<pre>import com.jme3.export.InputCapsule;
import com.jme3.export.JmeExporter;
import com.jme3.export.JmeImporter;
import com.jme3.export.OutputCapsule;
import com.jme3.export.Savable;
import com.jme3.material.Material;
import java.io.IOException;
public class MyCustomClass implements Savable {
private int someIntValue;
private float someFloatValue;
private Material someJmeObject;
...
// your other code...
...
public void write(JmeExporter ex) throws IOException {
someJmeObject = capsule.readSavable("someJmeObject", new Material());
}
}</pre>
<p>
For each class field that you want to save and load,
</p>
<ul>
<li><div> Add one line that <code>write()</code>s the data to the JmeExport output capsule. </div>
<ul>
<li><div> Specify the variable to save, give it String name (can be the same as the variable name), and specify a default value.</div>
</li>
</ul>
</li>
<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> One 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 ones that you used in the <code>write() method</code>) and a default value.</div>
@ -149,8 +149,6 @@ Open your game project in the jMonkeyEngine <acronym title="Software Development
<strong>Building</strong>
</p>
<ol>
<li><div> Right-click the project node and choose Set Main Project.</div>
</li>
<li><div> Right-click the project node to build your project. <br/>
An APK file is created in the "dist" folder.</div>
</li>
@ -161,14 +159,18 @@ An APK file is created in the "dist" folder.</div>
<strong>Running</strong>
</p>
<ol>
<li><div>Select the project</div>
<li><div>Right-click the project node and choose Set Main Project.</div>
</li>
<li><div> Select the "Android Device" build configuration next to the Run toolbar button.</div>
</li>
<li><div> Make sure "Compile on Save" is disabled in your project preferences.</div>
<li><div><em>Make sure "Compile on Save" is disabled in your project preferences.</em></div>
</li>
<li><div> Run the application on a connected phone by right-clicking it and selecting "Run" or press the "Play" button in the toolbar.</div>
</li>
<li><div> The application will run and output its log to the "Output" window of the <acronymtitle="Software Development Kit">SDK</acronym>.</div>
</li>
<li><div> When finished testing, click the "x" next to the run status in the lower right to quit the logging output.</div>
</li>
</ol>
<p>
@ -180,6 +182,10 @@ The default android run target uses the default device set in the Android config
During build, the libraries and main jar file from the main project are copied to the android project libs folder for access. During this operation the desktop-specific libraries are replaced with android specific JARs.
</p>
</div>
<h4><a>Installing NBAndroid</a></h4>
@ -199,12 +205,12 @@ Activating the nbandroid plugin in the jMonkeyEngine <acronym title="Software De
</div>
<h4><a>Beta Notes</a></h4>
<h4><a>Notes</a></h4>
<div>
<ul>
<li><div> The package name parameter is only used when creating the project and only sets the android MainActivity package name</div>
</li>
<li><div> The needed jMonkeyEngine3.jar for android comes with the plugin and is automatically added to the android build</div>
<li><div> The needed android.jar comes with the plugin and is automatically added to the android build</div>
</li>
<li><div> All non-android project libraries are automatically excluded from the android build. This is currently hard-coded in the build script, check nbproject/mobile-impl.xml for the details.</div>
</li>
@ -260,6 +266,10 @@ Since the main project is not configured to access the android api directly, you
Although you will use android specific api, using a camera is not exactly android specific and so you should try to design this part of the application as platform independent as possible as well. As an example, if you want to use the phones camera as an image input stream for a texture, you can create e.g. the AppState that manages the image and makes it available to the application inside the main project (no android code is needed). Then in the android part of the code you make a connection to the camera and update the image in the AppState. This also allows you to easily support cameras on other platforms in the same way or fallback to something else in case the platform doesn't support a camera.
</p>
<p>
Note that you have to build the whole project once to make (new) classes in the main project available to the android part.
@ -110,10 +110,10 @@ In this tutorial, you learn some new terms:
<th>What you want to do</th><th>How you say it in JME3 terminology</th>
</tr>
<tr>
<td>Structure the 3D scene</td><td>Define the scene graph</td>
<td>Lay out the 3D scene</td><td>Populate the scene graph</td>
</tr>
<tr>
<td>Create scene objects</td><td>Create Spatials</td>
<td>Create scene objects</td><td>Create Spatials (e.g. create Geometries)</td>
</tr>
<tr>
<td>Make an object appear in the scene</td><td>Attach a Spatial to the rootNode</td>
@ -121,8 +121,11 @@ In this tutorial, you learn some new terms:
<tr>
<td>Make an object disappear from the scene</td><td>Detach the Spatial from the rootNode</td>
</tr>
<tr>
<td>Position/move, turn, or resize an object</td><td>Translate, rotate, scale an object. Transform an object.</td>
</tr>
</table></div>
<!-- EDIT1 TABLE [3079-3371] -->
<!-- EDIT1 TABLE [3079-3496] -->
<p>
Every JME3 application has a rootNode: Your game automatically inherits the <code>rootNode</code> object from SimpleApplication. Everything attached to the rootNode is part of the scene graph. The elements of the scene graph are Spatials.
@ -149,7 +152,7 @@ Every JME3 application has a rootNode: Your game automatically inherits the <cod
<th> Examples: </th><td> A box, a sphere, a player, a building, a piece of terrain, a vehicle, missiles, NPCs, etc… </td><td> The <code>rootNode</code>, a floor node grouping several terrains, a custom vehicle-with-passengers node, a player-with-weapon node, an audio node, etc… </td>
</tr>
</table></div>
<!-- EDIT2 TABLE [3787-4280] -->
<!-- EDIT2 TABLE [3912-4405] -->
</div>
<h2><a>Understanding the Code</a></h2>
@ -201,7 +204,7 @@ What happens in the code snippet? You use the <code>simpleInitApp()</code> metho
</li>
</ul>
</li>
<li><div> You create a Node.</div>
<li><div> You create a pivot Node.</div>
<ul>
<li><div> Name the Node "pivot".</div>
</li>
@ -213,13 +216,13 @@ What happens in the code snippet? You use the <code>simpleInitApp()</code> metho
rootNode.attachChild(pivot);</pre>
<p>
If you run the application with only the code up to here, the scene appears empty. This is because the Node is invisible and you have not yet attached any visible Geometries to the rootNode.
If you run the application with only the code up to here, the scene appears empty. This is because a Node is invisible, and you have not yet attached any visible Geometries to the rootNode.
</p>
</div>
</li>
</ul>
</li>
<li><div> Attach the two boxes to the node. <pre> pivot.attachChild(blue);
<li><div> Attach the two boxes to the pivot node. <pre> pivot.attachChild(blue);
pivot.attachChild(red);</pre>
<p>
@ -236,10 +239,24 @@ If you run the app with only the code up to here, you see two cubes: A red cube
</li>
</ol>
</div>
<h3><a>What is a Pivot Node?</a></h3>
<div>
<p>
<strong>What has happened?</strong> You have grouped two Geometries by attaching them to one pivot Node. You can now use the pivot Node as a handle to move the two Geometries. Rotating the pivot Node rotates both attached Geometries, in one step. Transforming a Node to transform attached Spatials is a common task. You will use this method a lot in your games when you move Spatials around, e.g. for game characters. You can also rotate Spatials around their own center – then you do not need a pivot Node.
You can transform (e.g. rotate) Geometries around their own center, or around a user defined center point. A user defined center point for one or more Geometries is called pivot.
</p>
<ul>
<li><div> In this example, you have grouped two Geometries by attaching them to one pivot Node. You use the pivot Node as a handle to rotate the two Geometries together around one common center. Rotating the pivot Node rotates all attached Geometries, in one step. The pivot node is the center of the rotation. Before attaching the other Geometries, make certain that the pivot node is at (0,0,0). Transforming a parent Node to transform all attached child Spatials is a common task. You will use this method a lot in your games when you move Spatials around. <br/>
<strong>Examples:</strong> A vehicle and its driver move together; a planet with its moon orbits the sun. </div>
</li>
<li><div> Contrast this case with the other option: If you don't create an extra pivot node and transform a Geometry, then every transformation is done relative to the Geometry's origin (typically the center). <br/>
<strong>Examples:</strong> If you rotate each cube directly (using <code>red.rotate(0.1f , 0.2f , 0.3f);</code> and <code>blue.rotate(0.5f , 0.0f , 0.25f);</code>), then each cube is rotated individually around its center. This is similar to a planet rotating around its own center.</div>
</li>
</ul>
</div>
@ -250,7 +267,7 @@ If you run the app with only the code up to here, you see two cubes: A red cube
<th> Task…? </th><th> Solution! </th>
</tr>
<tr>
<td> Create a Spatial </td><td> Create a shape and give it a Material. For example: <pre>Box(Vector3f.ZERO, 1, 1, 1);
<td> Create a Spatial </td><td> Create a shape, wrap it into a Geometry, and give it a Material. For example: <pre>Box(Vector3f.ZERO, 1, 1, 1);
Geometry thing = new Geometry("thing", mesh);
<td> Find a Spatial in the scene by the object's name or ID. </td><td> Look at the node's children: <pre>Spatial thing = rootNode.getChild("thing");</pre>
<td> Find a Spatial in the scene by the object's name, or ID, or by its position in the parent-child hierarchy. </td><td> Look at the node's children or parent: <pre>Spatial thing = rootNode.getChild("thing");</pre>
<td> Specify what should be loaded at the start </td><td> Everything you initialize and attach to the <code>rootNode</code> in the <code>simpleInitApp()</code> method is part of the scene at the start of the game. </td>
</tr>
</table></div>
<!-- EDIT3 TABLE [7080-8201] -->
<!-- EDIT3 TABLE [8042-9304] -->
</div>
<h2><a>How do I Transform Spatials?</a></h2>
@ -301,7 +319,7 @@ To move a Spatial <em>to</em> specific coordinates, such as (0,40.2f,-2), use: <
@ -329,7 +347,7 @@ To roll an object 180° around the z axis: <pre>thing.rotate( 0f , 0f , 180*
</td><td>pitch = nodding your head</td><td>yaw = shaking your head</td><td>roll = cocking your head</td>
</tr>
</table></div>
<!-- EDIT6 TABLE [9335-10116] -->
<!-- EDIT6 TABLE [10438-11219] -->
</div>
<h2><a>How do I Troubleshoot Spatials?</a></h2>
@ -360,7 +378,7 @@ Did you rotate around the right axis? </td>
<td> A Geometry has an unexpected Color or Material. </td><td> Did you reuse a Material from another Geometry and have inadvertently changed its properties? (If so, consider cloning it: mat2 = mat.clone(); ) </td>
</tr>
</table></div>
<!-- EDIT7 TABLE [10249-11222] -->
<!-- EDIT7 TABLE [11352-12325] -->
</div>
<h2><a>How do I Add Custom Data to Spatials?</a></h2>
<strong>Prerequisites:</strong> This tutorial assumes that:
<strong>Prerequisites:</strong> This tutorial assumes that you have <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://jmonkeyengine.org/wiki/doku.php/"><paramname="text"value="<html><u>downloaded the jMonkeyEngine SDK</u></html>"><paramname="textColor"value="blue"></object>.
</p>
<ul>
<li><div> You have <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://jmonkeyengine.org/wiki/doku.php/"><paramname="text"value="<html><u>downloaded the jMonkeyEngine SDK</u></html>"><paramname="textColor"value="blue"></object> (or set up the jMonkeyEngine3 in another IDE of your choice)</div>
<p>
In this tutorial series, we assume that you use the jMonkeyEngine <ahref="/com/jme3/gde/core/docs/sdk.html">SDK</a>. As an intermediate or advanced Java developer, you will quickly see that, in general, you can develop jMonkeyEngine code in any integrated development environment (NetBeans IDE, Eclipse, IntelliJ) or even from the <ahref="/com/jme3/gde/core/docs/jme3/simpleapplication_from_the_commandline.html">command line</a>.
</p>
<p>
OK, let's get ready to create our first jMonkeyEngine3 application.
</p>
</div>
<h2><a>Create a Project</a></h2>
<div>
<p>
In the jMonkeyEngine <acronymtitle="Software Development Kit">SDK</acronym>:
</p>
<ol>
<li><div> Choose File→New Project… from the main menu.</div>
</li>
<li><div> You are have <ahref="/com/jme3/gde/core/docs/sdk/project_creation.html">created a Java SE project with the JME3 libraries on the classpath</a>.</div>
<li><div> In the New Project wizard, select the template JME3→Basic Game. Click Next. </div>
<ol>
<li><div> Specify a project name, e.g. "HelloWorldTutorial"</div>
</li>
</ul>
<li><div> Specify a path where to store your new project, e.g. a <code>jMonkeyProjects</code> directory in your home directory.</div>
</li>
</ol>
</li>
<li><div> Click Finish. </div>
</li>
</ol>
<p>
You are ready to create your first jMonkeyEngine3 game! You can generally use the tutorials in this introductory series with any integrated development environment (IDE), such as the jMonkeyEngine <acronymtitle="Software Development Kit">SDK</acronym>, NetBeans, Eclipse, or run them straight from the commandline. In the following, we will use the jMonkeyEngine <acronymtitle="Software Development Kit">SDK</acronym>.
If you have questions, read more about <ahref="/com/jme3/gde/core/docs/sdk/project_creation.html">Project Creation</a> here.
</p>
<p>
<p><div>We recommend to go through the steps yourself, as described in the tutorials. Alternatively, you can create a project based on the <ahref="/com/jme3/gde/core/docs/sdk/sample_code.html">JmeTests</a> template in the jMonkeyEngine <acronymtitle="Software Development Kit">SDK</acronym>. It will create a project that already contains the <code>jme3test.helloworld</code> samples (and many others). For example, you can use the JmeTests project to verify whether you got the solution right.
</div></p>
</p>
</div>
<h2><a>Writing a SimpleApplication</a></h2>
<h2><a>Write a SimpleApplication</a></h2>
<div>
<p>
Create a <code>jme3test.helloworld</code> package and a file <code>HelloJME3.java</code> in it.
For this tutorial, you want to create a <code>jme3test.helloworld</code> package in your project, and create a file <code>HelloJME3.java</code> in it.
</p>
<p>
In the jMonkeyEngine <acronymtitle="Software Development Kit">SDK</acronym>, you right-click the Source Packages node:
In the jMonkeyEngine <acronymtitle="Software Development Kit">SDK</acronym>:
</p>
<ul>
<li><div> Select <code>New… > Java Class</code> to create a new file.</div>
<ol>
<li><div> Right-click the Source Packages node of your project.</div>
</li>
<li><div> Choose New…→Java Class to create a new file.</div>
</li>
<li><div> Enter a class name: <code>HelloJME3</code></div>
<li><div> Enter the class name: <code>HelloJME3</code></div>
</li>
<li><div> Enter a package: <code>jme3test.helloworld</code></div>
<li><div> Enter the package name: <code>jme3test.helloworld</code>. </div>
</li>
<li><div> Click Finish.</div>
</li>
</ul>
</ol>
<p>
The <acronymtitle="Software Development Kit">SDK</acronym> creates the file HelloJME3.java for you.
</p>
</div>
@ -88,19 +125,21 @@ public class HelloJME3 extends SimpleApplication {
}</pre>
<p>
Build and run the HelloJME3 class. If a jme settings dialog pops up, confirm the default settings.
Right-click the HelloJME3 class and choose Run. If a jME3 settings dialog pops up, confirm the default settings.
</p>
<ol>
<li><div> You should see a simple window displaying a 3-D cube.</div>
<li><div> You should see a simple window displaying a 3D cube.</div>
</li>
<li><div> Press the WASD keys and move the mouse to navigate around.</div>
</li>
<li><div> Use the WASD keys and the mouse to navigate around.</div>
<li><div>Look at the FPS text and object count information in the bottom left. You will use this information during development, and you will remove it for the release. (To read the numbers correctly, consider that the 14 lines of text counts as 14 objects with 914 vertices.)</div>
</li>
<li><div> Press Escape to close the application.</div>
</li>
</ol>
<p>
Congratulations, it works! How did we do that?
Congratulations! Now let's find out how it works!
</p>
</div>
@ -110,7 +149,42 @@ Congratulations, it works! How did we do that?
<p>
The code above has initialized the scene, and started the game.
The code above has initialized the scene, and started the application.
</p>
</div>
<h3><a>Start the SimpleApplication</a></h3>
<div>
<p>
Look at the first line. The HelloJME3.java class extends <code>com.jme3.app.SimpleApplication</code>.
</p>
<pre>public class HelloJME3 extends SimpleApplication {
// your code...
}</pre>
<p>
Every JME3 game is an instance of <code>com.jme3.app.SimpleApplication</code>. The SimpleApplication class manages your 3D scene graph and automatically draws it to the screen – that is, in short, what a game engine does for you!
</p>
<p>
You start every JME3 game from the main() method, as every standard Java application:
</p>
<ol>
<li><div> Instantiate your <code>SimpleApplication</code>-based class</div>
</li>
<li><div> Call the application's <code>start()</code> method to start the game engine. </div>
</li>
</ol>
<pre> public static void main(String[] args){
HelloJME3 app = new HelloJME3(); // instantiate the game
app.start(); // start the game!
}</pre>
<p>
This code opens your application window. Let's learn how you put something into the window next.
</p>
</div>
@ -119,44 +193,55 @@ The code above has initialized the scene, and started the game.
<div>
<div><table>
<tr>
<th>What you want to do</th><th>How you say it in JME3 terminology</th>
<th>What you want to do</th><th>How you say that in JME3 terminology</th>
</tr>
<tr>
<td>You want to create a cube.</td><td>I create a Geometry with a 1x1x1 Box shape.</td>
</tr>
<tr>
<td>You want to create a cube.</td><td>You create a Geometry with a 1x1x1 Box shape.</td>
<td>You want to use a blue color.</td><td>I create a Material with a blue Color property.</td>
</tr>
<tr>
<td>You want to use a blue color.</td><td>You create a Material with a blue Color property.</td>
<td>You want to colorize the cube blue.</td><td>I set the Material of the Box Geometry.</td>
</tr>
<tr>
<td>You want to colorize the cube blue.</td><td>You set the Geometry's Material.</td>
<td>You want to add the cube to the scene.</td><td>I attach the Box Geometry to the rootNode.</td>
</tr>
<tr>
<td>You want the cube to appear in the scene.</td><td>You attach the cube to the rootNode.</td>
<td>You want the cube to appear in the center.</td><td>I create the Box at the origin = at <code>Vector3f.ZERO</code>.</td>
</tr>
</table></div>
<!-- EDIT1 TABLE [2897-3262] -->
<!-- EDIT1 TABLE [5076-5549] -->
<p>
If you are unfamiliar with the vocabulary, read more about <ahref="/com/jme3/gde/core/docs/jme3/the_scene_graph.html">the Scene Graph</a> here.
</p>
</div>
<h3><a>Initializing the Scene</a></h3>
<h3><a>Initialize the Scene</a></h3>
<div>
<p>
In Java, the creation of a blue cube looks as follows:
Look at rest of the code sample. The <code>simpleInitApp()</code> method is automatically called once at the beginning when the application starts. Every JME3 game must have this method. In the <code>simpleInitApp()</code> method, you load game objects before the game starts.
</p>
<pre> public void simpleInitApp(){
Box(Vector3f.ZERO, 1, 1, 1); // create cube shape at the origin
Geometry geom = new Geometry("Box", b); // create cube geometry from the shape
Material mat = new Material(assetManager,
"Common/MatDefs/Misc/Unshaded.j3md"); // create a simple material
mat.setColor("Color", ColorRGBA.Blue); // set color of material to blue
geom.setMaterial(mat); // set the cube's material
rootNode.attachChild(geom); // make the cube appear in the scene
// your initialization code...
}</pre>
<p>
In the <code>simpleInitApp()</code> method, you create or load all game objects before the game starts. The <code>simpleInitApp()</code> method is automatically called once at the beginning of every JME3 game.
The initialization code of a blue cube looks as follows:
</p>
<pre> public void simpleInitApp(){
Box(Vector3f.ZERO, 1, 1, 1); // create a 1x1x1 box shape at the origin
Geometry geom = new Geometry("Box", b); // create a cube geometry from the box shape
Material mat = new Material(assetManager,
"Common/MatDefs/Misc/Unshaded.j3md"); // create a simple material
mat.setColor("Color", ColorRGBA.Blue); // set color of material to blue
geom.setMaterial(mat); // set the cube geometry 's material
rootNode.attachChild(geom); // make the cube geometry appear in the scene
}</pre>
<p>
A typical JME3 game has the following initialization process:
@ -168,23 +253,23 @@ A typical JME3 game has the following initialization process:
</li>
<li><div> You make objects appear in the scene by attaching them to the <code>rootNode</code>.</div>
</li>
<li><div><strong>Examples:</strong> Load player, terrain, sky, enemies, obstacles, and place them in their start positions.</div>
<li><div><strong>Examples:</strong> Load player, terrain, sky, enemies, obstacles, …, and place them in their start positions.</div>
</li>
</ul>
</li>
<li><div> You initialize variables</div>
<ul>
<li><div> You set variables to their start values. </div>
<li><div> You create variables to track the game state. </div>
</li>
<li><div> You want to use variables track the game state. </div>
<li><div> You set variables to their start values. </div>
</li>
<li><div><strong>Examples:</strong> Set the <code>score</code> to 0, set <code>health</code> to 100%, and so on.</div>
<li><div><strong>Examples:</strong> Set the <code>score</code> to 0, set <code>health</code> to 100%, …</div>
</li>
</ul>
</li>
<li><div> You initialize keys and mouse actions</div>
<li><div> You initialize keys and mouse actions.</div>
<ul>
<li><div> The following input bindings are pre-configured by default:</div>
<li><div> The following input bindings are pre-configured:</div>
<ul>
<li><div> W,A,S,D keys – Move around in the scene</div>
</li>
@ -194,9 +279,9 @@ A typical JME3 game has the following initialization process:
</li>
</ul>
</li>
<li><div>Add your own keys and mouse clicks.</div>
<li><div>Define your own additional keys and mouse click actions.</div>
</li>
<li><div><strong>Examples:</strong> Click to shoot, press Space to jump, etc.</div>
<li><div><strong>Examples:</strong> Click to shoot, press Space to jump, …</div>
</li>
</ul>
</li>
@ -204,37 +289,11 @@ A typical JME3 game has the following initialization process:
</div>
<h3><a>Starting the Game</a></h3>
<div>
<p>
The HelloJME3.java class extends <code>com.jme3.app.SimpleApplication</code>, which is a subclass of <code>com.jme3.app.Application</code>. Every JME3 game is an instance of <code>com.jme3.app.SimpleApplication</code>.
</p>
<p>
To run a JME3 game, you first instantiate your <code>SimpleApplication</code>-based class, and then call its <code>start()</code> method:
</p>
<pre> public static void main(String[] args){
HelloJME3 app = new HelloJME3();
app.start(); // start the game
}</pre>
<p>
Typically you start a game from your Java application's main() method.
</p>
</div>
<h2><a>Conclusion</a></h2>
<div>
<p>
These few lines of code simply display a static 3D cube. You can navigate around in this 3D scene.
</p>
<p>
You have learned that a SimpleApplication is a good starting point because it provides you with:
</p>
<ul>
@ -248,23 +307,23 @@ You have learned that a SimpleApplication is a good starting point because it pr
<p>
When developing a game application, you will now want to:
When developing a game application, you want to:
</p>
<ol>
<li><div> Initialize your game world,</div>
<li><div> Initialize the game scene</div>
</li>
<li><div> Trigger actions in the event loop,</div>
<li><div> Trigger game actions </div>
</li>
<li><div> Respond to user input.</div>
</li>
</ol>
<p>
In the following tutorials you learn how accomplish these tasks with the jMonkeyEngine 3.
The now following tutorials teach how you accomplish these tasks with the jMonkeyEngine 3.
</p>
<p>
Continue with the <ahref="/com/jme3/gde/core/docs/jme3/beginner/hello_node.html">Hello Node</a> tutorial, where we will first show you more details about how to initialize the game world, also known as the scene graph.
Continue with the <ahref="/com/jme3/gde/core/docs/jme3/beginner/hello_node.html">Hello Node</a> tutorial, where you learn more details about how to initialize the game world, also known as the scene graph.
We recommend downloading the <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://code.google.com/p/jmonkeyengine/downloads/list"><paramname="text"value="<html><u>jMonkeyEngine SDK</u></html>"><paramname="textColor"value="blue"></object> - but of course you can also build the jMonkeyEngine yourself from the sources. You need <ahref="/com/jme3/gde/core/docs/htpp/subversion.tigris.org.html">Subversion</a> installed.
We recommend downloading the <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://code.google.com/p/jmonkeyengine/downloads/list"><paramname="text"value="<html><u>jMonkeyEngine SDK</u></html>"><paramname="textColor"value="blue"></object> - but of course you can also build the jMonkeyEngine yourself from the sources. In this case, you need the <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://subversion.tigris.org"><paramname="text"value="<html><u>Subversion</u></html>"><paramname="textColor"value="blue"></object>file version system installed (svn).
</p>
<ol>
@ -17,7 +17,7 @@ We recommend downloading the <object classid="java:org.netbeans.modules.javahelp
<li><div> This compiles the files <code>dist/jMonkeyEngine3.jar</code> and<code>dist/libs/*</code></div>
<li><div> This compiles the JAR files in <code>dist/libs/*</code></div>
</li>
</ul>
</li>
@ -33,7 +33,7 @@ We recommend downloading the <object classid="java:org.netbeans.modules.javahelp
</li>
</ul>
</li>
<li><div><strong>Use:</strong> Create a Java SE project and place <code>dist/jMonkeyEngine3.jar</code> and all JARs from the <code>dist/lib</code> directory on the classpath.</div>
<li><div><strong>Use:</strong> Create a Java SE project and place all JARs from the <code>dist/lib</code> directory on the classpath.</div>
<ul>
<li><div> You can now extend your first game from <code>com.jme3.app.SimpleApplication</code>. </div>
@ -510,14 +510,24 @@ Use PhysicsControl's joints.
</div>
<h3><a>How do I get rid of the debug display (fps, stats)?</a></h3>
<h3><a>What are these FPS/Objects/Vertices/Triangles statistics?</a></h3>
<div>
<p>
At the bottom left of every default SimpleGame, you see the <ahref="/com/jme3/gde/core/docs/jme3/advanced/statsview.html">StatsView</a> and the FPS (frames per seconds) view. It provides you with extra information during the development phase. For example, if the object count is increasing and the FPS slows down, then you now that your code attaches too many and does not detach enough objects.
</p>
</div>
<h3><a>How do I get rid of the FPS/Objects statistics?</a></h3>
<div>
<p>
In the application's simpleInitApp() method, call:
</p>
<pre>setDisplayFps(false);
setDisplayStatView(false);</pre>
<pre>setDisplayFps(false); // to hide the FPS
setDisplayStatView(false); // to hide the statistics </pre>
setRenderer(AppSettings.LWJGL_OPENGL3)</td><td>Switch Video Renderer</td><td>OpenGL 2</td>
<td>setRenderer(AppSettings.LWJGL_OPENGL1) <br/>
setRenderer(AppSettings.LWJGL_OPENGL2) <br/>
setRenderer(AppSettings.LWJGL_OPENGL3)</td><td>Switch Video Renderer to OpenGL 1.1, OpenGL 2, or OpenGL 3.3. If your graphic card does not support all OpenGL2 features (<code>UnsupportedOperationException: GLSL and OpenGL2 is required for the LWJGL renderer</code>), then you can force your SimpleApplication to use OpenGL1 compatibility. (Then you still can't use special OpenGL2 features, but at least the error goes away and you can continue with the rest.) </td><td> OpenGL 2 </td>
</tr>
<tr>
<td>setBitsPerPixel(32)</td><td>Set the color depth. <br/>
@ -74,7 +75,7 @@ Set VSync to false to deactivate vertical syncing (faster, but possible page tea
@ -96,7 +97,7 @@ Set VSync to false to deactivate vertical syncing (faster, but possible page tea
<td>setStereo3D(true)</td><td>Enable 3D stereo. This feature requires hardware support from the GPU driver. See <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://en.wikipedia.org/wiki/Quad_buffering"><paramname="text"value="<html><u>Quad Buffering</u></html>"><paramname="textColor"value="blue"></object>. Currently, your everday user's hardware does not support this, so you can ignore it for now.</td><td>false</td>
@ -111,7 +112,7 @@ ImageIO.read(new File("")), …});</td><td>This specifies the little a
<td>setSettingsDialogImage("/path/to/splash.png")</td><td>A custom splashscreen image in the assets directory which is displayed when the settings dialog is shown.</td><td>"/com/jme3/app/Monkey.png"</td>
<form><div><inputtype="hidden"name="do"value="login"/><inputtype="hidden"name="sectok"value="d53e8f44804daa7c4f329d03722a8f2c"/><inputtype="submit"value="Login"class="button"title="Login"/></div></form><form><div><inputtype="hidden"name="do"value="index"/><inputtype="submit"value="Sitemap"class="button"accesskey="x"title="Sitemap [X]"/></div></form><a><inputtype="button"class="button"value="Back to top"onclick="window.scrollTo(0, 0)"title="Back to top"/></a>
<form><div><inputtype="hidden"name="do"value="login"/><inputtype="hidden"name="sectok"value="4a32a40e0c3a07e8cd3f2514309b5e56"/><inputtype="submit"value="Login"class="button"title="Login"/></div></form><form><div><inputtype="hidden"name="do"value="index"/><inputtype="submit"value="Sitemap"class="button"accesskey="x"title="Sitemap [X]"/></div></form><a><inputtype="button"class="button"value="Back to top"onclick="window.scrollTo(0, 0)"title="Back to top"/></a>
</div>
<div></div>
</div-->
@ -351,7 +359,7 @@ You've followed a link to a topic that doesn't exist yet. If permissio
Next we copy the necessary JAR libraries. You only have to do this set of steps once every time you download a new JME3 build.
Next you copy the necessary JAR libraries from the download to your project. You only have to do this set of steps once every time you download a new JME3 build.
</p>
<pre>mkdir HelloJME3/build
mkdir HelloJME3/lib
cp jme3/jMonkeyEngine3.jar HelloJME3/lib
cp jme3/lib/*.* HelloJME3/lib</pre>
<p>
If you have built JME3 from the sources, then the paths are different:
If you have built JME3 from the sources, then the copy paths are different:
</p>
<pre>mkdir HelloJME3/build
mkdir HelloJME3/lib
cp jme3/dist/jMonkeyEngine3.jar HelloJME3/lib
cp jme3/dist/*.* HelloJME3/lib</pre>
</div>
@ -132,13 +130,13 @@ public class HelloJME3 extends SimpleApplication {
We build the sample application into the build directory…
@ -47,7 +47,7 @@ Let's have a look at the abstract project structure in the Project Explorer
</li>
<li><div><strong>Source Packages node:</strong> This is where you manage your packages and classes. For a newly created project, it contains one package and one class, <code>Main.java</code>. Double click <code>Main.java</code> to open it in the editor.</div>
</li>
<li><div><strong>Libraries node:</strong> An overview of all libraies on your game's classpath. The classpath is already set-up for the jme3 framework (including LWJGL, JOGG, JOAL, JOGL, etc).</div>
<li><div><strong>Libraries node:</strong> An overview of all libraies on your game's classpath. The classpath is already set-up for the jme3 framework (including LWJGL, Bullet, Nifty <acronymtitle="Graphical User Interface">GUI</acronym>, etc).</div>
</li>
</ul>
@ -128,23 +128,25 @@ Right-Click the project to open the Project properties.
<p>
You may want to use external Java libraries in your jME project, for example content generators or artificial intelligence implementations.
</p>
<p>
Add the library to the global library list:
</p>
<ul>
<li><div> Select Tools→Libraries in the main menu.</div>
</li>
<li><div> Click "New Library", enter a name for the library and press OK</div>
<li><div> Click "New Library", enter a name for the library, and press OK</div>
</li>
<li><div> In the "Classpath" tab, press "Add JAR/Folder" and select the jar file(s) needed for the library</div>
</li>
<li><div> In the "JavaDoc" tab, press "Add ZIP/Folder" and select the javadoc for the library (zipped or folder)</div>
<li><div>(Optional) In the "JavaDoc" tab, press "Add ZIP/Folder" and select the javadoc for the library, as zip file or folder.</div>
</li>
<li><div> In the "Sources" tab you can select a folder or jar file containing the source files of the library if available</div>
<li><div>(Optional) In the "Sources" tab you can select a folder or jar file containing the source files of the library.</div>
</li>
<li><div> Press OK</div>
</li>
<li><div> Right-Click your project</div>
</li>
</ul>
<p>
@ -162,7 +164,7 @@ Add the library to a project:
<p>
Thats it, your project can now use the external library.
That's it, your project can now use the external library. If you also linked the javadoc and sources, the <acronymtitle="Software Development Kit">SDK</acronym> will assist you with javadoc popups, code completion (ctrl-space) and source navigation (ctrl-click).
</p>
</div>
@ -170,9 +172,9 @@ Thats it, your project can now use the external library.
<h3><a>Development Process</a></h3>
<div>
<ul>
<li><div><strong>Creating new files and packages:</strong> Select the Source Packages node (or any of its subnodes), and press ctrl-N (File>New File): Use the New File wizard to create new Java classes, Java packages, Java beans, Swing forms, Junit files, JME3 Materials and Models, and many more.</div>
<li><div><strong>Creating new files and packages:</strong> Select the Source Packages node (or any of its subnodes), and press ctrl-N (File→New File): Use the New File wizard to create new Java classes, Java packages, Java beans, Swing forms, JUnit files, j3m Materials, j3o scenes, j3f filters, and many more.</div>
</li>
<li><div><strong>Editing files:</strong> Open the Projects Explorer and double-click a Java file from the Source Packages to open it in the Editor. The <ahref="/com/jme3/gde/core/docs/sdk/code_editor.html">jMonkeyEngine SDK Code Editor</a> assists you in many ways, including Syntactic and semantic code coloring, code completion, and javadoc. <ahref="/com/jme3/gde/core/docs/sdk/code_editor.html">(More...)</a></div>
<li><div><strong>Editing files:</strong> Open the Projects Explorer and double-click a Java file from the Source Packages to open it in the Editor. The <ahref="/com/jme3/gde/core/docs/sdk/code_editor.html">jMonkeyEngine SDK Code Editor</a> assists you in many ways, including syntactic and semantic code coloring, code completion, and javadoc. <ahref="/com/jme3/gde/core/docs/sdk/code_editor.html">(More...)</a></div>
</li>
<li><div><strong>Adding Assets:</strong></div>
<ul>
@ -182,7 +184,7 @@ Thats it, your project can now use the external library.
</li>
</ul>
</li>
<li><div><strong>ToDo List:</strong> The tasks window automatically lists all lines containing errors and warnings, and all lines that you have marked with comment keywords such as <code>FIXME</code>, @todo, TODO.</div>
<li><div><strong>ToDo List:</strong> The tasks window automatically lists all lines containing errors and warnings, and all lines that you have marked with the comment keywords <code>FIXME</code>, @todo, or TODO.</div>
@ -230,30 +232,24 @@ Thats it, your project can now use the external library.
<h2><a>Running Sample Projects</a></h2>
<div>
<ol>
<li><div> Choose File > New Project from the main menu.</div>
</li>
<li><div> In the New Project Wizard, select JME3 > JME3 Tests</div>
</li>
<li><div> Click next to pick a path where to store the <code>JME3Tests</code> project.</div>
</li>
<li><div> Click Finish. The sample project opens. </div>
</li>
<li><div> Right-click the <code>JME3Tests</code> project and choose Run.</div>
<p>
The <acronymtitle="Software Development Kit">SDK</acronym> contains <ahref="/com/jme3/gde/core/docs/sdk/sample_code.html">Sample Code</a> (read more).
</p>
<p>
Open the Source Packages node of the JmeTests project.
</p>
<ul>
<li><div> Use the TestChooser to try out the included jMonkeyEngine demos!</div>
<li><div> Right-click the <code>JME3Tests</code> project and choose Run. <br/>
Choose samples from the TestChooser and try out the included demos.</div>
</li>
</ul>
</li>
<li><div> Open the Source Packages node of the sample's project.</div>
<ul>
<li><div> Browse a demo's source code to learn how a feature is implemented.</div>
<li><div> Browse a demo's source code in the <acronymtitle="Software Development Kit">SDK</acronym>'s Project window to learn how a feature is implemented and used.</div>
</li>
<li><div> Feel free to modify the code samples and experiment! If you break something, you can always recreate the packaged samples from the <code>JME3 Tests</code> template.</div>