Java-Gaming.org Hi !
Featured games (91)
games approved by the League of Dukes
Games in Showcase (804)
Games in Android Showcase (237)
games submitted by our members
Games in WIP (867)
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  
  [solved] Updating & Rendering in a timely fashion  (Read 8318 times)
0 Members and 1 Guest are viewing this topic.
Offline TehJavaDev

JGO Knight


Medals: 17
Projects: 3
Exp: 7-9 months


Java is so dope they wanna >:D


« Posted 2014-08-28 02:12:33 »

Hello JGO members, I wanted to create a basic game and I wanted to accomplish the following:
#1: Update (Every 16ms if possible, 16ms = windows minimum cpu time?)
#2: Render (Every 60ms if possible, 60ms = refresh rate)

I don't know how to go about doing this as the update and render times will vary depending on what is being called in those methods.

If it's possible I would like to do this on 1 thread, if anyone advises against that please tell me why, and how I should go about doing it? ^_^

Thanks JGO, looking forward to any feedback ^__^


Checkout my new easy to use java networking library: GNetLib
Offline BurntPizza

« JGO Bitwise Duke »


Medals: 486
Exp: 7 years



« Reply #1 - Posted 2014-08-28 02:21:56 »

Do you really want to render at 60ms intervals? That's only 16 FPS.

In regards to decoupled game loops on one thread (read: easiest, safest way): http://gafferongames.com/game-physics/fix-your-timestep/
Offline TehJavaDev

JGO Knight


Medals: 17
Projects: 3
Exp: 7-9 months


Java is so dope they wanna >:D


« Reply #2 - Posted 2014-08-28 02:24:12 »

Do you really want to render at 60ms intervals? That's only 16 FPS.

Thank you, I didn't even think about that.
I had just read somewhere to repaint upon the screen being refreshed.
Oops, thank you again Shocked

My game isn't going to have any physics involved so I don't know if I should follow through with a fixed timestep/delta time.

What do you think?
(Garden type of game, growing plants, simple animations if any at all ^__^)

Checkout my new easy to use java networking library: GNetLib
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline BurntPizza

« JGO Bitwise Duke »


Medals: 486
Exp: 7 years



« Reply #3 - Posted 2014-08-28 02:27:40 »

You're confusing refresh rate (frequency) with the time between refreshes. They are the inverse of each other.

60FPS (60 Hz) = 1 / 60 second (1000 / 60 = ~16 milliseconds)
Offline TehJavaDev

JGO Knight


Medals: 17
Projects: 3
Exp: 7-9 months


Java is so dope they wanna >:D


« Reply #4 - Posted 2014-08-28 02:32:17 »

Thank you for that info ^__^ I'll take it into account.

One more question ^_^

I didn't want to jam up my application and overwork it by doing the following like so (pseudo-code):
1  
2  
3  
4  
while (condition) {
    update();
    render();
}


Should I involve a minimum sleep time?
Possibly update/render at a fixed rate?
(Once again, no physics involved Shocked)

I'm just stuck XD
Thanks for any help, overlooking the page you posted now.

Checkout my new easy to use java networking library: GNetLib
Offline BurntPizza

« JGO Bitwise Duke »


Medals: 486
Exp: 7 years



« Reply #5 - Posted 2014-08-28 02:38:19 »

Yes, as it stands that loop runs as fast as it can, which will be different for different things happening in the update and render methods, and even across different computers.

Try this:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
int desiredFPS = 60;

long nanosToSleep = 1000000000L / desiredFPS;

while (condition) {
    long startTime = System.nanoTime();

    update();
    render();

    // wait until it's time to do next frame, making sure it's been nanosToSleep since we started this frame
    while(System.nanoTime() < startTime + nanosToSleep)
        Thread.sleep(1);
}
Offline TehJavaDev

JGO Knight


Medals: 17
Projects: 3
Exp: 7-9 months


Java is so dope they wanna >:D


« Reply #6 - Posted 2014-08-28 02:41:53 »

Where you said:
wait until it's time to do next frame, making sure it's been nanosToSleep since we started this frame

I don't quite understand o:
If you have the time could you explain what's happening?

Is it waiting just to be in sync & call the 'update/render' @ 60 times a second?

>__< Sorry if I'm a newb XD

Checkout my new easy to use java networking library: GNetLib
Offline BurntPizza

