jMonkeyEngine 3.0 Beginner's Guide.pdf Code example problems

I’m sorry if this is in the wrong place or if this has been answered before, i did look around but did not find any solutions to this problem but basically i have been reading the JMonkeyEngine 3.0 Beginner’s Guide to learn JMonkeyEngine and it’s helping a lot but i have found that some of the examples appear to be incorrect, i have re-done the examples over and i still get the same problem.
I’m not sure if i got the wrong copy of the book, or i’m just being a real idiot and not doing it correctly,

a few bits and pieces of my code:

        /**
         * Create a cannon ball geometry and attach to scene graph.
         */
        Geometry ball_geo = new Geometry("cannon ball", ballMesh);
        ball_geo.setMaterial(stoneMat);
        rootNode.attachChild(ball_geo);
        /**
         * Position the cannon ball
         */
        ball_geo.setLocalTranslation(cam.getLocation());
        /**
         * Make the ball physcial with a mass > 0.0f
         */
        ballPhy = new RigidBodyControl(6f);
        /**
         * Add physical ball to physics space.
         */
        ball_geo.addControl(ballPhy);
        bulletAppState.getPhysicsSpace().add(ballPhy);
        /**
         * Accelerate the physcial ball to shoot it.
         */
        ballPhy.setLinearVelocity(cam.getDirection().mult(50));

    }

This is the shoot cannon ball method from the falling bricks example and it works (Method from IDE help window).

public void shootCannonBall() {
Geometry ballGeo = new Geometry("cannon ball", ballMesh);
ballGeo.setMaterial(stoneMat);
ballGeo.setLocalTranslation(cam.getLocation());
rootNode.attachChild(ballGeo);
ballPhy = new RigidBodyControl(5f);
ballPhy.setCcdSweptSphereRadius(.1f);
ballPhy.setCcdMotionThreshold(0.001f);
ballPhy.setLinearVelocity(cam.getDirection().mult(50));
ballGeo.addControl(ballPhy);
bulletAppState.getPhysicsSpace().add(ballPhy);
}

And this is the shoot cannon ball method from the book, when i try and execute this method it throws a null pointer exception at the ballPhy.setCcdSweptSphereRadius(.1f); method, i’m not too sure what is wrong so…

And then the physics town example also had problems, The book example was missing the thingPhy Variable and the thingGeo Variable from this small piece of code:

[java]bulletAppState.getPhysicsSpace().remove(thingPhy);
thingGeo.removeFromParent();[/java]

But then example from the IDE help window worked perfectly and did not seam to have these Variables,

so i’m not too use sure about this, any advice will be helpful, Thanks, Luke.

Also just a small side note i was wondering about changing the .j3o, .jm3d and other file extentions just for making a game feel more personal and then also changing the folder location of the asset pack, Thanks again.

re: “when i try and execute this method it throws a null pointer exception at the ballPhy.setCcdSweptSphereRadius(.1f); method”

No, it definitely does not. It may throw an exception inside that method but that line is definitely not throwing an NPE or you haven’t pasted the code correctly.

In general, if you want help with an exception then you will need to post the full stack trace so that we don’t have to guess which parts you’ve left out.

“Yo, I pirated your book, don’t know what I’m coding and want to change file endings inside the assets.jar to make my game more personal.” shakes head

re: “when i try and execute this method it throws a null pointer exception at the ballPhy.setCcdSweptSphereRadius(.1f); method”

No, it definitely does not. It may throw an exception inside that method but that line is definitely not throwing an NPE or you haven’t pasted the code correctly.

In general, if you want help with an exception then you will need to post the full stack trace so that we don’t have to guess which parts you’ve left out.

this is the entire output:

Jul 22, 2014 12:55:06 AM com.jme3.system.JmeDesktopSystem initialize
INFO: Running on jMonkeyEngine 3.0.10
Jul 22, 2014 12:55:06 AM com.jme3.system.Natives extractNativeLibs
INFO: Extraction Directory: C:\Users\Melaia\.jmonkeyplatform\assetpacks\FallingBricks
Jul 22, 2014 12:55:09 AM com.jme3.system.lwjgl.LwjglContext printContextInitInfo
INFO: Lwjgl 2.9.0 context running on thread LWJGL Renderer Thread
Jul 22, 2014 12:55:09 AM com.jme3.system.lwjgl.LwjglContext printContextInitInfo
INFO: Adapter: igdumdim64
Jul 22, 2014 12:55:09 AM com.jme3.system.lwjgl.LwjglContext printContextInitInfo
INFO: Driver Version: 9.18.10.3257
Jul 22, 2014 12:55:09 AM com.jme3.system.lwjgl.LwjglContext printContextInitInfo
INFO: Vendor: NVIDIA Corporation
Jul 22, 2014 12:55:09 AM com.jme3.system.lwjgl.LwjglContext printContextInitInfo
INFO: OpenGL Version: 4.4.0
Jul 22, 2014 12:55:09 AM com.jme3.system.lwjgl.LwjglContext printContextInitInfo
INFO: Renderer: GeForce GT 630M/PCIe/SSE2
Jul 22, 2014 12:55:09 AM com.jme3.system.lwjgl.LwjglContext printContextInitInfo
INFO: GLSL Ver: 4.40 NVIDIA via Cg compiler
Jul 22, 2014 12:55:09 AM com.jme3.asset.AssetConfig loadText
WARNING: Cannot find loader com.jme3.scene.plugins.blender.BlenderModelLoader
Jul 22, 2014 12:55:09 AM com.jme3.audio.lwjgl.LwjglAudioRenderer initInThread
INFO: Audio Device: OpenAL Soft
Jul 22, 2014 12:55:09 AM com.jme3.audio.lwjgl.LwjglAudioRenderer initInThread
INFO: Audio Vendor: OpenAL Community
Jul 22, 2014 12:55:09 AM com.jme3.audio.lwjgl.LwjglAudioRenderer initInThread
INFO: Audio Renderer: OpenAL Soft
Jul 22, 2014 12:55:09 AM com.jme3.audio.lwjgl.LwjglAudioRenderer initInThread
INFO: Audio Version: 1.1 ALSOFT 1.15.1
Jul 22, 2014 12:55:09 AM com.jme3.audio.lwjgl.LwjglAudioRenderer initInThread
INFO: AudioRenderer supports 64 channels
Jul 22, 2014 12:55:09 AM com.jme3.audio.lwjgl.LwjglAudioRenderer initInThread
INFO: Audio effect extension version: 1.0
Jul 22, 2014 12:55:09 AM com.jme3.audio.lwjgl.LwjglAudioRenderer initInThread
INFO: Audio max auxilary sends: 4
Jul 22, 2014 12:55:15 AM com.jme3.app.Application handleError
SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]
java.lang.NullPointerException
	at com.jme3.bullet.objects.PhysicsRigidBody.setCcdSweptSphereRadius(PhysicsRigidBody.java:280)
	at mygame.Main.shootCannonBall(Main.java:176)
	at mygame.Main$1.onAction(Main.java:46)
	at com.jme3.input.InputManager.invokeActions(InputManager.java:169)
	at com.jme3.input.InputManager.onMouseButtonEventQueued(InputManager.java:433)
	at com.jme3.input.InputManager.processQueue(InputManager.java:833)
	at com.jme3.input.InputManager.update(InputManager.java:883)
	at com.jme3.app.Application.update(Application.java:604)
	at com.jme3.app.SimpleApplication.update(SimpleApplication.java:231)
	at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:151)
	at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:185)
	at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:228)
	at java.lang.Thread.run(Thread.java:744)

BUILD SUCCESSFUL (total time: 17 seconds)

This is the whole application:

package mygame;

import com.jme3.app.SimpleApplication;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.input.MouseInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.MouseButtonTrigger;
import com.jme3.light.AmbientLight;
import com.jme3.light.DirectionalLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.shape.Box;
import com.jme3.scene.shape.Sphere;
import com.jme3.scene.shape.Sphere.TextureMode;

//Busy on page 177
public class Main extends SimpleApplication{

    private BulletAppState bulletAppState;
    //
    private Material brickMat, stoneMat, woodMat;
    //
    private static final Sphere ballMesh;
    private static final Box brickMesh;
    private static final Box floorMesh;
    //
    private static Node wallNode;
    //
    private RigidBodyControl brickPhy, ballPhy, floorPhy;
    //
    private static final float BRICK_LENGTH = 0.4F, BRICK_WIDTH = 0.3F,
            BRICK_HEIGHT = 0.25F, WALL_WIDTH = 12, WALL_HEIGHT = 6;
    //
    private static final String SHOOT = "shoot";
    //
    private ActionListener actionListener = new ActionListener(){

        public void onAction(String name, boolean isPressed, float tpf){
            if(name.equals(SHOOT) && !isPressed){
                shootCannonBall();
            }
        }

    };

