Synchronzing my bars to cross the screen in 1 second

Dear All,



Please help me with this, I am going to loose my mind.



This application is about displaying white bars on  black background moving from left to right,



my aim is to let these bars cross the screen in a time margin at speeds of 5 seconds and 1 Second, keeping the distances equal between each bar and the other.



here is my final code



package swings;

import java.util.ArrayList;
import com.jme.app.SimpleGame;
import com.jme.renderer.Renderer;
import com.jme.scene.Spatial.CullHint;
import com.jme.scene.shape.Quad;
import com.jme.util.Timer;
import com.jmex.scene.TimedLifeController;

public class TestSlidingBars2DModified
    extends SimpleGame {
  // width in pixels
  private int barWidth = 20;
  // speed in pixel per second
  private float barSpeed = 700;
  // Array of Bars to move
  private ArrayList<Quad> bars = new ArrayList<Quad> ();
 // TimedLifeController TLC =  new TimedLifeController(1);
  private float tpf = 0;
  private int Speed = 4;
  @Override
  protected void simpleInitGame() {
    lightState.detachAll();
    rootNode.setRenderQueueMode(Renderer.QUEUE_ORTHO);
    com.jme.system.DisplaySystem.getDisplaySystem().getRenderer().clearBuffers();
    com.jme.system.DisplaySystem.getDisplaySystem().getRenderer().draw(rootNode);
    com.jme.system.DisplaySystem.getDisplaySystem().getRenderer().displayBackBuffer();

    // create a few bars and attach it to the scene

    for (int i = 1, xLoc = 0; xLoc < display.getWidth(); i++) {
      xLoc = barWidth * 2 * i;
      System.out.println(xLoc);
      Quad bar = new Quad("q" + i, barWidth, display.getHeight());
      // move the bar to the far left of the screen
      bar.setLocalTranslation(barWidth / 2 + xLoc, display.getHeight() / 2, 0);
      bar.setCullHint(CullHint.Never);
      // add the bar to the array of bars, to move them later
      bars.add(bar);
      // attach the bar to the screen
      rootNode.attachChild(bar);
    }
  }

  /**
   * Move the Bars to the right.
   */
  @Override
  protected void simpleUpdate() {
    tpf = Timer.getTimer().getTimePerFrame();
    //  System.out.println("Timer per frame is " + tpf);
   //  if (tpf > 0.01f) {
     // tpf = 0.01f;
   //  }
    // move all bars
    for (Quad bar : bars) {
      System.out.println("it is now safely at " + bar.getLocalTranslation().x);

      //  if (bar.getLocalTranslation().x - barWidth >= display.getWidth() ) {

      if (bar.getLocalTranslation().x >= display.getWidth())

     {
        // move the bar back to the left side of the screen
         bar.getLocalTranslation().x = -barWidth/2;
      //  bar.getLocalTranslation().x = barWidth;
      }
      // move the bar to the right, independent of the current framerate
      //  bar.getLocalTranslation().x += barSpeed*tpf;
      bar.getLocalTranslation().x += (display.getWidth() / Speed) * tpf;
    }
  }

  public static void main(String[] args) {
    TestSlidingBars2DModified game = new TestSlidingBars2DModified();
    game.setConfigShowMode(ConfigShowMode.AlwaysShow);
    com.jme.system.DisplaySystem.getDisplaySystem().setVSyncEnabled(true);
    game.getNewSettings().setVerticalSync(true);
    game.start();
  }
}


Looks pretty close. What is the specific thing that's bothering you?



I could see two potential issues with the synchronizing -



The main one is just the way you are setting up the initial positions. xLoc limits the loop but is not the actual position the bar is placed at (that is barWidth / 2 + xLoc). Result is the last bar created is already off the screen, pops back up on the left and messes up spacing. Just fixing that loop up should correct the most obvious problem.



A more subtle problem is that by updating every bar's position independantly based on tpf, floating point errors will creep in to the positions. Eventually things will get out of synch. In this scenario it would make much more sense just to have one moving position and everything else offset from that by a static amount. If that's too inflexible then perhaps maintain a loop timer and have a simple function to calculate a given bar's position from  that time.



Lastly you do have some unnecessary code in there. For example, you don't need to calculate tpf in a SimpleGame and you don't need the backbuffer stuff.



EDIT: Just noticed there's another thread on the subject, and it looks like some of that stuff might have been done for good reason. In which case feel free to ignore the last bit!

thanks for the 2 notes,



I fixed the loop with this piece and it worked



barsCount = (int) Math.ceil((display.getWidth() + 2 * barWidth -1) / (2 * barWidth)) ;



and in simpleUpdate, I did 2 things


protected void simpleUpdate() {
   // System.out.println(System.currentTimeMillis());
    if( updated == false)
      {
        tpf = Timer.getTimer().getTimePerFrame();
        updated = true ;
      }
    //  System.out.println("Timer per frame is " + tpf);
  //   if (tpf > 0.01f) {
   //   tpf = 0.01f;
    // }
    // move all bars
    for (Quad bar : bars) {
     // System.out.println("it is now safely at " + bar.getLocalTranslation().x);

      //  if (bar.getLocalTranslation().x - barWidth >= display.getWidth() ) {

      if (bar.getLocalTranslation().x >= display.getWidth())

     {
        // move the bar back to the left side of the screen
         bar.getLocalTranslation().x -= barsCount*2*barWidth;
      //  bar.getLocalTranslation().x = barWidth;
      }
      // move the bar to the right, independent of the current framerate
      //  bar.getLocalTranslation().x += barSpeed*tpf;
      bar.getLocalTranslation().x += (display.getWidth() / Speed) * tpf;
    }
  }



I used a fixed tpf, the one read on the first time the simpleUpdate is called,

the second thing is to use the barsCount for estimating the exact positioning.


my now issue :

I checked how many times the simpleUpdate is called and it seems it is called many times in the one millisecond,

this many times is different from one case to the other.

is it possible to control the number of times simpleUpdate is called to have it once per frame ??

It shouldn't be getting called many times per frame - you're probably seeing timer update inaccuracy. Make sure you are averaging over a large number of updates.

I added this print statement to the simpleUpdate



System.out.println(System.currentTimeMillis());



and what i Saw was a print of the same millisecond 2, 3 or 4 times, very few times, the millisecond was printed only once.

A good idea is to draw the bars to an image only once and put a view port over this image ,

in this case, all i need is to just move one object, the view port in my case.



any guides to do this idea ???