« JGO Bitwise Duke »


Medals: 486
Exp: 7 years



« Reply #7 - Posted 2014-08-28 02:47:17 »

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
int desiredFPS = 60;

//  amount of time between frames that corresponds to desiredFPS
long nanosToSleep = 1000000000L / desiredFPS;

while (condition) {
    //  what time is it right now (start of this frame)
    long startTime = System.nanoTime();

    //  do game stuff, this will take an unknown and possible varying amount of time
    update();
    render();

    //  it is now some time after startTime, but, assuming we're not behind schedule
    //  (update and render aren't too slow), we still have time until the next frame
    //  should be started.

    // so we...
    // wait until it's time to do next frame, making sure it's been nanosToSleep since we started this frame
    while(System.nanoTime() < startTime + nanosToSleep)
        Thread.sleep(1);

    //  it has now been nanosToSleep time since we started this frame, loop back and do the next one
}
Offline TehJavaDev

JGO Knight


Medals: 17
Projects: 3
Exp: 7-9 months


Java is so dope they wanna >:D


« Reply #8 - Posted 2014-08-28 03:09:35 »

Thanks alot ^__^

Going to implement a FPSCounter and see how the framerate is.

Checkout my new easy to use java networking library: GNetLib
Offline TehJavaDev

JGO Knight


Medals: 17
Projects: 3
Exp: 7-9 months


Java is so dope they wanna >:D


« Reply #9 - Posted 2014-08-28 03:17:15 »

Thanks for everything BurntPizza, but I seem to only be getting 59 frames per second?
NOTE: The update/render methods are empty at the time being.

Is this normal or did I not program my fps counter correctly?

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  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
   protected static void startGameThread() {
      gameThreadRunning = true;
      gameThread = new Thread() {
         @Override
         public void run() {
            super.run();
            frameStartTime = System.nanoTime();
            while (gameThreadRunning) {
               final long startTime = System.nanoTime();

               if ((System.nanoTime() - frameStartTime) / 1000000 >= 1000) {
                  fps = frames;
                  frames = 0;
                  System.out.println("FPS: " + fps);
                  frameStartTime = System.nanoTime();
               }

               // Update
               update();

               // Render
               render();
               frames++;

               while (System.nanoTime() < startTime + nanosToSleep) {
                  try {
                     Thread.sleep(1);
                  } catch (final InterruptedException e) { }
               }
            }
         }
      };
      gameThread.setName("GameThread01");
      gameThread.start();
   }


Thanks for any feedback ^_^

Checkout my new easy to use java networking library: GNetLib
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline thedanisaur

JGO Knight


Medals: 59



« Reply #10 - Posted 2014-08-28 05:57:34 »

It's probably truncating and you're actually getting 59.999 fps.

Also remove the if frameStartTime==-1 statement. You're causing an unnecessary branch every frame. Just in it frameStartTime to nanotime before you enter the loop.

Every village needs an idiot Cool
Offline TehJavaDev

JGO Knight


Medals: 17
Projects: 3
Exp: 7-9 months


Java is so dope they wanna >:D


« Reply #11 - Posted 2014-08-28 16:05:53 »

Just in it frameStartTime to nanotime before you enter the loop.

Thanks, I'll see if its truncating. ^_^

EDIT: It's not truncating the frames :/
1  
2  
FPS: 50.0
FPS: 59.0

Checkout my new easy to use java networking library: GNetLib
Offline philfrei
« Reply #12 - Posted 2014-08-28 23:04:24 »

In this section:
1  
2  
3  
4  
5  
6  
    while (System.nanoTime() < startTime + nanosToSleep) {
        try {
            Thread.sleep(1);
            } catch (final InterruptedException e) { }
        }
    }

...I'm not sure the Thread.sleep(1) command actually does what one thinks it should consistently on all systems. The sleep command depends on the system clock, which is a different time source than that of System.nanoTime(). (API for nanoTime() and Thread.sleep() elucidates this.) If you are on an old version of Windows, it might actually be sleeping longer than that.

Can also try the following:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
// import java.util.Timer
// assumes also a reference to the "game"

    Timer timer = new Timer();
    TimerTask task = new TimerTask();

    timer.scheduleAtFixedRate(task, 0, 16);  

    class GameLoopTask implements TimerTask
    {
        game.update();
        game.render();
    }
}


