As a quick and dirty hack I use this to print my animation timer on the screen:
[java]
cinematic.addCinematicEvent(0, new AbstractCinematicEvent() {
@Override
public void onPlay() {
}
@Override
public void onUpdate(float tpf) {
counter += tpf;
//System.out.println("Simulation Timer: "+counter); // used for debugging
txt.setText("Simulation Timer: "+ Double.valueOf(String.format(Locale.US, “%1$.5f”, counter)));
}
@Override
public void onStop() {
}
@Override
public void onPause() {
}
});
[/java]
however this stops for some reason at time 10.003 seconds. the way my code is setup is initiate the code above at the beginning and then read from a trace file the other cinematic events.
The question is how can I update the simulation timer text all the time and not let it stop. And I’m curious to know why it’s stopping at time 10 specifically.
Can anyone help me with this?
How are you creating the BitmapText? If you leave the System.out.println() in does it continue to print out even after the bitmap text stops updating?
You may be being hit with a bug in BitmapText. (at least I think it’s still there.)
no I don’t get anything after 10 secs with System.out.println(); I create the BitmapText using the following code:
[java]// print the simulation timer on the animation screen
BitmapFont fnt = assetManager.loadFont(“Interface/Fonts/Default.fnt”);
final BitmapText txt = new BitmapText(fnt, false);
txt.setSize(fnt.getPreferredSize() * 2f);
txt.setLocalTranslation(0, settings.getHeight(), 0); // position of the printed timer
guiNode.attachChild(txt);[/java]
Ok, if you stop getting output even from the system out println then it’s not bitmap text’s fault. I have no idea.
10 seconds seems suspicious… like something is set to do something after 10 seconds but I don’t know anything about cinematics.
AbstractCinematicEvent’s initialDuration is 10 seconds
Exactly, the event last 10 secs, so its update method is not called anymore after 10 sec.
Ok now I know why i’m getting 10 secs however the question remains: Is there a way to setup a simulation timer?
I’m not certain what end result you want with the timer. Is it to show how far along each AbstractCinematicEvent is? Or globally knowing how long the cinematics have been running?
Globally… I want a timer for the animation as a whole
Just do a counter+=tpf in the main application class or a special appstate?
As i’m using cinematics I don’t have a main update(tpf). How can I do so with a special appstate?
[java]
public class MyAppState extends AbstractAppState {
float totalTime = 0;
public void update( float tpf ) {
totalTime += tpf;
}
}
[/java]
Then somewhere:
getStateManager().attach( new MyAppState() );
So in my main I added:
[java]// Timer
getStateManager().attach( new MyAppState() );[/java]
and created the class MyAppState adding
[java]@Override
public void update( float tpf ) {
totalTime += tpf;
System.out.println("Sim time: "+totalTime);
}[/java]
however that update() function doesn’t get called
I have to check this because sooooo many people do it wrong:
Is your application extending SimpleApplication like it’s supposed to?
Does your MyAppState do anything different than the one I posted other than its update() method?
Yes you were right!
Does your MyAppState do anything different than the one I posted other than its update() method?
I created a MyAppState that implements from appState and I guess the other methods were the problem. Now it works.
Sorry if this may sound too easy but does calling the main function from the update() of MyAppState to pass the new time (see below) a bad and design or will result in poor performance over the long term?
[java]@Override
public void update( float tpf )
{
totalTime += tpf;
//System.out.println("Sim time: "+totalTime);
// send it to Jme3Cinematics - Call updateTimer function to animate the timer
myApp.updateTimer(totalTime);
}[/java]
Yes that would be bad design: heading back to the main app constantly. It would mean you still have your timer code in the main app.
Try to encapsulate all of your timer stuff in your appState. In the initialize method you can grab the rootNode (or create your own node and attach it to the root node) from the main app and add your timer display directly to that, without having to go back to your main app constantly. Then make sure to remove the timer stuff from the node when the appState is detached.
@Sploreg, not sure I understood you very well. I do have the BitmapText created in the main and gets updated from a function also available in the main but gets called from MyAppState.
To do you what you are recommending, I didn’t quite get these 2 parts:
(1)
In the initialize method you can grab the rootNode (or create your own node and attach it to the root node) from the main app and add your timer display directly to that
how can I add a node or modify the rootNode from MyAppState?
and (2)
Then make sure to remove the timer stuff from the node when the appState is detached.
can u explain them please in code or pseudo code?
App states let you put a lot of the main app code that uses the update loop, outside of the main class. This way you can easily remove or disable an app state and not harm your main app.
When your AppState is created, its initialize() method is called. That is where you want to create your bitmap text. Then in the appState’s update, update that bitmap text directly without heading to your main app.
Basically copy all the bitmap text stuff you did to your appState.
https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:advanced:application_states has some good examples.
Hmmmm actually that made it worse, I guess i’m doing something wrong (look below at my MyAppState class):
[java]public class MyAppState extends AbstractAppState {
float totalTime = 0;
BitmapText txt;
// 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) {
// 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 )
{
totalTime += tpf;
System.out.println("Sim time: "+totalTime);
// send it to Jme3Cinematics - Call updateTimer function to animate the timer
//myApp.updateTimer(totalTime);
txt.setText("Simulation Timer: "+ Double.valueOf(String.format(Locale.US, “%1$.5f”, totalTime)));
}
// function that gets the rootNode from the main (Jme3Cinematics)
public Node getRootNode(){
return rootNode;
}
}
[/java]
the issue is now the timer is running in the back ground even if I didn’t initiate the app yet.