Learner having trouble with Nifty

Hello there,

I’m trying to interface my operational car racing game with Nifty.

I want a Start Screen with a button on it saying “Start” (original) which when clicked will start the main screen and gameplay.

I’ve gone through the Nifty tutorials, have created an xml file for the screens thus

<?xml version="1.0" encoding="UTF-8"?>
<!--
To change this template, choose Tools | Templates
and open the template in the editor.
-->


<nifty xmlns="http://nifty-gui.sourceforge.net/nifty-1.3.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://nifty-gui.sourceforge.net/nifty-1.3.xsd http://nifty-gui.sourceforge.net/nifty-1.3.xsd">
    <useStyles filename="nifty-default-styles.xml" />
    <useControls filename="nifty-default-controls.xml" />
    <screen id="start" controller="Reved.MyStartScreen">
        <layer id="background" childLayout="center">
            <image filename="Interface/start-background.png"></image>
        </layer>
        <layer id="foreground" childLayout="vertical">
            <panel id="panel_top" height="25%" width="75%" align="center" childLayout="center">
                <text text="REVED - An Exciting Motor Racing Game" font="Interface/Fonts/Default.fnt" width="100%" height="100%" />
            </panel>
            <panel id="panel_mid" height="50%" width="75%" align="center" childLayout="center">
                <text text="" font="Interface/Fonts/Default.fnt" width="100%" height="100%" wrap="true" />
            </panel>
            <panel id="panel_bottom" height="25%" width="75%" align="center" childLayout="horizontal" >
                <panel id="panel_bottom_left" height="50%" width="50%" valign="center" childLayout="center">
                    <control name="button" label="Start" id="StartButton" align="center" valign="center" visibleToMouse="true" >
                        <interact onClick="StartGame()" />
                    </control>
                </panel>
                <panel id="panel_bottom_right" height="50%" width="50%" valign="center" childLayout="center">
                    <control name="button" label="Quit" id="QuitButton" align="center" valign="center" visibleToMouse="true" >
                       <interact onClick="QuitGame()" />  
                    </control>
                </panel>
            </panel>
        </layer>
    </screen>
    <screen id="hud">
        <layer id="background" childLayout="center">
            <image filename="Interface/hud-frame.png"></image>
        </layer>
        <layer id="foreground" childLayout="horizontal">
            <panel id="panel_left" width="80%" height="100%" childLayout="vertical" ></panel>
            <panel id="panel_right" width="20%" height="100%" childLayout="vertical">
                <panel id="panel_top_right1" width="100%" height="15%" childLayout="center">
                    <control name="label" color="#000" text="123" width="100%" height="100%" />
                </panel>
                <panel id="panel_top_right2" width="100%" height="15%" childLayout="center">
                    <image filename="Interface/face1.png" valign="center" align="center" height="50%" width="30%" ></image>
                </panel>
                <panel id="panel_bot_right" width="100%" height="70%" valign="center" ></panel>
            </panel>
        </layer>
    </screen>
</nifty>

The Screen Controller is called MyStartScreen.java

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Reved;

import com.jme3.app.Application;
import com.jme3.app.SimpleApplication;
import com.jme3.app.state.AbstractAppState;
import com.jme3.app.state.AppStateManager;
import com.jme3.asset.AssetManager;
import com.jme3.math.ColorRGBA;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.Node;
import de.lessvoid.nifty.Nifty;
import de.lessvoid.nifty.screen.Screen;
import de.lessvoid.nifty.screen.ScreenController;

/**
 *
 * @author steve
 */
