Trouble Updated HUD

Hello All,



I am new to JMonkey and have run into a problem while trying to update my HUD. I have been following the Nifty Gui Demo tutorials and I am getting null pointer exceptions when I try to update my screen.



I am able to change between screen fine with this code:

[java]

public void goToScreen(String nextScreen)

{

nifty.gotoScreen(nextScreen); // switch to another screen

// start the game and do some more stuff…



}

[/java]



Yet, in this code in the same class I get NULL pointer exceptions. Even though my update functions looks the same as the Nifty Gui Demo’s.



[java]

@Override

public void update(float tpf) {

/** jME update loop! */



// if (screen.getScreenId().equals(“hud”) && weapon1Clicked == true)

// {

// // load or create new image

// NiftyImage img = nifty.getRenderEngine().createImage(“Interface/Pistol.png”, false);

// // find old image

// Element niftyElement = nifty.getCurrentScreen().findElementByName(“CurrentWeapon”);

// // swap old with new image

// niftyElement.getRenderer(ImageRenderer.class).setImage(img);

// weapon1Clicked = false;

// }

[/java]





I appreciate any help I can get.

What’s the stack trace? (What line throws the NPE?).



Most likely you haven’t updated the screen member variable with the Nifty screen…

…so whats null?

Thanks for the quick response.



Sorry about that, the line that throws the NPE is line 5 in the update loop.



SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]

java.lang.NullPointerException

at mygame.StartScreen.update(StartScreen.java:161)

at com.jme3.app.state.AppStateManager.update(AppStateManager.java:255)

at com.jme3.app.SimpleApplication.update(SimpleApplication.java:241)

at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:149)

at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:182)

at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:223)

at java.lang.Thread.run(Thread.java:722)





In my update loop screen is null, and if I try and use nifty it also throws an NPE.

You will have to post the code of your StartScreen class or else we don’t know what is on line 161.

If your screen is null, then set your screen, and your nifty variables (if you have them referenced locally) in the bind() method.



[java]public void bind(Nifty nifty, Screen screen) {

this.nifty = nifty;

this.screen = screen;[/java]

Here is my whole StartScreen Class



[java]

/*

  • To change this template, choose Tools | Templates
  • and open the template in the editor.

    */

    package mygame;



    /**

    *
  • @author Jordon

    /



    import com.jme3.app.Application;

    import com.jme3.app.state.AbstractAppState;

    import com.jme3.app.state.AppStateManager;

    import de.lessvoid.nifty.Nifty;

    import de.lessvoid.nifty.screen.Screen;

    import de.lessvoid.nifty.screen.ScreenController;

    import de.lessvoid.nifty.elements.Element;

    import de.lessvoid.nifty.elements.render.ImageRenderer;

    import de.lessvoid.nifty.render.NiftyImage;





    public class StartScreen extends AbstractAppState implements ScreenController {





    public Nifty nifty;



    public Screen screen;

    private Application app;



    boolean weapon1Clicked = false;

    boolean weapon2Clicked = false;

    boolean weapon3Clicked = false;



    String currentScreen;

    int healthPercentage;

    public Element healthBar;

    /
    * custom methods /



    public StartScreen()

    {

    /
    * Your custom constructor, can accept arguments /



    }



    /
    * Nifty GUI ScreenControl methods /







    public void onStartScreen() { }



    public void onEndScreen() { }



    /
    * jME3 AppState methods /

    public void goToScreen(String nextScreen)

    {

    nifty.gotoScreen(nextScreen); // switch to another screen

    // start the game and do some more stuff…



    }

    @Override

    public void bind(Nifty nifty, Screen screen) {

    this.nifty = nifty;

    this.screen = screen;



    //healthBar = nifty.getScreen("hud").findElementByName("playerHealth");

    }

    public void decreaseHealth()

    {







    }

    public void weapon1Clicked()

    {

    weapon1Clicked = true;

    System.out.print(weapon1Clicked + " Inventory clicked n");

    }

    public void weapon2Clicked()

    {

    weapon2Clicked = true;

    System.out.print(weapon2Clicked + " Inventory clicked n");

    }

    public void weapon3Clicked()

    {

    weapon3Clicked = true;

    System.out.print(weapon3Clicked +" Inventory clicked n");

    }

    public void DoNothing()

    {

    System.out.print(weapon1Clicked + "Do Nothing clicked n");

    }



    public void startGame()

    {



    }

    public void quitGame()

    {

    System.exit(0);

    nifty.exit();



    }





    @Override

    public void initialize(AppStateManager stateManager, Application app) {

    super.initialize(stateManager, app);

    this.app=app;





    }



    @Override

    public void update(float tpf) {

    /
    * jME update loop! */



    if (screen.getScreenId().equals("hud") && weapon1Clicked == true)

    {

    // load or create new image

    NiftyImage img = nifty.getRenderEngine().createImage("Interface/Pistol.png", false);

    // find old image

    Element niftyElement = nifty.getCurrentScreen().findElementByName("CurrentWeapon");

    // swap old with new image

    niftyElement.getRenderer(ImageRenderer.class).setImage(img);

    weapon1Clicked = false;

    }













    }



    }



    [/java]



    I cleaned up my code a little bit so the NPE is thrown on line 118 now.



    I have done that in the bind method, and it works for using the nifty variable to switch screen but it throws and NPE when I try and use it in my update loop.

You should be responding to the actions of the buttons immediately in your weapon#Clicked() methods, not in your update loop. Set the element image in the button response methods instead.

Also for each Screen you should have a different ScreenController so you don’t have to do is “screenId().equals(“hud”)” bit.



But as for your error, you screen is just not set yet: update is getting called before bind(). That or the screen has no ID.

1 Like

@Sploreg

Thanks for the tip. I will do that this was just my initial test to try and update my HUD.



How would I make bind get called before update?



Also, I have tried to give my screen id’s but it won’t let me use the id() method.



Here is how I set up my screens in java excluding all of the layers etc.



[java]

nifty.addScreen(“hud”, new ScreenBuilder(“hud”) {{

controller(new mygame.StartScreen());





}}.build(nifty));



[/java]



I excluded all of the layers and panels so as not to spam the thread with all of my layers and panels.

I guess because the update loop runs before nifty has bound the screen controller.



Edit: That’s what I get for not refreshing the page, beaten to it by sploreg :slight_smile:

You don’t make bind get called before update, just check if the screen != null. Better yet, don’t do any of that in update(). That is the wrong spot for it.



Use the Nifty event bus to fire and receive button events.

1 Like

@Sploreg



Alright, Thanks for your help. I will look into using the event bus.