Java-Gaming.org Hi !
Featured games (90)
games approved by the League of Dukes
Games in Showcase (711)
Games in Android Showcase (213)
games submitted by our members
Games in WIP (785)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Delay Line of Code for X Amount of Seconds  (Read 1812 times)
0 Members and 1 Guest are viewing this topic.
Offline 0AndrewShepherd0

Junior Newbie


Exp: 1-3 months



« Posted 2016-12-15 21:52:49 »

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!
Offline FabulousFellini
« Reply #1 - Posted 2016-12-15 22:00:47 »

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

init:
1  
2  
boolean spawn = true;
long startTime, endTime;


update:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
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;
}

-FabulousFellini
Offline 0AndrewShepherd0

Junior Newbie


Exp: 1-3 months



« Reply #2 - Posted 2016-12-16 03:59:40 »

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!
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline VoidBuffer

Junior Devvie


Medals: 4
Exp: 2 years



« Reply #3 - Posted 2016-12-16 05:56:04 »

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.
Offline SteveSmith
« Reply #4 - Posted 2016-12-16 13:08:43 »

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.

Offline bitbytebytes

Junior Devvie


Medals: 2



« Reply #5 - Posted 2016-12-16 14:37:47 »

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

« JGO Overlord »


Medals: 1260
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #6 - Posted 2016-12-16 16:13:02 »

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:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
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.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings!
Offline 0AndrewShepherd0

Junior Newbie


Exp: 1-3 months



« Reply #7 - Posted 2016-12-16 16:13:34 »

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.
Offline FabulousFellini
« Reply #8 - Posted 2016-12-16 16:15:19 »

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!

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.

-FabulousFellini
Offline 0AndrewShepherd0

Junior Newbie


Exp: 1-3 months



« Reply #9 - Posted 2016-12-16 16:23:19 »

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!

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.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline FabulousFellini
« Reply #10 - Posted 2016-12-16 16:52:36 »

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!

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:
1  
2  
3  
4  
5  
6  
7  
8  
9  
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.

-FabulousFellini
Offline 0AndrewShepherd0

Junior Newbie


Exp: 1-3 months



« Reply #11 - Posted 2016-12-18 04:01:14 »

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:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
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 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.
Offline Riven
Administrator

« JGO Overlord »


Medals: 1260
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #12 - Posted 2016-12-18 10:34:23 »

1  
2  
3  
4  
5  
6  
7  
8  
public static final int HZ = 60;

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

public void update() {
   ... [snipped]
}

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?

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings!
Offline SHC
« Reply #13 - Posted 2016-12-18 13:55:48 »

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
GameTimer
class.

1  
2  
3  
4  
5  
6  
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.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
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.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
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.

Offline Longarmx
« Reply #14 - Posted 2016-12-18 17:35:07 »

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:
 
1  
2  
3  
4  
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.

Offline 0AndrewShepherd0

Junior Newbie


Exp: 1-3 months



« Reply #15 - Posted 2016-12-18 23:01:22 »

1  
2  
3  
4  
5  
6  
7  
8  
public static final int HZ = 60;

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

public void update() {
   ... [snipped]
}

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?

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.
Offline 0AndrewShepherd0

Junior Newbie


Exp: 1-3 months



« Reply #16 - Posted 2016-12-19 00:33:56 »

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?

Alright, I see what you're saying now. Thank you!
Offline Riven
Administrator

« JGO Overlord »


Medals: 1260
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #17 - Posted 2016-12-19 07:35:28 »

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
GameTimer
class.

1  
2  
3  
4  
5  
6  
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.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
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.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
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.

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.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings!
Offline SHC
« Reply #18 - Posted 2016-12-19 09:12:50 »

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?

Offline SteveSmith
« Reply #19 - Posted 2016-12-22 08:46:00 »

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.

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.

Pages: [1]
  ignore  |  Print  
 
 

 
numerical (180 views)
2017-02-21 07:32:16

numerical (179 views)
2017-02-21 07:31:46

theagentd (287 views)
2017-02-18 13:42:33

theagentd (288 views)
2017-02-18 13:35:16

h.pernpeintner (1455 views)
2017-01-24 22:39:11

h.pernpeintner (1440 views)
2017-01-24 22:38:32

Galdo (2005 views)
2017-01-12 13:44:09

Archive (2050 views)
2017-01-02 05:31:41

0AndrewShepherd0 (2586 views)
2016-12-16 03:58:39

0AndrewShepherd0 (2332 views)
2016-12-15 21:50:57
List of Learning Resources
by elect
2016-09-09 09:47:55

List of Learning Resources
by elect
2016-09-08 09:47:20

List of Learning Resources
by elect
2016-09-08 09:46:51

List of Learning Resources
by elect
2016-09-08 09:46:27

List of Learning Resources
by elect
2016-09-08 09:45:41

List of Learning Resources
by elect
2016-09-08 08:39:20

List of Learning Resources
by elect
2016-09-08 08:38:19

Rendering resources
by Roquen
2016-08-08 05:55:21
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!