AnimControl null pointer exception

Good afternoon everyone! I am working on a zombie hunting humans game and I am almost done though I have run into a problem with the animation.

[java]testHuman = assetManager.loadModel(“Models/new_thin_zombie.j3o”);
testHuman.setMaterial(zombieMaterial);
testHuman.scale(.5f);
testHuman.setLocalTranslation(0, 0, 0);
humanNode.attachChild(testHuman);

    humanControl = testHuman.getControl(AnimControl.class);
    humanControl.addListener(this);
    humanChannel = humanControl.createChannel();
    humanChannel.setAnim("walk", 0);[/java] 

This is where I am having the problems at.

At the “humanControl.addListener(this);” line I get this null pointer exception:

[java]SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]
java.lang.NullPointerException
at mygame.Main.simpleInitApp(Main.java:109)
at com.jme3.app.SimpleApplication.initialize(SimpleApplication.java:225)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.initInThread(LwjglAbstractDisplay.java:130)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:207)
at java.lang.Thread.run(Thread.java:722)[/java]

Here is the code for the entire class if that would help and if any other code from the other classes is necessary just ask:

[java]package mygame;

import com.jme3.animation.AnimChannel;
import com.jme3.animation.AnimControl;
import com.jme3.animation.AnimEventListener;
import com.jme3.animation.LoopMode;
import com.jme3.app.SimpleApplication;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.collision.shapes.CollisionShape;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.bullet.util.CollisionShapeFactory;
import com.jme3.font.BitmapText;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.post.FilterPostProcessor;
import com.jme3.post.filters.FogFilter;
import com.jme3.renderer.RenderManager;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.texture.Texture;
import com.jme3.water.SimpleWaterProcessor;