public class MyStartScreen extends AbstractAppState
                           implements ScreenController {
  private ViewPort viewPort;
  private Node rootNode;
  private Node guiNode;
  private AssetManager assetManager;
  private Node localRootNode = new Node("Start Screen RootNode");
  private Node localGuiNode = new Node("Start Screen GuiNode");
  private final ColorRGBA backgroundColor = ColorRGBA.Gray;  
  
    public MyStartScreen(SimpleApplication app)
    {
      this.rootNode     = app.getRootNode();
      this.viewPort     = app.getViewPort();
      this.guiNode      = app.getGuiNode();
      this.assetManager = app.getAssetManager();  
    }
    
    @Override
    public void initialize(AppStateManager stateManager, Application app) {
        super.initialize(stateManager, app);
        //TODO: initialize your AppState, e.g. attach spatials to rootNode
        //this is called on the OpenGL thread after the AppState has been attached
    }

    @Override
    public void update(float tpf) {
        //TODO: implement behavior during runtime
    }

    @Override
    public void cleanup() {
        super.cleanup();
        //TODO: clean up what you initialized in the initialize method,
        //e.g. remove all spatials from rootNode
        //this is called on the OpenGL thread after the AppState has been detached
    }

    @Override
    public void bind(Nifty nifty, Screen screen) {
       // throw new UnsupportedOperationException("Not supported yet.");
    }

    public void onStartScreen() {
       // throw new UnsupportedOperationException("Not supported yet.");
    }

    public void onEndScreen() {
       // throw new UnsupportedOperationException("Not supported yet.");
       // app.stop();
    }
    
      //.............................................
    //..Start the Game
    //.............................................
    
    public void StartGame()
    {
        System.out.println("In Start Game") ;
        
        
       //  app.simpleInitApp1() ; // does not recognise app
       // Started = true;
    }
    
    //..............................................
    //.. Quit the Game
    //..............................................
    
    public void QuitGame()
    {
      //  app.stop();
    }
}

The bulk of the code is in the Reved class, the bit that initialises the Nifty interface is called from SimpleInitApp

 public void SetupNifty()
    {
        
        startScreen = new MyStartScreen(this);

        stateManager.attach(startScreen);
        niftyDisplay = new NiftyJmeDisplay(assetManager, inputManager, audioRenderer, guiViewPort);
        nifty = niftyDisplay.getNifty();
        guiViewPort.addProcessor(niftyDisplay);
        nifty.fromXml("Interface/screens.xml", "start", startScreen);
        //nifty.setDebugOptionPanelColors(true); //un-comment this line to use DebugPanelColors and make sure Nifty is running correctly.
        
        flyCam.setDragToRotate(true); //detaches camera from mouse unless you click/drag.
    }
   
    /***************************************************
     * Initialise the App
     ***************************************************/
    
    @Override
    public void simpleInitApp() 
    {
        SetupNifty() ;
        Started = false ;
    }

The main class initialises the Reved Application

  • To change this template, choose Tools | Templates
  • and open the template in the editor.
    */
    package Reved;

import com.jme3.app.SimpleApplication;
import com.jme3.niftygui.NiftyJmeDisplay;
import de.lessvoid.nifty.Nifty;

/**
*

  • @author steve
    */

    public class Main {

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

    }

The Start button is wired to the StartGame() function in MyStartScreen.java, and I want this to call SimpleInitApp1 in the Reved class which sets the game running.

On running , the Start Screen appears, when the Start button is clicked it prints an output to the console, but I cannot access SimpleInitApp1 through the app variable.

What am I missing ?

Your MyStartScreen class has no field called app and one is never set anyway.

I’m a bit confused. Should “simpleInitApp” call the setup of the Nifty Interface ?

I really want to call “simpleInitApp” from the press of a button on the Nifty screen which would then set the main game running.

Is this possible ? Is it best practise ?

simpleInitApp() is called by JME when the app is started.

Anyway, your error is a basic Java beginner error. You have a class named MyStartScreen. You try to access a field called “app” but that field doesn’t exist anywhere in the class because you haven’t declared it or set it.

Presumably you want to have a field called app in that class.

And presumable you want to set it in the MyStartScreen() constructor just like rootNode, viewPort, etc…

Learning Java while learning JME and especially nifty is going to be super difficult.

Well, despite my L Plates I have got it working after a fashion. There is work to do, but thanks for pointing me in the right direction.

:smile:

We all have to start somewhere… nifty just tends to throw a few extra wrenches in the works along the way. Even experienced devs struggle with it sometimes.