Delay Line of Code for X Amount of Seconds

Hi, all! This is my first post on this forum.

I’m working on my first game, and the basic objective is to collect as much trash as you can, but I’m having a little problem. To spawn the objects, I’m checking the level to see if it’s 1, 2, 3, etc. then spawn x amount of objects for that level. But, I don’t want them all to spawn at once, I want to delay part of the code for a certain time so the player can have a chance to catch them all.

Here is the code I’m talking about. http://pastebin.java-gaming.org/0660d2d05521e

Inside of the if statement, are 2 separate sections of code, that spawn the objects, how can I delay the second part by a few seconds. I’ve googled it, but all I can find are people saying to put the thread to sleep, but I don’t want to stop the game completely, just delay a section of code.

Any help is appreciated!

You can add a countdown timer. Here’s some psudo code:

init:


boolean spawn = true;
long startTime, endTime;

update:


public void update() {
    endTime = System.currentTimeMillis();

    if(first object has spawned && spawn = true) {
        // start timer
       startTime = System.currentTimeMillis();
       spawn = false;
    }

    if(endTime - startTime >= 2000) // so if countdown timer is greater than 2 seconds
        spawn object 2 here;
}

Hi there,

I tried implementing this into my code, but it doesn’t seem to be working. Here is the entire class where spawning is handled if you’d like to take a look. http://pastebin.java-gaming.org/660dd35025e12

Thanks for the reply!

Put some print statements inside of those conditionals to see that it gets to line 49. Also try printing the output of, endTime - startTime. Everything looks fine from the limited code we’re seeing.

One thing to bear in mind is that since you’re using System.currentTimeMillis(), this will still keep running even if your game is paused. It’s better to pass a delta in the update() function, and subtract this from the time remaining.

The points at which you check system time are only nanoseconds apart.

To avoid the time-sensitive issues with pauses, and other time related oddities Cas (of puppygames’ fame) introduced me into the wonderful world of counters. Just get your game to run at 60fps, always. (this may be a barrier, but it’s one of the best investments for your game). Then, when you need to schedule an action, you’d just do:


public static final int HZ = 60;

private int countdown = 0;
private int state = 0;

public void update() {
   if(countdown == 0) {
      if(state == 0) {
         doThingX();
         countdown = 3 * HZ; // reach state=1 in 3sec
      }
      else if(state == 1) {
         doThingY();
         countdown = 30 * HZ; // reach state=2 in 30sec
      }
      else if(state == 2) {
         doThingZ();
         countdown = 10 * HZ; // reach state=3 in 10sec
      }
      state++;
   }
   countdown--;

   // do your typical update-stuff
}

Make it as complicated as your heart desires. You can have multiple counters, states that freeze counters until a certain condition is met, etc etc. You end up with a (fully deterministic) state-machine.

This is a reply to SteveSmith. I’m putting that because I don’t know if it will look as a reply.

The update method in this class isn’t being called in the main class update method unless the game isn’t paused. I made sure to add that feature in.

Maybe try it without the scoreKeep check, and see what happens. So just take out the if(scoreKeep >= 1000) and see if it works. I feel like that’s what might be messing up the timer, but I could be completely wrong. Just gotta try stuff out, and trace your code to see where the problem is. Do what @VoidBuffer said to do as well. That way you can see exactly where the code is getting to.

Yep. I moved the code out from the scoreKeep if statement and the timer works. But the problem is with doing that, is now there are hundreds of objects spawning, but the timer does work now. The if statement is to make sure that the code only executes once.

Maybe try to use a boolean value for that check instead of scoreKeep int. Something like:


boolean firstSpawn = true;
if(first objects have not been spawned yet && firstSpawn == true) {
    spawnFirstObjects();
    firstSpawn = false;
}

doSecondSpawnCheck();

doTimer();


You will have to mess around with that though.

This works brilliantly! One problem though, I can’t seem to find a way to reset the two integers for the next level. I tried setting them back to 0 after the if statement that checks the level, but it just keeps looping again.

You can make your state-machine as advanced as you want. You can even introduce an integer for ‘level’, but it might be better to create a new Level class with it’s own update-logic with a unique state-machine. I’m not sure what the problem is that you describe, what is wrong with looping? Once the two integers are reset to zero, it will restart all logic. Is this not desired?

I guess that you didn’t completely understand what Riven said, you seem to not understand the logic. He just gave you the core logic. While it works in the raw form, you can make your life easier by introducing a [icode]GameTimer[/icode] class.


public GameTimer(long millis, boolean loop, Runnable action)
{
    this.millis = millis;
    this.loop = loop;
    this.action = action;
}

We take the number of milliseconds to wait, whether to keep running or stop after the first run, and an action, which is a Runnable which can be invoked later when the time expires. Now, we just need start and stop methods so we can control the timer whenever we want.


public void start()
{
    this.elapsed = 0;
    this.active = true;
}

public void stop()
{
    this.active = false;
}

This is simple enough, we have the basic encapsulation of the timer. All we need now is the core logic of the timer. We’ll do it in the update method of the timer.


public void update(long elapsedMillis)
{
    if (!active) return;

    elapsed += elapsedMillis;

    if (elapsed >= millis)
    {
        action.run(); // Run the action
        stop();

        // If in loop, start the timer again
        if (loop)
            start();
    }
}

That is all there is to it. Just update the timer object every time you update the game along with your objects and you are done.

If you don’t care about a real-time accurate delay and instead just want a general delay, it might just be easier to create an integer called ticks. On every level, it begins at 0 and increments every level update. You can then say something like this in your update:

if(ticks == 2 * 60) { // Theoretical 2 seconds in game time @60Hz
    spawnGarbage();
}
etc...

This would be simpler than trying to get unnecessary accuracy if you don’t need it.

What I meant when I said looping was, it doesn’t stop, the integers are being reset so the if statement keeps running, spawning hundreds of objects.

Alright, I see what you’re saying now. Thank you!

I’d actually be (mildly) against this abstraction layer. The more complex your game gets, the more trickery is involved adjusting the internal state of the timers. In the end you are going to expose all fields with getters and setters and your abstraction layer is getting in the way.

Can you please explain more? I think I already expose everything except the elapsed and the active flag. What is the trickery involved in it?

I don’t think that will make a difference. If the game is paused (or you might be saving state?) immediately after the code is run once, and then unpaused a few minutes later, System.currentTimeMillis() will have moved on and stuff will be spawned immediately.