[SOLVED] Jme3 Beginner: Putting a Timer text in my animation

Use the isEnabled() and setEnabled part of the AppState interface. In the update loop of your appstate first check if isEnabled(). If not, bail out of the loop without updating the timer.

When your animation starts, call myAppState.setEnabled(true).

When setEnabled() is false… update() won’t be called.

Well fixed that by simply attaching the appstate whenever play is called (animation starts) - see below… However, it’s still slower than before (calling it everytime from main - bad design).

[java]

public void onPlay(CinematicEvent cinematic) {

//chaseCam.setEnabled(true); // chase drive camera (can’t see difference till you have a floor)

System.out.println(“play”);



// Attach an application state that gets the Simulation Timer

getStateManager().attach( new MyAppState() );

}[/java]

Then something else is wrong.



There is physically/practically/absolutely no difference between an app state’s update method and calling a method from simpleUpdate every time. It’s doing exactly the same thing. Unless you are accidentally attaching the app state hundreds of times or something.



And note: you could have gone with the original suggestion of just setEnabled(true) instead of attaching it. At least then if you forget to setEnabled(false) (instead of forgetting to detach it) then you don’t end up with multiple copies hanging around.



Your line above could have been:

getStateManager().getState( MyAppState.class ).setEnabled(true);

There is physically/practically/absolutely no difference between an app state’s update method and calling a method from simpleUpdate every time. It’s doing exactly the same thing.


so are you saying my old bad design will have the same performance?


Also I implemented setEnabled and it's still slower. it loops and prints only when the user initiates the animation however it's slow. I can't figure out why from debugging it as everything looks to be doing what it's supposed to.
[java]@Override
public void update( float tpf )
{
// if animation is off break loop
if (!active) {
return;
}
totalTime += tpf;
System.out.println("Sim time: "+totalTime);
}[/java]

How are you determining that it is slow as compared to the old bad design way?



Old bad design way:

calls a method on update



New app state design way:

calls a method on update, it’s just not done directly by you



So if there is a slow down then it is unrelated to that alone.

How are you determining that it is slow as compared to the old bad design way?


animation is breaking up everytime simulator timer is updated... easily noticed, with the other design it's smooth.