/**

  • test

  • @author Benzoate
    */
    public class Main extends SimpleApplication implements AnimEventListener{

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

    static BulletAppState bulletAppState;
    BitmapText hud;

    static Spatial world;
    static Node worldNode, humanNode, zombieNode;
    static Spatial waterPlane;
    static SimpleWaterProcessor waterProcessor;

    static Material zombieMaterial, humanMaterial;
    static Texture zombieTexture, humanTexture;
    FogFilter fog;
    FilterPostProcessor fpp;
    static float zombieMoan = 0;
    static int humansLeft = 6;

    static Spatial testHuman;
    static AnimControl humanControl;
    static AnimChannel humanChannel;

    @Override
    public void simpleInitApp() {
    bulletAppState = new BulletAppState();
    stateManager.attach(bulletAppState);
    viewPort.setBackgroundColor(ColorRGBA.DarkGray);
    fpp = new FilterPostProcessor(assetManager);
    fog = new FogFilter();
    fog.setFogColor(new ColorRGBA(0.9f, 0.9f, 0.9f, 1.0f));
    fog.setFogDistance(25);
    fog.setFogDensity(.8f);
    fpp.addFilter(fog);
    viewPort.addProcessor(fpp);
    hud = new BitmapText(guiFont, false);

     cam.setLocation(new Vector3f(100, 5, -100));
     Quaternion camRotation = new Quaternion();
     camRotation.fromAngleAxis(-FastMath.PI/2, new Vector3f(0, 1, 0));
     cam.setRotation(camRotation);
     flyCam.setMoveSpeed(30);
     
     worldNode = new Node("WorldNode");
     humanNode = new Node("HumanNode");
     zombieNode = new Node("ZombieNode");
     worldNode.attachChild(zombieNode);
     worldNode.attachChild(humanNode);
     rootNode.attachChild(worldNode);
     
     initMaterials();
     initTerrain();
     initCrosshairs();
     initKeys();
     Sound.setSounds(assetManager);
     Path.initPaths(assetManager, rootNode);
     
     Player.makePlayer();
     Human.makeHuman(assetManager, humanNode, Path.path0, Path.time0);
     Human.makeHuman(assetManager, humanNode, Path.path1, Path.time1);
     Human.makeHuman(assetManager, humanNode, Path.path2, Path.time2);
     Human.makeHuman(assetManager, humanNode, Path.path3, Path.time3);
     Human.makeHuman(assetManager, humanNode, Path.path4, Path.time4);
     Human.makeHuman(assetManager, humanNode, Path.randomPath, Path.timeRandom);
     
     
     testHuman = assetManager.loadModel("Models/new_thin_zombie.j3o");
     testHuman.setMaterial(zombieMaterial);
     testHuman.scale(.5f);
     testHuman.setLocalTranslation(0, 0, 0);
     humanNode.attachChild(testHuman);
     
     humanControl = testHuman.getControl(AnimControl.class);
     humanControl.addListener(this);
     humanChannel = humanControl.createChannel();
     humanChannel.setAnim("walk", 0);
    

    }

    @Override
    public void simpleUpdate(float tpf) {
    Player.playerUpdate(cam, assetManager, humanNode, zombieNode, rootNode);
    listener.setLocation(cam.getLocation());
    listener.setRotation(cam.getRotation());

     zombieMoan += tpf;
     System.out.print(zombieMoan);
     if(zombieMoan > 12.696969){
         zombieMoan = 0;
         Sound.setSoundLocation(Sound.zombie, Player.playerControl.getPhysicsLocation());
         Sound.playSound(Sound.zombie);
     }
     hud();
    

    }

    private ActionListener actionListener = new ActionListener(){
    public void onAction(String binding, boolean isPressed, float tpf){
    if(binding.equals(“Left”) ){
    Player.left = isPressed;
    }
    if(binding.equals(“Right”)){
    Player.right = isPressed;
    }
    if(binding.equals(“Up”)){
    Player.up = isPressed;
    }
    if(binding.equals(“Down”)){
    Player.down = isPressed;
    }
    if(binding.equals(“Attack”)){
    Player.attack = isPressed;
    }
    if(binding.equals(“Location”)){
    Player.playerLocation = Player.playerControl.getPhysicsLocation();
    System.out.println(" addWayPoint(new Vector3f("+Player.playerLocation.x+"f, 0, "+Player.playerLocation.z+“f));”);
    }
    }
    };

    @Override
    public void simpleRender(RenderManager rm) {
    //TODO: add render code
    }

    public void onAnimCycleDone(AnimControl control, AnimChannel channel, String animName){
    if(animName.equals(“walk”)){
    channel.setAnim(“walk”, .5f);
    channel.setLoopMode(LoopMode.Loop);
    channel.setSpeed(1f);
    }
    }

    public void onAnimChange(AnimControl control, AnimChannel channel, String animName){

    }

    public void initMaterials(){
    zombieTexture = assetManager.loadTexture(“Materials/new_thin_zombie.png”);
    zombieMaterial = new Material(assetManager, “Common/MatDefs/Misc/Unshaded.j3md”);
    zombieMaterial.setTexture(“ColorMap”, zombieTexture);

     humanTexture = assetManager.loadTexture("Materials/new_thin_human.png");
     humanMaterial = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
     humanMaterial.setTexture("ColorMap", humanTexture);
    

    }

    public void initTerrain(){
    world = assetManager.loadModel(“Scenes/World.j3o”);
    CollisionShape worldCollision = CollisionShapeFactory.createMeshShape((Node) world);
    RigidBodyControl landscape = new RigidBodyControl(worldCollision, 0);
    world.addControl(landscape);
    worldNode.attachChild(world);
    bulletAppState.getPhysicsSpace().add(landscape);

     waterProcessor = new SimpleWaterProcessor(assetManager);
     waterProcessor.setReflectionScene(worldNode);
     viewPort.addProcessor(waterProcessor);
     
     waterPlane = waterProcessor.createWaterGeometry(75, 75);
     waterPlane.setLocalTranslation(50, -3, 90);
     waterPlane.setMaterial(waterProcessor.getMaterial());
     worldNode.attachChild(waterPlane);
    

    }

    public void initKeys(){
    inputManager.addMapping(“Left”, new KeyTrigger(KeyInput.KEY_A));
    inputManager.addListener(actionListener, “Left”);

     inputManager.addMapping("Right", new KeyTrigger(KeyInput.KEY_D));
     inputManager.addListener(actionListener, "Right");
     
     inputManager.addMapping("Up", new KeyTrigger(KeyInput.KEY_W));
     inputManager.addListener(actionListener, "Up");
     
     inputManager.addMapping("Down", new KeyTrigger(KeyInput.KEY_S));
     inputManager.addListener(actionListener, "Down");
     
     inputManager.addMapping("Attack", new KeyTrigger(KeyInput.KEY_SPACE));
     inputManager.addListener(actionListener, "Attack");
     
     inputManager.addMapping("Location", new KeyTrigger(KeyInput.KEY_F));
     inputManager.addListener(actionListener, "Location");
    

    }

    public void initCrosshairs(){
    setDisplayStatView(false);
    guiFont = assetManager.loadFont(“Interface/Fonts/Default.fnt”);
    BitmapText ch = new BitmapText(guiFont, false);
    ch.setSize(guiFont.getCharSet().getRenderedSize()*2);
    ch.setText("+");
    ch.setLocalTranslation(settings.getWidth()/2 - ch.getLineWidth()/2, settings.getHeight()/2 + ch.getLineHeight()/2, 0);
    guiNode.attachChild(ch);
    }

    public void hud(){
    guiFont = assetManager.loadFont(“Interface/Fonts/Default.fnt”);
    hud.setSize(guiFont.getCharSet().getRenderedSize()*2);
    hud.setText("Humans Remaining: "+humansLeft);
    hud.setLocalTranslation(0, 750, 0);
    guiNode.attachChild(hud);
    }
    }
    [/java]

Check your model in the Scene Explorer. The AnimControl is normally attached a few descendant children down.

@wezrule
I’m not using the scene explorer to put them into the world, I’m doing the humans and zombies exclusively through code

@Benzoat said: @wezrule I'm not using the scene explorer to put them into the world, I'm doing the humans and zombies exclusively through code

Well, you can look at them in the scene explorer or you can look at them in code. The scene explorer is an easy way to look regardless of how you load them normally. It doesn’t change your game any more than looking at your Java files in Notepad would.

…but it would tell you where your anim control is since it is is obviously not in the root of the model.

@pspeed said: Well, you can look at them in the scene explorer or you can look at them in code. The scene explorer is an easy way to look regardless of how you load them normally. It doesn't change your game any more than looking at your Java files in Notepad would.

…but it would tell you where your anim control is since it is is obviously not in the root of the model.

Oh that makes sense, I thought that he was suggesting loading the models into the scene directly, instead of code, then looking at it through scene explorer. Though I do not know how to view a scene composer based from the code if you would care to enlighten me?

@Benzoat said: Oh that makes sense, I thought that he was suggesting loading the models into the scene directly, instead of code, then looking at it through scene explorer. Though I do not know how to view a scene composer based from the code if you would care to enlighten me?

You can’t.

Method 1: open model in scene explorer, look at model hierarchy with eyes, find where the anim control is. Completion time roughly 10 seconds. Side-effects = 0.

Method 2: write code to traverse the scene graph starting at your model and dump all of the controls of all of the children, and their children, and so on. Completion time roughly much longer than 10 seconds. Side effects = bunch of extra code you don’t need anymore.