    static{
        floorMesh = new Box(Vector3f.ZERO, 10F, 0.5F, 5F);
        brickMesh = new Box(Vector3f.ZERO, BRICK_LENGTH, BRICK_HEIGHT, BRICK_WIDTH);
        ballMesh = new Sphere(32, 32, 0.25f, true, false);
        ballMesh.setTextureMode(TextureMode.Projected);
        floorMesh.scaleTextureCoordinates(new Vector2f(4, 4));

    }

    public static void main(String[] args){
        Main app = new Main();
        app.start();
    }

    @Override
    public void simpleInitApp(){

        inputManager.addMapping(SHOOT, new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
        inputManager.addListener(actionListener, SHOOT);

        flyCam.setMoveSpeed(10.5F);
        cam.setLocation(new Vector3f(0, 5, 0));
        bulletAppState = new BulletAppState();
        stateManager.attach(bulletAppState);

        brickMat = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");
        stoneMat = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");
        woodMat = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");

        brickMat.setTexture("DiffuseMap", assetManager.loadTexture("Textures/Brick.png"));
        stoneMat.setTexture("DiffuseMap", assetManager.loadTexture("Textures/Pebbles.png"));
        woodMat.setTexture("DiffuseMap", assetManager.loadTexture("Textures/Bark.png"));

        brickMat.getAdditionalRenderState().setAlphaTest(true);
        brickMat.getAdditionalRenderState().setAlphaFallOff(5.5F);

        stoneMat.getAdditionalRenderState().setAlphaTest(true);
        stoneMat.getAdditionalRenderState().setAlphaFallOff(5.5F);

        woodMat.getAdditionalRenderState().setAlphaTest(true);
        woodMat.getAdditionalRenderState().setAlphaFallOff(5.5F);

        Geometry floorGeo = new Geometry("Floor", floorMesh);
        floorGeo.setMaterial(woodMat);
        floorGeo.move(0f, -BRICK_HEIGHT * 2F, 0f);
        rootNode.attachChild(floorGeo);
        floorPhy = new RigidBodyControl(0.0f);
        floorGeo.addControl(floorPhy);
        bulletAppState.getPhysicsSpace().add(floorPhy);

        wallNode = new Node("Wall");
        float offsetH = BRICK_LENGTH / 3;
        float offsetV = 0;
        for(int j = 0; j < WALL_HEIGHT; j++){
            for(int i = 0; i < WALL_WIDTH; i++){
                Vector3f brickPos = new Vector3f(offsetH + BRICK_LENGTH * 2.1f * i - (BRICK_LENGTH * WALL_WIDTH), offsetV + BRICK_HEIGHT, 0f);
                wallNode.attachChild(makeBrick(brickPos));
            }
            offsetH = -offsetH;
            offsetV += 2 * BRICK_HEIGHT;
        }
        rootNode.attachChild(wallNode);

        DirectionalLight sun = new DirectionalLight();
        sun.setDirection(new Vector3f(1, 0, -2));
        sun.setColor(ColorRGBA.White);
        rootNode.addLight(sun);

        AmbientLight ambient = new AmbientLight();
        rootNode.addLight(ambient);

    }

    //<editor-fold defaultstate="collapsed" desc="Update method">
    @Override
    public void simpleUpdate(float tpf){
    }
    //</editor-fold>

    private Geometry makeBrick(Vector3f loc){
        Geometry brickGeo = new Geometry("brick", brickMesh);
        brickGeo.setMaterial(brickMat);
        wallNode.attachChild(brickGeo);
        brickGeo.move(loc);
        brickPhy = new RigidBodyControl(5f);
        brickGeo.addControl(brickPhy);
        bulletAppState.getPhysicsSpace().add(brickPhy);

        return brickGeo;
    }

    /*public void shootCannonBall(){
     * /**
     * Create a cannon ball geometry and attach to scene graph.
     */
    /*Geometry ball_geo = new Geometry("cannon ball", ballMesh);
    ball_geo.setMaterial(stoneMat);
    rootNode.attachChild(ball_geo);
    /**
     * Position the cannon ball
     */
    /*ball_geo.setLocalTranslation(cam.getLocation());
    /**
     * Make the ball physcial with a mass > 0.0f
     */
    /*ballPhy = new RigidBodyControl(6f);
    /**
     * Add physical ball to physics space.
     */
    /*ball_geo.addControl(ballPhy);
    bulletAppState.getPhysicsSpace().add(ballPhy);
    /**
     * Accelerate the physcial ball to shoot it.
     */
    /*ballPhy.setLinearVelocity(cam.getDirection().mult(50));
    
}*/
    
    public void shootCannonBall() {
Geometry ballGeo = new Geometry("cannon ball", ballMesh);
ballGeo.setMaterial(stoneMat);
ballGeo.setLocalTranslation(cam.getLocation());
rootNode.attachChild(ballGeo);
ballPhy = new RigidBodyControl(5f);
ballPhy.setCcdSweptSphereRadius(.1f);
ballPhy.setCcdMotionThreshold(0.001f);
ballPhy.setLinearVelocity(cam.getDirection().mult(50));
ballGeo.addControl(ballPhy);
bulletAppState.getPhysicsSpace().add(ballPhy);
}

}
“Yo, I pirated your book, don’t know what I’m coding and want to change file endings inside the assets.jar to make my game more personal.” *shakes head*

I’m sorry but i don’t quite understand you.

I had the same “Null Pointer Exception” when clicking the LMB to shoot a Cannonbal

My code is below, followed by the StackTrace

package mygame;

import com.jme3.asset.TextureKey;
import com.jme3.scene.Node;
import com.jme3.app.SimpleApplication;
import com.jme3.asset.plugins.ZipLocator;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.control.BetterCharacterControl;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.input.KeyInput;
import com.jme3.input.MouseInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.input.controls.MouseButtonTrigger;
import com.jme3.light.AmbientLight;
import com.jme3.light.DirectionalLight;
import com.jme3.light.PointLight;
import com.jme3.light.SpotLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Box;
import com.jme3.scene.shape.Sphere;
import com.jme3.util.TangentBinormalGenerator;
import com.jme3.post.FilterPostProcessor;
import com.jme3.post.filters.BloomFilter;
import com.jme3.scene.CameraNode;
import com.jme3.scene.control.CameraControl;
import com.jme3.scene.shape.Sphere.TextureMode;
import com.jme3.texture.Texture.WrapMode;
import java.awt.Color;


public class PhysicsFallingBricks extends SimpleApplication 
{

// Make this a physical game by attaching a BulletAppState instance.
private BulletAppState bulletAppState;

/*-------------------------------------------------------------------------------------
Prepare some class fields for the objects in your scene. The scene uses boxes for the
bricks, spheres for the cannon balls, and another box for the floor. You also prepare
fields for three materials and three RigidBodyControls.
*--------------------------------------------------------------------------------------*/

/** Materials for bricks, cannon balls, floor. */
Material brickMat, stoneMat, woodMat;

/** Meshes for bricks, cannon balls, floor. */

private static final Sphere ballMesh;
private static final Box brickMesh;
private static final Box floorMesh;
private static Node wallNode;

/** PhysicsControls for bricks, cannon balls, floor. */

private RigidBodyControl brickPhy;
public RigidBodyControl ballPhy;
private RigidBodyControl floorPhy;

/*-------------------------------------------------------------------
 * To keep the code more readable and extendable, let's declare a few constants for
the size of the bricks and the brick wall.
 --------------------------------------------------------------------*/

private static final float BRICK_LENGTH = 0.4f;
private static final float BRICK_WIDTH = 0.3f;
private static final float BRICK_HEIGHT = 0.25f;
private static final float WALL_WIDTH = 12;
private static final float WALL_HEIGHT = 6;


/*---------------------------------------------------------------------------------
 All bricks and all cannon balls use the same box and sphere shape, respectively,
 so go ahead and initialize the meshes in a static block.
* ---------------------------------------------------------------------------------------*/
      
static 
{
  floorMesh = new Box(Vector3f.ZERO, 10f, 0.5f, 5f);
  brickMesh = new Box(Vector3f.ZERO,
  BRICK_LENGTH, BRICK_HEIGHT, BRICK_WIDTH);
  ballMesh = new Sphere( 32, 32, 0.25f, true, false);
  ballMesh.setTextureMode(TextureMode.Projected);
  floorMesh.scaleTextureCoordinates( new Vector2f(4f,4f) );
}

public static void main(String[] args) {
    PhysicsFallingBricks app = new PhysicsFallingBricks();
    app.start();
  }

