From 11e23de0eceea945e835fc8939d72a2887a7bf13 Mon Sep 17 00:00:00 2001
From: "nor..67"
Material mat_brick = new Material( - assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); - + assetManager, "Common/MatDefs/Misc/Unshaded.j3md");+ +
+ Applying a texture to the material: -<code java> -mat_brick.setTexture("ColorMap", + +
+mat_brick.setTexture("ColorMap", assetManager.loadTexture("Textures/Terrain/BrickWall/BrickWall.jpg"));
@@ -139,7 +142,7 @@ rootNode.attachChild(scene); - +
assets/Sound/
directory of your project. j
-
The main class to look at is com.jme3.audio.AudioNode
.
-By default, a new audio node is buffered, i.e. JME loads the whole file into memory before playing:
AudioNode boom = new AudioNode(assetManager, "Sound/boom.wav");+
AudioNode boom = new AudioNode(assetManager, "Sound/boom.wav");+
AudioNode music = new AudioNode(assetManager, "Sound/music.wav", true);+
+
AudioNode Method | Usage | +
---|---|
getStatus() | Returns either Status.Playing, Status.Stopped, or Status.Paused. | +
getVolume() | Returns the volume. | +
getPitch() | Returns the pitch. | +
+There are other obvious getters to poll the status of corresponding setters below.
-AudioNode music = new AudioNode(assetManager, "Sound/music.wav", true);
AudioNode Method | Usage | ||
---|---|---|---|
setLooping(false) | Configures the sound that, if it is played, it plays once and stops. This is the default. | +setLooping(false) | Configures the sound so that, if it is played, it plays once and stops. This is the default. |
setLooping(true) | 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. | +setLooping(true) | 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. +Does not work for streamed sounds! |
setPositional(false) @@ -70,7 +91,7 @@ setDirectional(false) | All 3D effects switched off. This sound is global | setMaxDistance(100f) | Maximum distance the sound can be heard, in world units. Default is 20. |
AudioNode Method | Usage | Activates 3D audio: The sound appears to come f | setReverbEnabled(true) | 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. |
---|
AudioNode Method | Usage | Activates 3D audio: This sound can only be heard from setOuterAngle() | 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! |
---|
c
Closet 1.00f 1.0f 1.0f 1.00f 0.15f 1.0f 0.600f 0.0025f 0.500f 0.0006f
Activate the preset with setEnvironment(). E.g. in a dungeon environment:
@@ -179,7 +200,7 @@ A sound engineer can create a custom
-You can find more info about OpenAL and its advanced features here:
+You can find more info about OpenAL and its advanced features here: . It depends on the hardware whether audio effects are supported (if not, you get the message
+
This class can be found under
-Usage: Your custom subclass implements the three methods
+
+The pivot point's position will be at
Specify the following parameters for each joint:
diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/monkey_zone.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/monkey_zone.html
index 8c8cbc02b..1ae5ddb95 100644
--- a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/monkey_zone.html
+++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/monkey_zone.html
@@ -152,9 +152,9 @@ To implement autonomous AI players MonkeyZone uses a system of Commands that are
-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:
@@ -138,49 +138,51 @@ Before you can create a Physics Control, you must create a Collision Shape from
-Tip: 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:
+
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:
-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.
-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.
-Tip: 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:
+com.jme3.audio.Environment
OpenAL EFX not available! Audio effects won't work.
)
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
com.jme3.scene.control.AbstractControl
.
@@ -163,43 +175,59 @@ This class can be found under
com.jme3.scene.control.AbstractControl
controlUpdate()
, controlRender()
, and cloneForSpatial()
as shown here:
+Usage: Your custom subclass implements the three methods controlUpdate()
, controlRender()
, setSpatial()
, and cloneForSpatial()
as shown here:
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
}
+
@Override
protected void controlUpdate(float tpf){
if(spatial != null && thing != null) {
// Implement your custom control here ...
- // Change scene graph etc
+ // Change scene graph, access and modify userdata in the spatial, etc
}
}
+
@Override
protected void controlRender(RenderManager rm, ViewPort vp){
- // optional rendering manipulation (advanced)
+ // optional rendering manipulation (for advanced users)
}
+
@Override
public Control cloneForSpatial(Spatial spatial){
final MyControl control = new MyControl(...);
control.setSpatial(spatial);
return control;
}
+
@Override
public void read(JmeImporter im) throws IOException {
super.read(im);
// im.getCapsule(this).read(...);
}
+
@Override
public void write(JmeExporter ex) throws IOException {
super.write(ex);
// ex.getCapsule(this).write(...);
}
+
}
Light and Shadows
(0,0,0)
in the global 3D space. In A's local space that is at (0,0,0)
and in B's local space (remember B's position was set to (0,-1,0)
) that is at (0,1,0)
.
+
com.jme3.shadow.PssmShadowR
...
public void simpleInitApp() {
....
- pssmRenderer = new PssmShadowRenderer(
- assetManager,1024,4,PssmShadowRenderer.EDGE_FILTERING_PCF);
+ pssmRenderer = new PssmShadowRenderer(assetManager, 1024, 3);
pssmRenderer.setDirection(new Vector3f(-1, -1, -1).normalizeLocal());
viewPort.addProcessor(pssmRenderer);
@@ -195,14 +194,6 @@ The constructor expects the following values:
-
-
-
-
Shape Purpose
+ Shape Usage Examples
-
BoxCollisionShape Box shaped objects such as bricks, crates, simple obstacles. Does not roll.
+ BoxCollisionShape Box shaped entities Does not roll. Bricks, crates, simple oblong entities.
-
SphereCollisionShape Spherical objects such as balls. Can roll.
+ SphereCollisionShape Spherical entities. Can roll. Balls, simple compact entities.
-
CylinderCollisionShape Tube-shaped pillars, disc-shaped wheels. Can roll on one side.
+ CylinderCollisionShape Tube-shaped and disc-shaped entities. Can roll on one side. Pillars, wheels.
-
CapsuleCollisionShape 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.
+ CapsuleCollisionShape A compound of a cylinder plus two spheres at the top and bottom. Is locked to stay upright, does not roll. 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.
-
CompoundCollisionShape A CompoundCollisionShape allows custom combinations of box/sphere/cylinder shapes to form another more complex shape.
+ CompoundCollisionShape A CompoundCollisionShape allows custom combinations of box/sphere/cylinder shapes to form another more complex shape. Complex shapes.
-
MeshCollisionShape A free-form mesh-accurate shape that wraps itself around a mesh.
+
-Limitations: 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. MeshCollisionShape A free-form mesh-accurate shape that wraps itself around a static entity.
+Limitations: Only non-mesh collision shapes (sphere, box, cylinder, compound) can collide with mesh-accurate collision shapes. Only works for static obstacles. A whole static game level model.
-
GImpactCollisionShape This free-form Mesh Collision Shape can be used for moving objects. Uses . Limitations: CPU intensive, use sparingly! We recommend using HullCollisionShapes or CompoundShapes made of simple shapes if you need improved performance.
+ GImpactCollisionShape This free-form Mesh Collision Shape that wraps itself around dynamically moving entities. Uses .
+Limitations: CPU intensive, use sparingly! We recommend using HullCollisionShapes or CompoundShapes made of simple shapes if you need improved performance. Physics simulation of a complex object.
-
HeightFieldCollisionShape Optimized Mesh Collision Shape for static terrains. This shape is much faster than a other Free-Form Mesh Shapes. Requires heightmap data.
+ HeightFieldCollisionShape Optimized Mesh Collision Shape for static terrains. This shape is much faster than a other Free-Form Mesh Shapes. Requires heightmap data. Optimized for terrains.
-
HullCollisionShape A collision shape that is based on a mesh but is a simplified convex version.
+ HullCollisionShape A collision shape that is based on a mesh but is a simplified convex version. …
-
SimplexCollisionShape A physical point, line, triangle, or quad Collision Shape, defined by one to four points.
+ SimplexCollisionShape A physical point, line, triangle, or quad Collision Shape, defined by one to four points. Guardrails
-
PlaneCollisionShape A 2D plane that can be used as flat solid floor or wall.
+ PlaneCollisionShape A 2D plane Flat solid floor or wall.
+bulletAppState.getPhysicsSpace().enableDebug(assetManager);
+bulletAppState.getPhysicsSpace().enableDebug(assetManager);
CompoundCollisionShape myComplexShape =
@@ -218,7 +220,7 @@ SphereCollisionShape, BoxCollisionShape, CapsuleCollisionShape are also not mesh
@@ -226,23 +228,23 @@ BulletPhysics are available in jME3 through Bullet Physics Controls from the com
Physics Control Purpose
-
RigidBodyControl 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.
+ RigidBodyControl 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…
-
CharacterControl 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).
+ CharacterControl 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).
-
GhostControl A GhostControl is a PhysicsControl that detects overlaps with other physical objects. A GhostControl is non-solid 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.
+ GhostControl Use for collision and intersection detection between physical entities. A GhostControl is non-solid 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.
VehicleControl
-PhysicsVehicleWheel Implements terrestric vehicle behaviour.
+PhysicsVehicleWheel Use for vehicles such as cars, tanks, hover crafts, ships, motorcycles.
-
RagDollControl Implements Ragdoll behaviour.
+ RagDollControl Use for collapsing, flailing, or loosely falling characters or with a Ragdoll (or puppet-on-strings) behaviour.
PhysicsControls Code Samples
@@ -273,7 +275,12 @@ model.addControl(character_phys);
bulletAppState.getPhysicsSpace().add(character_phys);
+For example, the following creates a box with the correct Box Collision Shape:
Box(1,1,1); myBox.addControl(new RigidBodyControl( 1.0f )); // implicit BoxCollisionShape @@ -286,7 +293,7 @@ bulletAppState.getPhysicsSpace().add(myBox);
-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.
bulletAppState.getPhysicsSpace().setGravity(new Vector3f(0f,-1f,0f)); @@ -306,7 +313,7 @@ bulletAppState.getPhysicsSpace().setAccuracy(0.005f);
-You remove physical objects from the scene like this: +You remove physical entities from the scene by removing their PhysicsControl from the PhysicsSpace and also their Spatial from the rootNode:
bulletAppState.getPhysicsSpace().remove(myPhysicsControl); @@ -314,7 +321,7 @@ myModel.removeFromParent();
@@ -326,50 +333,56 @@ On a PhysicsControl, you can set the following physical properties.
CharacterControl Method | Property | ||
---|---|---|---|
setFallSpeed(1f) | Fall speed (down) | +setUpAxis(1) | CharacterControls have a fixed upward axis! This means they cannot fall over. +Values: 0 = X axis , 1 = Y axis , 2 = Z axis. +Default: 1, because for characters and vehicle, up is typically along the Y axis. |
setJumpSpeed(1f) | Jump speed (up) | +setJumpSpeed(1f) | Jump speed (movement along up axis) |
setMaxSlope(1.5f) | How steep the slopes are that the character can still climb. | +setFallSpeed(1f) | Fall speed (movement along negative up axis) |
setUpAxis(1) | 0 = X axis , 1 = Y axis , 2 = Z axis. E.g. for characters and vehicle, up is usually along the the Y axis. | +setMaxSlope(1.5f) | 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. |
setGravity(1f) | You can change the Gravity of a physics object after it was added to the physics space | +setGravity(1f) | The intensity of gravity for this CharacterControl'ed entity. To change the direction of gravity for a character, modify the up axis. |
Property | Static | Dynamic | Kinematic | +Property | Static | Kinematic | Dynamic |
---|---|---|---|---|---|---|---|
Does it have a mass? | no, 0f | yes, >0f | yes, >0f (Inertia is calculated for kinematic objects you need mass to do that) | +Examples | Immobile obstacles: Floors, walls, buildings, … | Remote-controlled entities: Airships, meteorites, doors; networked or remote-controlled NPCs; invisible "airhooks" for hinges and joints. | Interactive entities: Rolling balls, movable crates, falling pillar, space ship… |
How does it move? | never | setWalkDirection(), setLinearVelocity(), applyForce(), etc | setLocalTranslation(), move() | +Does it have a mass? | no, 0.0f | yes1), >0.0f | yes, >0.0f |
Can it move and push others? | no | yes | yes | +How does it move? | never | setLocalTranslation(); | setLinearVelocity(); applyForce(); +setWalkDirection(); for CharacterControl |
Is is affected by forces? -(Falls when it mid-air? Can be pushed by others?) | no | yes | no | +How to place in scene? | setPhysicsLocation(); +setPhysicsRotation() | setLocalTranslation(); +setLocalRotation(); | setPhysicsLocation(); + setPhysicsRotation() |
+
Can it move and push others? | no | yes | yes | ||||
Examples | Immobile obstacles: Floor, wall, buildings, … | Interactive objects: Soccer ball, movable crate, falling pillar, … | Remote-controlled objects: Airship, meteorites, networked NPCs, invisible "airhooks" for hinges and joints. | + Is is affected by forces? +(Falls when it mid-air? Can be pushed by others?) | no | no | yes |
How to activate? | setMass(0f), (By default, objects are not kinematics) | setMass(1f), setKinematic(false) | setMass(1f), setKinematic(true) | +How to activate? | setMass(0f); +setKinematic(false); | setMass(1f); +setKinematic(false); | setMass(1f); +setKinematic(true); |
- -Tip: 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 hinges and joints. - +
airhook.setKinematic(true);-
-Use the following methods to move physics objects. +Use the following methods to move physics entities.
PhysicsControl Method | Motion | ||
---|---|---|---|
setLinearVelocity(new Vector3f(0f,0f,1f)) | Set the linear speed of this object. | +setLinearVelocity(new Vector3f(0f,0f,1f)) | Set the linear speed of this entity. |
setAngularVelocity(new Vector3f(0f,0f,1f)) | Set the rotational speed of the object; the x, y and z component are the speed of rotation around that axis. | +setAngularVelocity(new Vector3f(0f,0f,1f)) | Set the rotational speed of the entity; the x, y and z component are the speed of rotation around that axis. |
applyCentralForce(…) | Move (push) the object once with a certain moment, expressed as a Vector3f. | +applyCentralForce(…) | Move (push) the entity once with a certain moment, expressed as a Vector3f. |
applyForce(…) | 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. | +applyForce(…) | 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. |
applyTorque(…) | Rotate (twist) the object once around its axes, expressed as a Vector3f. | +applyTorque(…) | Rotate (twist) the entity once around its axes, expressed as a Vector3f. |
applyImpulse(…) | An idealised change of momentum. This is the kind of push that you would use on a pool billiard ball. | @@ -460,10 +481,11 @@ Use the following methods to move physics objects.clearForces() | Cancels out all forces (force, torque) etc and stops the motion. |
-Note: 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. +
@@ -480,7 +502,7 @@ PhysicsControls also supports the following features:
-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 SDK. +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 SDK.
@@ -53,5 +53,66 @@ You can save and load scenes and individual Nodes using com.jme3.export.binary.B ... + + +
+
+If you have a custom class that you want to save or assign using setUserData()
, the class must implement the com.jme3.export.Savable
interface.
+
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 { + OutputCapsule capsule = ex.getCapsule(this); + capsule.write(someIntValue, "someIntValue", 1); + capsule.write(someFloatValue, "someFloatValue", 0f); + capsule.write(someJmeObject, "someJmeObject", new Material()); + } + + public void read(JmeImporter im) throws IOException { + InputCapsule capsule = im.getCapsule(this); + someIntValue = capsule.readInt( "someIntValue", 1); + someFloatValue = capsule.readFloat( "someFloatValue", 0f); + someJmeObject = capsule.readSavable("someJmeObject", new Material()); + } +}+ +
+For each class field that you want to save and load, +
+write()
s the data to the JmeExport output capsule. read…()
s the data to the JmeImport input capsule. capsule.read…()
method for the data type. Specify the String name of the variable (must be the same ones that you used in the write() method
) and a default value.@@ -180,6 +182,10 @@ The default android run target uses the default device set in the Android config Optionally, download
++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. +
+-Prerequisites: This tutorial assumes that: +Prerequisites: This tutorial assumes that you have .
-+In this tutorial series, we assume that you use the jMonkeyEngine SDK. 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 command line. +
+ ++OK, let's get ready to create our first jMonkeyEngine3 application. +
+ + + ++ +In the jMonkeyEngine SDK: +
+jMonkeyProjects
directory in your home directory.-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 SDK, NetBeans, Eclipse, or run them straight from the commandline. In the following, we will use the jMonkeyEngine SDK. +If you have questions, read more about Project Creation here. +
+ ++
jme3test.helloworld
samples (and many others). For example, you can use the JmeTests project to verify whether you got the solution right.
+
-Create a jme3test.helloworld
package and a file HelloJME3.java
in it.
+For this tutorial, you want to create a jme3test.helloworld
package in your project, and create a file HelloJME3.java
in it.
-In the jMonkeyEngine SDK, you right-click the Source Packages node: +In the jMonkeyEngine SDK:
-New… > Java Class
to create a new file.HelloJME3
HelloJME3
jme3test.helloworld
jme3test.helloworld
. +The SDK creates the file HelloJME3.java for you. +
-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.
-Congratulations, it works! How did we do that? +Congratulations! Now let's find out how it works!
@@ -110,7 +149,42 @@ Congratulations, it works! How did we do that?-The code above has initialized the scene, and started the game. +The code above has initialized the scene, and started the application. +
+ + + +
+
+Look at the first line. The HelloJME3.java class extends com.jme3.app.SimpleApplication
.
+
public class HelloJME3 extends SimpleApplication { + // your code... +}+ +
+Every JME3 game is an instance of com.jme3.app.SimpleApplication
. 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!
+
+You start every JME3 game from the main() method, as every standard Java application: +
+SimpleApplication
-based classstart()
method to start the game engine. public static void main(String[] args){ + HelloJME3 app = new HelloJME3(); // instantiate the game + app.start(); // start the game! + }+ +
+This code opens your application window. Let's learn how you put something into the window next.
What you want to do | How you say it in JME3 terminology | +What you want to do | How you say that in JME3 terminology | +
---|---|---|---|
You want to create a cube. | I create a Geometry with a 1x1x1 Box shape. | ||
You want to create a cube. | You create a Geometry with a 1x1x1 Box shape. | +You want to use a blue color. | I create a Material with a blue Color property. |
You want to use a blue color. | You create a Material with a blue Color property. | +You want to colorize the cube blue. | I set the Material of the Box Geometry. |
You want to colorize the cube blue. | You set the Geometry's Material. | +You want to add the cube to the scene. | I attach the Box Geometry to the rootNode. |
You want the cube to appear in the scene. | You attach the cube to the rootNode. | +You want the cube to appear in the center. | I create the Box at the origin = at Vector3f.ZERO . |
+ +If you are unfamiliar with the vocabulary, read more about the Scene Graph here. +
+
-In Java, the creation of a blue cube looks as follows:
+Look at rest of the code sample. The simpleInitApp()
method is automatically called once at the beginning when the application starts. Every JME3 game must have this method. In the simpleInitApp()
method, you load game objects before the game starts.
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... }
-In the simpleInitApp()
method, you create or load all game objects before the game starts. The simpleInitApp()
method is automatically called once at the beginning of every JME3 game.
+The initialization code of a blue cube looks as follows:
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 + }
A typical JME3 game has the following initialization process: @@ -168,23 +253,23 @@ A typical JME3 game has the following initialization process:
rootNode
.score
to 0, set health
to 100%, and so on.score
to 0, set health
to 100%, …
-
-The HelloJME3.java class extends com.jme3.app.SimpleApplication
, which is a subclass of com.jme3.app.Application
. Every JME3 game is an instance of com.jme3.app.SimpleApplication
.
-
-To run a JME3 game, you first instantiate your SimpleApplication
-based class, and then call its start()
method:
-
public static void main(String[] args){ - HelloJME3 app = new HelloJME3(); - app.start(); // start the game - }- -
-Typically you start a game from your Java application's main() method. -
- --These few lines of code simply display a static 3D cube. You can navigate around in this 3D scene. -
- -You have learned that a SimpleApplication is a good starting point because it provides you with:
-When developing a game application, you will now want to: +When developing a game application, you want to:
-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.
-Continue with the Hello Node 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 Hello Node tutorial, where you learn more details about how to initialize the game world, also known as the scene graph.
-We recommend downloading the - but of course you can also build the jMonkeyEngine yourself from the sources. You need Subversion installed. +We recommend downloading the - but of course you can also build the jMonkeyEngine yourself from the sources. In this case, you need the file version system installed (svn).
dist/jMonkeyEngine3.jar
and all JARs from the dist/lib
directory on the classpath.dist/lib
directory on the classpath.com.jme3.app.SimpleApplication
. +At the bottom left of every default SimpleGame, you see the StatsView 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. +
+ +In the application's simpleInitApp() method, call: +
-setDisplayFps(false); -setDisplayStatView(false);+
setDisplayFps(false); // to hide the FPS +setDisplayStatView(false); // to hide the statistics
UnsupportedOperationException: GLSL and OpenGL2 is required for the LWJGL renderer
), 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.) Settings Property (Input) | Description | Default | setUseJoysticks(true) | Activate optional joystick support | false |
---|
Settings Property (Audio) | Description | Default | setStereo3D(true) | Enable 3D stereo. This feature requires hardware support from the GPU driver. See . Currently, your everday user's hardware does not support this, so you can ignore it for now. | false |
---|
Settings Property (Branding) | Description | Default | This specifies the little a | setSettingsDialogImage("/path/to/splash.png") | A custom splashscreen image in the assets directory which is displayed when the settings dialog is shown. | "/com/jme3/app/Monkey.png" |
---|
-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.
mkdir HelloJME3/build mkdir HelloJME3/lib -cp jme3/jMonkeyEngine3.jar HelloJME3/lib -cp jme3/lib/*.* HelloJME3/lib+cp jme3/lib/*.* HelloJME3/lib
-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:
mkdir HelloJME3/build mkdir HelloJME3/lib -cp jme3/dist/jMonkeyEngine3.jar HelloJME3/lib -cp jme3/dist/*.* HelloJME3/lib+cp jme3/dist/*.* HelloJME3/lib
cd HelloJME3 -javac -d build -cp "lib/eventbus-1.4.jar:lib/j-ogg-oggd.jar:lib/j-ogg-vorbisd.jar:lib/jME3-lwjgl-natives.jar:lib/jMonkeyEngine3.jar:lib/jbullet.jar:lib/jheora-jst-debug-0.6.0.jar:lib/jinput.jar:lib/jme3test.jar:lib/jme3testdata.jar:lib/lwjgl.jar:lib/nifty-1.3-SNAPSHOT.jar:lib/nifty-default-controls-1.3-SNAPSHOT.jar:lib/nifty-examples-1.3-SNAPSHOT.jar:lib/nifty-style-black-1.3-SNAPSHOT.jar:lib/nifty-style-grey-1.0.jar:lib/stack-alloc.jar:lib/vecmath.jar:lib/xmlpull-xpp3-1.1.4c.jar:." src/hello/HelloJME3.java+javac -d build -cp "lib/eventbus-1.4.jar:lib/j-ogg-oggd.jar:lib/j-ogg-vorbisd.jar:lib/jME3-lwjgl-natives.jar:lib/jbullet.jar:lib/jinput.jar:lib/lwjgl.jar:lib/stack-alloc.jar:lib/vecmath.jar:lib/xmlpull-xpp3-1.1.4c.jar:lib/jME3-blender.jar:lib/jME3-core.jar:lib/jME3-desktop.jar:lib/jME3-jogg.jar:lib/jME3-plugins.jar:lib/jME3-terrain.jar:lib/jME3-testdata.jar:lib/jME3-niftygui.jar:lib/nifty-default-controls.jar:lib/nifty-examples.jar:lib/nifty-style-black.jar:lib/nifty.jar:." src/hello/HelloJME3.java
… and run it.
cd build -java -cp "../lib/eventbus-1.4.jar:../lib/j-ogg-oggd.jar:../lib/j-ogg-vorbisd.jar:../lib/jME3-lwjgl-natives.jar:../lib/jMonkeyEngine3.jar:../lib/jbullet.jar:../lib/jheora-jst-debug-0.6.0.jar:../lib/jinput.jar:../lib/jme3test.jar:../lib/jme3testdata.jar:../lib/lwjgl.jar:../lib/nifty-1.3-SNAPSHOT.jar:../lib/nifty-default-controls-1.3-SNAPSHOT.jar:../lib/nifty-examples-1.3-SNAPSHOT.jar:../lib/nifty-style-black-1.3-SNAPSHOT.jar:../lib/nifty-style-grey-1.0.jar:../lib/stack-alloc.jar:../lib/vecmath.jar:../lib/xmlpull-xpp3-1.1.4c.jar:." hello/HelloJME3+java -cp "../lib/eventbus-1.4.jar:../lib/j-ogg-oggd.jar:../lib/j-ogg-vorbisd.jar:../lib/jME3-lwjgl-natives.jar:../lib/jbullet.jar:../lib/jinput.jar:../lib/lwjgl.jar:../lib/stack-alloc.jar:../lib/vecmath.jar:../lib/xmlpull-xpp3-1.1.4c.jar:../lib/jME3-blender.jar:../lib/jME3-core.jar:../lib/jME3-desktop.jar:../lib/jME3-jogg.jar:../lib/jME3-plugins.jar:../lib/jME3-terrain.jar:../lib/jME3-testdata.jar:../lib/jME3-niftygui.jar:../lib/nifty-default-controls.jar:../lib/nifty-examples.jar:../lib/nifty-style-black.jar:../lib/nifty.jar:." hello/HelloJME3
Note: If you use Windows, the classpath separator is ";" instead of ":". diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/project_creation.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/project_creation.html index d3ecde1f7..0cb829358 100644 --- a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/project_creation.html +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/project_creation.html @@ -47,7 +47,7 @@ Let's have a look at the abstract project structure in the Project Explorer
Main.java
. Double click Main.java
to open it in the editor.+You may want to use external Java libraries in your jME project, for example content generators or artificial intelligence implementations. +
+ +Add the library to the global library list:
@@ -162,7 +164,7 @@ Add the library to a project:
-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 SDK will assist you with javadoc popups, code completion (ctrl-space) and source navigation (ctrl-click).
@@ -170,9 +172,9 @@ Thats it, your project can now use the external library.FIXME
, @todo, TODO.FIXME
, @todo, or TODO.JME3Tests
project.JME3Tests
project and choose Run.+ +The SDK contains Sample Code (read more). +
+ ++Open the Source Packages node of the JmeTests project. +
JME3Tests
project and choose Run. JME3 Tests
template.jMonkeyEngine3.jar
from the dist
dir of the compiled jme3 versiondist
dir of the compiled jme3 versionsrc
folder of the jme3 project in the "sources" tab