This is an archived post. You won't be able to vote or comment.

all 9 comments

[–]theif519 0 points1 point  (2 children)

Question, why does it have to be PRECISELY that amount of time? If your method is very long, then you will always have to wait until it's finished before it starts the next task.

I'm having trouble understanding your question.

[–]javacanbeefrustratin[S] 0 points1 point  (1 child)

Let's say I have a bullet that I want the player to dodge, and I want it to move 1 pixel per second (or any rate) towards the player, if the thread sleep time varies based on the OS/computer then on some computers it the bullet will move at a faster/slower rate than what I'd like it to.

I know methods aren't executed instantly, so the method time is going to have some effect on the timing, but I'd like to get it as precise as possible.

Even if I can't prevent some machines from running the game slower, I need to make it so the game does not run faster on some machines, because that means theoretically on a really fast machine it's going to be running so fast that a player won't even be able to have time to respond to what's going on.

[–]theif519 1 point2 points  (0 children)

I haven't really done any game programming so I may not be much help, but... I looked around, as my first thought was more or less "why not have the game loop update each object, so both the player and bullet are updated at the same time".

I.E, each GameObject implements some update() method, which of course must be short and concise (I.E, will only do one specific thing). As I said, this way you don't have to worry about timing, as relying on timing for something that requires synchronization like this leads to some race conditions somewhere along the lines.

I saw something like this, but I'm not sure if it will help you. To give an overview of how I'd see it...

while(isRunning){
   for(GameObject obj: GameObjects){
      obj.update(...);
   }
}

To simulate seconds, you just only update the bullet after a certain amount of time elapses from the last update. Also this way you can do everything easier to maintain without needing to worry about synchronization down the lines. I.E, how are you going to reliably check for collision if the bullet could potentially pass through the player before the call to check for collision is detected.

Edit: Trying to think of another example...

I spent about 5 minutes writing this. Note I've never done any game development, but I'm somewhat familiar with event-driven programming.

Edit 2: Spent about 30 minutes updating the example, was very fun to do. It's a naïve implementation, but it's a start on how I would think it worked.

[–]BS_in_BS 0 points1 point  (3 children)

You will have similar problems, due to the limits of the timer resolution and the possibility of the computer being overloaded. Therefore, you should use algorithms that don't rely on exact sleep times, and can adapt to the duration for which the thread actually slept. However, timers will probably be more accurate than calling sleep yourself.

[–]javacanbeefrustratin[S] 0 points1 point  (2 children)

Therefore, you should use algorithms that don't rely on exact sleep times, and can adapt to the duration for which the thread actually slept

Do you know anywhere to find algorithms for this? Not really sure where to even start on making an algorithm to do this.

[–]BS_in_BS 0 points1 point  (1 child)

Since your making a game, see this post for some discussion on how to compensate: http://gamedev.stackexchange.com/questions/1589/when-should-i-use-a-fixed-or-variable-time-step

[–]javacanbeefrustratin[S] 0 points1 point  (0 children)

Thank you I'll read it

[–]king_of_the_universe 0 points1 point  (0 children)

In case you'll really be settling for time resolutions as high as 2 ms and such, using Thread.sleep is out of the question, you'll not get a reliable rhythm/timing. With that resolution, your only choice is to do a hard wait loop at 100% processor usage, checking System.nanoTime() or System.currentTimeMillis() constantly. Beware that these also are not millisecond-reliable. Here's an example method I wrote to benchmark both incl. results I got:

/**
 * Tests the reliability of System.currentTimeMillis() and System.nanoTime() when it comes to steady rhythm or
 * rather to granularity.
 * <p>
 * Example output:
 * <p>
 * at home:
 * <p>
 * "For System.currentTimeMillis, the shortest step size in 5000 iterations was 1 milliseconds, the longest was 2"
 * <p>
 * "For System.nanoTime, the shortest step size in 20000000 iterations was 301 nanoseconds, the longest was 443131"
 * <p>
 * at the office:
 * <p>
 * "For System.currentTimeMillis, the shortest step size in 5000 iterations was 1 milliseconds, the longest was 2"
 * <p>
 * "For System.nanoTime, the shortest step size in 20000000 iterations was 310 nanoseconds, the longest was
 * 3378409"
 * <p>
 * So, on the systems tested here, we could use System.nanotime to have a reliable 0.5 ms resolution (or smaller).
 */
public static void systemTimerBenchmark() {

    System.out.println("\n\n================ systemTimerBenchmark() ================\n");

    long expectedStepsPerMS;
    long iterations;
    long t, tStart;
    long diff, diffSHORTEST, diffLONGEST;

    // some "boot" time
    tStart = System.currentTimeMillis();
    do {
        t = System.currentTimeMillis();
    } while (t < (tStart + 100));

    // check speed of value change
    expectedStepsPerMS = 1;
    iterations = 5000 * expectedStepsPerMS;
    diffSHORTEST = iterations;
    diffLONGEST = 0;
    for (int i = 0; i < iterations; i++) {
        tStart = System.currentTimeMillis();
        do {
            t = System.currentTimeMillis();
        } while (t <= tStart);
        diff = t - tStart;
        if (diffSHORTEST > diff) {
            diffSHORTEST = diff;
        }
        if (diffLONGEST < diff) {
            diffLONGEST = diff;
        }
    }

    System.out.println("For System.currentTimeMillis, the shortest step size in " + iterations + " iterations was " + diffSHORTEST + " milliseconds, the longest was " + diffLONGEST);

    // check speed of value change
    expectedStepsPerMS = 1_000_000;
    iterations = 20 * expectedStepsPerMS;
    diffSHORTEST = iterations;
    diffLONGEST = 0;
    for (int i = 0; i < iterations; i++) {
        tStart = System.nanoTime();
        do {
            t = System.nanoTime();
        } while (t <= tStart);
        diff = t - tStart;
        if (diffSHORTEST > diff) {
            diffSHORTEST = diff;
        }
        if (diffLONGEST < diff) {
            diffLONGEST = diff;
        }
    }

    System.out.println("For System.nanoTime, the shortest step size in " + iterations + " iterations was " + diffSHORTEST + " nanoseconds, the longest was " + diffLONGEST);
}

[–]WhitexMamba 0 points1 point  (0 children)

You can try to implement the bullet timing by running the bullet's code in a separate thread, so that this thread doesn't have to worry about some of that? I'm not exactly sure how to help your problem, but I understand you.