    @Override
    public void simpleInitApp() {
   
    
      bulletAppState = new BulletAppState();
      stateManager.attach(bulletAppState);

      /*-----------------------------------------------------------------
       * In the simpleInitApp() method, you initialize objects, and set up the scene.
         Create three .j3m files as you learned in the previous chapter (or use the sample
         materials provided with this book).
       ------------------------------------------------------------------*/
      
      brickMat =assetManager.loadMaterial("Materials/brick.j3m");
      stoneMat =assetManager.loadMaterial("Materials/Pebbles.j3m");
      woodMat =assetManager.loadMaterial("Materials/bark.j3m");
        
      /*------------------------------------------------------------------------
      Create a floor, a simple box geometry with a wood material and a
      RigidBodyControl. Since the floor is static, set its mass to zero. Move the floor
      a bit down to ensure it's below the lowest brick.
      ------------------------------------------------------------------------*/

      Geometry floorGeo = new Geometry("Floor", floorMesh);
      floorGeo.setMaterial(woodMat);
      floorGeo.move( 0f, - BRICK_HEIGHT *2f, 0f );
      rootNode.attachChild(floorGeo);

      /*---------------------------------------------
      // PhysicsControl with zero mass,
      // and default BoxCollisionShape:
      -----------------------------------------------*/
      
      floorPhy = new RigidBodyControl(0.0f);
      floorGeo.addControl(floorPhy);
      bulletAppState.getPhysicsSpace().add(floorPhy);
      
      /*----------------------------------------------------------------------
      Create a wall node that groups together several rows of brick geometries.
      The following loop calculates the offsets, and calls a makeBrick() method that
      returns brick geometries. In the end, you attach the wall node to the rootNode.
      *---------------------------------------------------------------------------*/ 

      wallNode=new Node("wall");
      float offsetH = BRICK_LENGTH / 3;
      float offsetV = 0;
      for (int j = 0; j < WALL_HEIGHT; j++) {
        for (int i = 0; i < WALL_WIDTH; i++) {
           Vector3f brickPos = new Vector3f(offsetH + BRICK_LENGTH * 2.1f * i
                                           - (BRICK_LENGTH*WALL_WIDTH),
                                              offsetV + BRICK_HEIGHT,0f );
           wallNode.attachChild(makeBrick(brickPos));
        }
        offsetH = -offsetH;
        offsetV += 2 * BRICK_HEIGHT;
      }
      rootNode.attachChild(wallNode);

      /*===================================================================
        In the simpleInitApp() method, register a SHOOT input mapping for the left
        mouse button. Register the SHOOT action to the actionListener.
       -------------------------------------------------------------------*/
      
      inputManager.addMapping(SHOOT,new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
      inputManager.addListener(actionListener, SHOOT);
      
      /*------------------------------------------
       * Add Light Sources
       -------------------------------------------*/
      
      DirectionalLight sun = new DirectionalLight();
      sun.setDirection(new Vector3f(1, -1, -2));
      sun.setColor(ColorRGBA.White);
      rootNode.addLight(sun);
      AmbientLight ambient = new AmbientLight();
      ambient.setColor(ColorRGBA.White.mult(5f));
      rootNode.addLight(ambient);
    }

    @Override
    public void simpleUpdate(float tpf) {
        //TODO: add update code
    }

    @Override
    public void simpleRender(RenderManager rm) {
        //TODO: add render code
    }
 
    /*--------------------------------------------------------------------------
    Implement the makeBrick() method to create the actual physical bricks, using the
    brickMesh shape and brickMat material. Position the brick geometry at its start
    position loc. Create a RigidBodyControl and specify a mass (here 5 kg), so the
    bricks become dynamic physical objects.
    *------------------------------------------------------------------------*/
    
    public Geometry makeBrick(Vector3f loc)
    {
      Geometry brickGeo = new Geometry("brick", brickMesh);
      brickGeo.setMaterial(brickMat);
      wallNode.attachChild(brickGeo);
      brickGeo.move(loc);
     
      // PhysicsControl with 5f mass, default BoxCollisionShape:
      
      brickPhy = new RigidBodyControl(5f);
      brickGeo.addControl(brickPhy);
      bulletAppState.getPhysicsSpace().add(brickPhy);
      return brickGeo;
   }
    
 /*---------------------------------------------------------------------------
    Write a shootCannonBall() method that creates a new physical
    geometry ballGeo from our ballMesh shape and stoneMat material.
    The setLinearVelocity() line defines the initial speed and direction
    of the object. In this case, we accelerate the cannon ball forward.
 ----------------------------------------------------------------------------*/
    
public void shootCannonBall()
{
  Geometry ballGeo = new Geometry("cannon ball", ballMesh);
  ballGeo.setMaterial(stoneMat);
  ballGeo.setLocalTranslation(cam.getLocation());
  rootNode.attachChild(ballGeo);
  ballPhy = new RigidBodyControl(5.0f);
  ballPhy.setCcdMotionThreshold(0.001f);
  ballPhy.setCcdSweptSphereRadius(0.1f);
  
  ballPhy.setLinearVelocity(cam.getDirection().mult(50));
  ballGeo.addControl(ballPhy);
  bulletAppState.getPhysicsSpace().add(ballPhy);
 }

/*-------------------------------------------------------------------------
Create an actionListener and a SHOOT string constant. Test whether a SHOOT
action was triggered. The SHOOT action calls the shootCannonBall() method.
---------------------------------------------------------------------------*/
private static final String SHOOT = "shoot";

private ActionListener actionListener = new ActionListener()
{
  public void onAction(String name, boolean keyPressed, float tpf) 
   {
     if (name.equals(SHOOT) && !keyPressed)
     {
        shootCannonBall();
     }
   }
    
 };

}
Mar 07, 2015 10:30:04 AM com.jme3.app.Application handleError
SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]
java.lang.NullPointerException
	at com.jme3.bullet.objects.PhysicsRigidBody.setCcdMotionThreshold(PhysicsRigidBody.java:289)
	at mygame.PhysicsFallingBricks.shootCannonBall(PhysicsFallingBricks.java:224)
	at mygame.PhysicsFallingBricks$1.onAction(PhysicsFallingBricks.java:244)
	at com.jme3.input.InputManager.invokeActions(InputManager.java:169)
	at com.jme3.input.InputManager.onMouseButtonEventQueued(InputManager.java:433)
	at com.jme3.input.InputManager.processQueue(InputManager.java:833)
	at com.jme3.input.InputManager.update(InputManager.java:883)
	at com.jme3.app.Application.update(Application.java:604)
	at com.jme3.app.SimpleApplication.update(SimpleApplication.java:231)
	at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:151)
	at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:185)
	at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:228)
	at java.lang.Thread.run(Thread.java:744)

OK, I have the answer.

The book specified the following code

public void shootCannonBall() {
Geometry ballGeo = new Geometry("cannon ball", ballMesh);
ballGeo.setMaterial(stoneMat);
ballGeo.setLocalTranslation(cam.getLocation());
rootNode.attachChild(ballGeo);
ballPhy = new RigidBodyControl(5f);
ballPhy.setCcdSweptSphereRadius(.1f);
ballPhy.setCcdMotionThreshold(0.001f);
ballPhy.setLinearVelocity(cam.getDirection().mult(50));
ballGeo.addControl(ballPhy);
bulletAppState.getPhysicsSpace().add(ballPhy);
}

The line

ballGeo.addControl(ballPhy);

must be moved to immediately after the line

ballPhy = new RigidBodyControl(5f);

and before

ballPhy.setCcdSweptSphereRadius(.1f);

For the love of god and his infinite wisdom, PLEASE learn how to put your code in code parenthesis.

I edited like nine million posts to make this topic pretty. That’s an excessive amount of edits. Please don’t make me do it again.

I think we really need a button for it at least… the pre thing doesn’t really work and the back-ticks are non-obvious.

1 Like

This topic is now unlisted. It will no longer be displayed in any topic lists. The only way to access this topic is via direct link.