It might be interesting to put in a counter to check the actual frame rate and compare.

music and music apps: http://adonax.com
Offline TehJavaDev

JGO Knight


Medals: 17
Projects: 3
Exp: 7-9 months


Java is so dope they wanna >:D


« Reply #13 - Posted 2014-08-29 04:27:11 »

Thanks ^__^

Actually ended up using the TimerTask for the first time to repaint a few panels on my Main Menu in the background.

Checkout my new easy to use java networking library: GNetLib
Offline SHC
« Reply #14 - Posted 2014-08-29 06:52:43 »

Never, Never use Timer and TimerTask for game loops, they are mainly designed with Swing in mind and may not work well for a gameloop. A decent game loop should run as fast as it can, decoupling logic and rendering. (Don't go multithreading yet, that sounds nice in the start, but cause a lot of troubles if written incorrect)

I use a Fixed Timestep GameLoop and I set it up like this.

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  
26  
27  
28  
29  
30  
31  
32  
33  
34  
public void run(int desiredUps, int desiredFps, int frameSkip)
{
    long now = System.nanoTime();
    long logicTime = System.nanoTime();
    long renderTime = System.nanoTime();

    long frameLogicTime = 1000000000 / desiredUps;
    long frameRenderTime = 1000000000 / desiredFps;

    int skippedFrames = 0;

    while (true)
    {
        if (Display.isCloseRequested())
            break;

        now = System.nanoTime();
        skippedFrames = 0;

        while (logicTime + frameLogicTime < now && skippedFrames < frameSkip)
        {
            update();
           
            skippedFrames++;
            logicTime += frameLogicTime;
        }

        while (renderTime + frameRenderTime < now)
        {
            render();
            renderTime += frameRenderTime;
        }
    }
}

If you use this, make sure that frameskip is atleast 1.  I recommend to give a reading to the following articles.


Hope that helps!

Offline philfrei
« Reply #15 - Posted 2014-08-29 07:38:08 »

Quote
Never, Never use Timer and TimerTask for game loops, they are mainly designed with Swing in mind and may not work well for a gameloop.

SHC -- Could you be more specific about your objections to the util.Timer? I've never had a problem with them, and there is nothing that I know about them that is specific to Swing. AFAIK, you can put any commands you want in them. You're not confusing the util.Timer with the Swing Timer, are you? I would agree that the Swing.Timer is not good for game programming due to performance issues arising from the potential EDT bottleneck.

Eventually, one can graduate to an Executor Service with a fixed schedule--that might be slightly preferable. But that would be a lot to learn for a Newbie. Better to get on with entity management, movement physics, collision detection, etc., imho.

music and music apps: http://adonax.com
Offline TehJavaDev

JGO Knight


Medals: 17
Projects: 3
Exp: 7-9 months


Java is so dope they wanna >:D


« Reply #16 - Posted 2014-08-29 07:58:29 »

Never, Never use Timer and TimerTask for game loops

I'm only using a Timer/TimerTask to update 2 panels in my MainMenu, it repaints both of them (panel.repaint()) and updates a Integer that handles my scrolling news bar.

I'm handling my GameLoop on a thread Tongue TimerTask is ran in the background to update versionAndInfoPanel and my HeaderPanel (No logic but newsX--)

Checkout my new easy to use java networking library: GNetLib
Offline basil_

« JGO Bitwise Duke »


Medals: 418
Exp: 13 years



« Reply #17 - Posted 2014-08-29 10:13:55 »

using Swing or other "timers" is fine. all of them use System.sleep(1) anyway.

just coming along with more stuff that you dont need for a game-loop. so it's not "clean" to use them but also totally fine.

on the other hand ... imo they're all wrong. a proper time/clock in java is a pain in the butt. my current approach comes more from measuring and profiling :

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  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
public class clock
{
  private double hz; // desired fps
  private double interval; // nanosec
 
  private double delta; // in millsec  
  private double start;
  private double last;
  public double currentHZ; // current fps

  public clock(float desiredHZ)
  {
    this.hz = desiredHZ;
    this.inverval = 1.0e9/hz;
  }

  public void begin()
  {
    start = (double)System.nanoTime();
    delta     = ( start - last )*1.0e-6;
    currentHZ = 1000f/delta;
    last = start;
  }  

  // usually you would use this which yields the same result as using any java Timer class.
  public void end()
  {
    double now = (double)System.nanoTime();
    while(now - start < interval)
    {
      Thread.sleep(1);
      now = (double)System.nanoTime();
    }
  }

  // but to get it more precise we can use Thread.yield()
  public void endYielding()
  {
    double now = (double)System.nanoTime();
    double t;
    while(( t = now - start ) < interval)
    {
      // switch to expensive yield when remaining sleep time is less then a threshold.
      // ideally this would be 1 ms when sleep(1) would actually be a 1 ms sleep, what it never is.
      if(( interval - t ) < 1.4e7) Thread.yield();  // magic number 1.4e7, works for me tho. higher = more precise + higher cpu usage
      else Thread.sleep(1);
      now = System.nanoTime();
    }
  }
}


in a game loop :

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
public void init()
{
  clock = new clock(45.33f); // 45.33
}

public void update()
{
  clock.begin();

  // paint things
  // swapBuffers

  clock.endYielding(); // sleep
  System.out.println("current FPS : " + clock.currentHZ);
}


i'm not able to program a more precise timer in java Sad
Offline thedanisaur

JGO Knight


Medals: 59



« Reply #18 - Posted 2014-08-29 18:13:12 »

Since everyone is using Thread.sleep(), which I think looks rather bad, I thought I'd just leave this here...

http://gafferongames.com/game-physics/fix-your-timestep/

Every village needs an idiot Cool
Offline basil_

« JGO Bitwise Duke »


Medals: 418
Exp: 13 years



« Reply #19 - Posted 2014-08-29 21:49:32 »

Since everyone is using Thread.sleep(), which I think looks rather bad, I thought I'd just leave this here...

http://gafferongames.com/game-physics/fix-your-timestep/
that's related to game physics, not to reliable loop frequency.

Offline TehJavaDev

JGO Knight


Medals: 17
Projects: 3
Exp: 7-9 months


Java is so dope they wanna >:D


« Reply #20 - Posted 2014-08-29 21:53:36 »

http://gafferongames.com/game-physics/fix-your-timestep/ that's related to game physics, not to reliable loop frequency.

Thank you ^_^
And not to be rude Smiley but that link's been posted earlier in this threads page XD

Thanks for your feedback though (:

Checkout my new easy to use java networking library: GNetLib
Offline philfrei
« Reply #21 - Posted 2014-08-29 23:57:02 »

Quote
using Swing or other "timers" is fine. all of them use System.sleep(1) anyway.
@basil_
Well, sort of. The util.Timer relies on native code implementing Object's wait(long) method. It is set to a value that corresponds to the schedule of the next TimerTask on its internal queue. Thus the wait is probably larger than 1.

Thread.sleep(1) uses native code for sleep(long).

But both do make use of the System Clock which is either limited by larger of the granularity of the milliseconds input parameter, or by the minimum interval at which the clock is updated (about 16 millis for some older Microsoft OS).

I don't think the util.Timer adds much in the way of overhead. The most significant addition is a very nifty queue implementation set up for the TimerTasks (I think it's set to a simple array of 128 unique tasks), but it is a model of efficiency (written by Joshua Bloch). I would guess having a single wait(long) is probably better than multiple calls to sleep(1). But these are quibbles to your main point.

music and music apps: http://adonax.com
Offline basil_

« JGO Bitwise Duke »


Medals: 418
Exp: 13 years



« Reply #22 - Posted 2014-08-30 00:16:51 »

yes, that's what i ment. on windows we're stucked at 15-16 ms. no selfmade native can help here, System.nanoTime() already is.

at least instead of Thread.sleep(1) we can use
1  
LockSupport.parkNanos(500000); // 0.5 ms
what works pretty good on linux.

anyway, that's low level. for high level most java utils are useful in the end.
Offline SHC
« Reply #23 - Posted 2014-08-30 06:58:33 »

SHC -- Could you be more specific about your objections to the util.Timer?

There is no specific reason or objection, but I don't like them. I would like to quote Eli Delventhal's Game Loops article.

Quote from: Eli Delventhal
Decent loops, but I still wouldn't use them

I think I've seen the approach of using either java.util.Timer or javax.swing.Timer more often than any other approach (at least in amateur projects). This is nice because it saves you from having to deal with any part of the loop yourself, and it's more or less accurate. The reason for this is that neither of the two Timer classes are intended to be used as heavy-lifting tasks.

That's the only reason why I don't like those Timers in game loops. Hope this helps.

Offline BurntPizza

« JGO Bitwise Duke »


Medals: 486
Exp: 7 years



« Reply #24 - Posted 2014-08-30 17:21:03 »

If you're going to use a Timer for the convenience, you might as well use a ScheduledExecutorService:

1  
2  
3  
4  
5  
6  
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

scheduler.scheduleAtFixedRate(() -> {
    update();
    render();
}, 0, 16, TimeUnit.MILLISECONDS);


I still wouldn't do this for a game however, as you cannot control what happens when update() and render() take more than 16 ms.
Offline philfrei
« Reply #25 - Posted 2014-08-31 04:04:57 »

@SHC
I always found that quote from Eli to be very puzzling. So, util.Timer was not intended for heavy-lifting? How can a person tell this? It's just code. Nothing in the API warns about this, nor anything in Joshua Bloch's well-documented source code for the class. Code in the TimerTask runs the same as code in a game loop, as far as I can tell, though they rely on different native routines (wait vs sleep).

@BurntPizza
...doesn't the exact same thing happens when update() and render() take more than the allotted time: the next iteration simply gets pushed back? This is the same with the ScheduledExecutorService (as you configured it), with util.Timer and with a game loop. Yes?

But if the NEXT iteration after that takes less than 16 millis, with either the scheduler or timer's .sheduleAtFixedRate(), an attempt to recover the lost time, gratis, no extra coding needed.

I suspect that the poor reputation util.Timer has vs. coding one's own timing mechanisms into game loops has an element of "herding behavior" to it or some sort of echo chamber effect. I have yet to read one rational explanation or see a concrete example that justifies the preference. I point out again, even "Killer Game Programming" from way back when gets the same performance with util.Timer as with their preferred game loops, and then says well, we are going to stick with writing our own game loops anyway. (The book does an excellent job of demolishing the swing.Timer, though!)

But this is okay. It probably doesn't make a bit of difference, and my harping on this is an example of I don't know what. I certainly don't want to try and tell other people they should convert their game loops to TimerTasks.

music and music apps: http://adonax.com
Offline thedanisaur

JGO Knight


Medals: 59



« Reply #26 - Posted 2014-08-31 08:24:06 »

How is a fixed time step not reliable? It's the same idea but you never sleep the thread.

Edit: I suppose if you sleep the thread then you aren't wasting cpu time doing nothing. Also, my bad reposting the link.

Every village needs an idiot Cool
Offline basil_

« JGO Bitwise Duke »


Medals: 418
Exp: 13 years



« Reply #27 - Posted 2014-08-31 11:11:37 »

in a rendering loop a fixed timestep/sleep-duration is not taking the "payload" in count.

you might get a stable sleep but it would _add_ to the cpu-time spend updating and rendering things.
Pages: [1]
  ignore  |  Print  
 
 

 
Riven (397 views)
2019-09-04 15:33:17

hadezbladez (5280 views)
2018-11-16 13:46:03

hadezbladez (2204 views)
2018-11-16 13:41:33

hadezbladez (5544 views)
2018-11-16 13:35:35

hadezbladez (1150 views)
2018-11-16 13:32:03

EgonOlsen (4585 views)
2018-06-10 19:43:48

EgonOlsen (5462 views)
2018-06-10 19:43:44

EgonOlsen (3119 views)
2018-06-10 19:43:20

DesertCoockie (4016 views)
2018-05-13 18:23:11

nelsongames (4708 views)
2018-04-24 18:15:36
A NON-ideal modular configuration for Eclipse with JavaFX
by philfrei
2019-12-19 19:35:12

Java Gaming Resources
by philfrei
2019-05-14 16:15:13

Deployment and Packaging
by philfrei
2019-05-08 15:15:36

Deployment and Packaging
by philfrei
2019-05-08 15:13:34

Deployment and Packaging
by philfrei
2019-02-17 20:25:53

Deployment and Packaging
by mudlee
2018-08-22 18:09:50

Java Gaming Resources
by gouessej
2018-08-22 08:19:41

Deployment and Packaging
by gouessej
2018-08-22 08:04:08
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!