I would like to implement the right design, it's just I can't figure out what am I doing wrong (and I 'm sure its from the MyAppState class). Can you see anything wrong?

[java]
public class TimerAppState extends AbstractAppState {

float totalTime = 0;
BitmapText txt;
protected boolean active = true;

// create an instance of the Simpleapplication inside Jme3Cinematics
private Jme3Cinematics myApp = Jme3Cinematics.getApp();

// reads the asset manager initialized in Jme3Cinematics
private AssetManager assetManager = myApp.getAssetManager();

// Node that will hold the rootNode from Jme3Cinemtics (main)
private Node rootNode = new Node("Root Node");


@Override
public void initialize(AppStateManager stateManager, Application app) {

AppSettings settings = new AppSettings(true);
settings.setResolution(1024, 768);
// print the simulation timer on the animation screen
BitmapFont fnt = assetManager.loadFont("Interface/Fonts/Default.fnt");
txt = new BitmapText(fnt, false);
txt.setSize(fnt.getPreferredSize() * 2f);
txt.setLocalTranslation(0, settings.getHeight(), 0); // position of the printed timer
//txt.setLocalTranslation(0, 0, 0); // position of the printed timer
getRootNode().attachChild(txt);

}


@Override
public void update( float tpf )
{
// if animation is off break loop
if (!active) {
return;
}
totalTime += tpf;
System.out.println("Sim time: "+totalTime);

//txt.setText("Simulation Timer: "+ Double.valueOf(String.format(Locale.US, "%1$.5f", totalTime)));
}



// function that enables the timer animation
public void setEnabled(boolean enabled) {
this.active = enabled;
}

// function that checks if the timer animation is enabled
public boolean isEnabled() {
return active;
}

// function that gets the rootNode from the main (Jme3Cinematics)
public Node getRootNode(){
return rootNode;
}

}
[/java]

form main:

[java]
getStateManager().attach( tp ); // tp is an instance of TimerAppState initialized earlier
tp.setEnabled(true);
[/java]

Yeah, you don’t call super.initialize() in your initialize method… so your initialize method gets call every update pass.

1 Like

Great!!!



Ok just two quick things:



1- you mentioned that I need to do a clean() can you tell me more about that?



2- Why is my BitmapText not being drawn? although I did attach it to the rootNode using getRootNode().attachChild(txt); and the txt gets called but it’s null for some reason.



[java]@Override

public void update( float tpf )

{

// if animation is off break loop

if (!active) {

return;

}

totalTime += tpf;

//System.out.println("Sim time: "+totalTime);



txt.setText("Simulation Timer: "+ Double.valueOf(String.format(Locale.US, “%1$.5f”, totalTime)));

// send it to Jme3Cinematics - Call updateTimer function to animate the timer

//myApp.updateTimer(totalTime);

}[/java]

re: clean, I just mean that if you want your app state to be detachable or pay attention to being disabled then you should detach your stuff… but I wouldn’t worry about that right now.



re: text, you set your bitmap text to be 768 meters into the sky over the world origin. I suspect it’s there floating high above you too tiny to see. Maybe you really meant to add it to the guiNode? If so, you probably also want to move it down because I think it will be drawn off the top of the screen. The position sets where the text baseline is.

pspeed can you please tell me how can I import the guiNode into the MyAppState? you are right, I meant to use guiNode and not rootNode.



I do want to print on the left upper corner of the screen.

If you are using SimpleApplication it is in there. Grab it when your AppState initializes.

cuz I use txt.setLocalTranslation(0, 0, 0); to see right in the middle but I don’t. Here’s my code:



[java]// create an instance of the Simpleapplication inside Jme3Cinematics

private Jme3Cinematics myApp = Jme3Cinematics.getApp();



// reads the asset manager initialized in Jme3Cinematics

private AssetManager assetManager = myApp.getAssetManager();



// Node that will hold the rootNode from Jme3Cinemtics (main)

private Node rootNode = new Node(“Root Node”);



// Node that will hold the guiNode from Jme3Cinemtics (main)

private Node guiNode = new Node (“Gui Node”);





@Override

public void initialize(AppStateManager stateManager, Application app) {



super.initialize(stateManager, app);

System.out.println(“Timer AppState Initialized”);



AppSettings settings = new AppSettings(true);

settings.setResolution(1024, 768);

// print the simulation timer on the animation screen

BitmapFont fnt = assetManager.loadFont(“Interface/Fonts/Default.fnt”);

txt = new BitmapText(fnt, false);

txt.setSize(fnt.getPreferredSize() * 2f);

//txt.setLocalTranslation(0, settings.getHeight(), 0); // position of the printed timer

txt.setLocalTranslation(0, 0, 0); // position of the printed timer

txt.setText("Simulation Timer: "+ Double.valueOf(String.format(Locale.US, “%1$.5f”, totalTime)));

getGuiNode().attachChild(txt);



}



// function that gets the rootNode from the main (Jme3Cinematics)

public Node getGuiNode(){

return guiNode;

}

[/java]

what? you are getting more and more confused I think, maybe you should sleep a bit over everything you learned ^^

1 Like

[java]

// Node that will hold the guiNode from Jme3Cinemtics (main)

private Node guiNode = new Node (“Gui Node”);

[/java]



Just because you’ve named that “guiNode” does not make it a gui node. Why not use the perfectly good on already created in SimpleApplication, already setup for you?



((SimpleApplication)app).getGuiNode();

sorry I had in my code myApp.getGuiNode().attachChild(txt); which didn’t work replaced it with urs (although I think they do the same thing) but still it doesn’t draw it.

It should be the same. I didn’t know what type “myApp” was and didn’t bother hunting back through posts to see if it was there… when there was a perfectly good app reference right where you needed it anyway. It just needed to be cast.



Your text should show up. You can try moving it to 100,100,0 or something. Given the window I can see into the current code and speculating on the modifications you’ve made, it should work even at 0,0.

1 Like

They do completely different things. The GuiNode in SimpleApplication has its queueBucket set to “Gui”. Where your gui node is just a regular node.

crush-kill-destroy this line:

[java]// Node that will hold the guiNode from Jme3Cinemtics (main)

private Node guiNode = new Node (“Gui Node”);[/java]

And use what pspeed gave you.

1 Like

That works now!



thanks guys!