Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (539)
Games in Android Showcase (133)
games submitted by our members
Games in WIP (603)
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  
  Yet another game loop ><  (Read 3629 times)
0 Members and 1 Guest are viewing this topic.
Offline AbstractChaos

Senior Newbie


Medals: 2



« Posted 2011-12-23 20:47:09 »

Hey guys i'm new here.
I have been working on a Block breaker clone for desktop as a project to get me used to the best practices and designs idioms for Java games. I have a first version which worked great on my more powerful laptop but when I went to my Net book I found it stuttered badly.I have seen all your different game loops but with no definitive answer on the best I was wondering if you guys could suggest improvements for my attempt at it Smiley

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  
private void gameLoop() {
      // Regenerate the game objects for a new game
      // ......
      state = State.PLAYING;
   
      // Game loop
      long beginTime, timeTaken, timeLeft;
      while (true) {
         beginTime = System.nanoTime();
         if (state == State.GAMEOVER) break;  // break the loop to finish the current play
         if (state == State.PLAYING) {
            // Update the state and position of all the game objects,
            // detect collisions and provide responses.
            gameUpdate();
         }
         // Refresh the display
         repaint();
         // Delay timer to provide the necessary delay to meet the target rate
         timeTaken = System.nanoTime() - beginTime;
         timeLeft = (UPDATE_PERIOD - timeTaken) / 1000000L;  // in milliseconds
         if (timeLeft < 10) timeLeft = 10;   // set a minimum
         try {
            // Provides the necessary delay and also yields control so that other thread can do work.
            Thread.sleep(timeLeft);
         } catch (InterruptedException ex) { }
      }
   }


As a side question is it better to leave Swing to handle the screen or should I handle that myself?

Thanks guys
AbtractChaos
Offline ra4king

JGO Kernel


Medals: 356
Projects: 3
Exp: 5 years


I'm the King!


« Reply #1 - Posted 2011-12-23 21:03:36 »

Thread.sleep is very inaccurate on most hardware/OSs, use this trick to force the OS to use the high precision timer:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
new Thread() {
    {
        setDaemon(true);
        start();
    }

    public void run() {
        while(true) {
            try {
                Thread.sleep(Long.MAX_VALUE);
            }
            catch(Exception exc) {}
        }
    }
};

Put this in your main.

Also different computers run at different speeds, so it is best to use a deltaTime when moving your sprites. DeltaTime is the time that last frame took to complete. You then pass this number to your update method. To use this deltaTime value, you divide it by 1e9 (nanoseconds per second) and multiply it by the speed at which you want to move per second.
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
long lastTime = System.nanoTime();
long frameTime = (long)(FPS/1e9);
while(true) {
    long now = System.nanoTime();
    long deltaTime = now - lastTime;
    lastTime += frameTime;
   
    gameUpdate(deltaTime);
   
    ....
}

public void gameUpdate(deltaTime) {
    speed += accelPerSecond * deltaTime / 1e9;
   
    playerPos.x += (speed * deltaTime / 1e9) * Math.cos(direction);
    playerPos.y += (speed * deltaTime / 1e9) * Math.sin(direction);
}


Setting a minimum of 10 milliseconds is also not good because if the game loop is late and needs to catch up, it will never be able to. Don't set a minimum at all.

Calling repaint() every frame and letting another thread to draw the screen is called passive rendering. The best way to render is active rendering. This is where you call paint in your game loop.

Offline AbstractChaos

Senior Newbie


Medals: 2



« Reply #2 - Posted 2011-12-23 21:15:40 »

Thanks  Grin, I will give that a go
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Abuse

JGO Knight


Medals: 15


falling into the abyss of reality


« Reply #3 - Posted 2011-12-23 23:18:09 »

Thread.sleep is very inaccurate on most hardware/OSs, use this trick to force the OS to use the high precision timer:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
new Thread() {
    {
        setDaemon(true);
        start();
    }

    public void run() {
        while(true) {
            try {
                Thread.sleep(Long.MAX_VALUE);
            }
            catch(Exception exc) {}
        }
    }
};

Put this in your main.

Also different computers run at different speeds, so it is best to use a deltaTime when moving your sprites. DeltaTime is the time that last frame took to complete. You then pass this number to your update method. To use this deltaTime value, you divide it by 1e9 (nanoseconds per second) and multiply it by the speed at which you want to move per second.
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
long lastTime = System.nanoTime();
long frameTime = (long)(FPS/1e9);
while(true) {
    long now = System.nanoTime();
    long deltaTime = now - lastTime;
    lastTime += frameTime;
   
    gameUpdate(deltaTime);
   
    ....
}

public void gameUpdate(deltaTime) {
    speed += accelPerSecond * deltaTime / 1e9;
   
    playerPos.x += (speed * deltaTime / 1e9) * Math.cos(direction);
    playerPos.y += (speed * deltaTime / 1e9) * Math.sin(direction);
}


Setting a minimum of 10 milliseconds is also not good because if the game loop is late and needs to catch up, it will never be able to. Don't set a minimum at all.

Calling repaint() every frame and letting another thread to draw the screen is called passive rendering. The best way to render is active rendering. This is where you call paint in your game loop.

There are schools of thought that disagree with everything (except the sleep daemon Thread to force high precision timer) you've said there Smiley

It depends upon what you are doing as to the best approach.

Make Elite IV:Dangerous happen! Pledge your backing at KICKSTARTER here! https://dl.dropbox.com/u/54785909/EliteIVsmaller.png
Offline AbstractChaos

Senior Newbie


Medals: 2



« Reply #4 - Posted 2011-12-24 00:52:18 »

Well i work with java as a job just not gaming and i found it always a good idea to follow "best practises" to keep the code easy to maintain and test. I guess i am trying to find the best approach to making the game loop and the game in general. When it comes to game programming i am a newbie. I will try to explain what i trying to do here and maybe you nice people could be so kind to help Smiley

I want a general architecture to handle everything about the game from resource management to the famous game loop, ability to set full screen on a game would be a nice option too. I understand there is plenty of libraries that will handle all of this for me but i'm afraid i wont learn which could cause more problems in the future Smiley
Offline Orangy Tang

JGO Kernel


Medals: 56
Projects: 11


Monkey for a head


« Reply #5 - Posted 2011-12-24 01:24:38 »

I have seen all your different game loops but with no definitive answer on the best

There is no 'best' game loop, just ones with different trade offs. Fixed steps vs. variable steps, fixed framerate vs. variable framerate, different methods that degrade under high load differently (eg. slowdown vs. dropped frames).

It really depends on exactly what kind of game and conditions you're aiming at. 2d or 3d? 2d games tend to look bad at variable framerates, but 3d can cope with that much better. Single player or networked? Singleplayer games might prefer to have slowdown if the cpu can't keep up - that's obviously bad if you're running a networked game.

[ TriangularPixels.com - Play Growth Spurt, Rescue Squad and Snowman Village ] [ Rebirth - game resource library ]
Offline AbstractChaos

Senior Newbie


Medals: 2



« Reply #6 - Posted 2011-12-24 01:44:21 »

Hmm i see your point this all stems from an issue i have where my paddle on a simple block breaker clone is freezes for a split second yet animation continues even updates continue as the balls carry on moving
(quite annoying since I now cant win Tongue ). All I can guess is it something im missing when it comes to keyboard inputs.
Offline dah01

Junior Devvie


Medals: 7



« Reply #7 - Posted 2011-12-24 02:44:24 »

What is this Thread.sleep business? http://why.how.does.that.give.you.high.precision.timer.com/idontunderstand.html
Offline namrog84

JGO Ninja


Medals: 46
Projects: 4


Keep programming!


« Reply #8 - Posted 2011-12-24 02:48:59 »


 Tongue your http link doesn't work for me  Roll Eyes

"Experience is what you get when you did not get what you wanted"
Offline Mr. Gol

Senior Devvie


Medals: 1



« Reply #9 - Posted 2011-12-24 11:59:36 »

Thread.sleep is very inaccurate on most hardware/OSs, use this trick to force the OS to use the high precision timer: (...)

I remember this being brought up a number of times before, but I never read the rationale behind it. Could you explain how creating a daemon thread leads to Thread.sleep() being more precise?
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Mike

« JGO Spiffy Duke »


Medals: 87
Projects: 1
Exp: 6 years


Java guru wanabee


« Reply #10 - Posted 2011-12-24 12:59:43 »

It forces the OS (only Windows?) to use high precision timers. If you need an even more precise answer I'm sure one of the gurus can answer it Smiley

Mike

My current game, Minecraft meets Farmville and goes online Smiley
State of Fortune | Discussion thread @ JGO
Offline dah01

Junior Devvie


Medals: 7



« Reply #11 - Posted 2011-12-24 14:12:27 »

Can't you just use system.getNanotime?
Offline ra4king

JGO Kernel


Medals: 356
Projects: 3
Exp: 5 years


I'm the King!


« Reply #12 - Posted 2011-12-24 19:22:57 »

All I know is that the Windows default timer has a resolution of about 10ms, while Linux and Mac are fine are 1ms. There are many topics on JGO where this has been discussed before.

Offline AbstractChaos

Senior Newbie


Medals: 2



« Reply #13 - Posted 2011-12-24 19:25:14 »

Even the:
1  
System.nanoTime()
, I thought it was released by Java for the very reason of certain OS's not having a high enough granularity?
Offline Z-Man
« Reply #14 - Posted 2011-12-24 21:46:00 »

Even the:
1  
System.nanoTime()
, I thought it was released by Java for the very reason of certain OS's not having a high enough granularity?
It doesn't matter, even if your using System.nanoTime() in your game loop, Thread.sleep() still has an low (10ms) timer resolution on Windows. So even if you use System.nanoTime() to sync your game loop to the desired FPS/UPS, calling Thread.sleep() to wait for the left over time could be inaccurate, i.e. sleep for an incorrect amount of time, and therefore throw off your game loop. That's why the daemon hack is used to force Windows to use a higher resolution.

EDIT: I forgot to mention that, according to the Java 6 API, System.currentTimeMillis()'s granularity is dependent on the OS, and System.nanoTime() will return the value of the OS's most precise available timer, in nanoseconds.

Thread.sleep is very inaccurate on most hardware/OSs, use this trick to force the OS to use the high precision timer: (...)

I remember this being brought up a number of times before, but I never read the rationale behind it. Could you explain how creating a daemon thread leads to Thread.sleep() being more precise?
AFAIK making the thread a daemon isn't important, it is only to keep it from forcing the program to continue running after all the other threads have finished. I believe the JVM will stop daemon threads after all non-daemon threads have stopped and then terminate the program. As for why the hack works, all I know is that if you keep a thread sleeping indefinitely it somehow helps force Windows to use the higher resolution timer. I don't know if anybody has ever said anything as to WHY it works.
Offline theagentd

« JGO Bitwise Duke »


Medals: 366
Projects: 2
Exp: 8 years



« Reply #15 - Posted 2011-12-25 14:17:44 »

The timer used is global for the OS. All programs that are running use the same timer, and Java switches the operating system to the better timer when sleep() is called and then switches back again when it ends. It doesn't seem to work when sleeping for short amounts of time though, since the sleep is shorter than the precision of the standard timer. Having an endlessly sleeping thread in the background costs nothing and forces the high-precision timer all the time, and it doesn't prevent your game from exiting as it's daemon. Or so I've heard.

Myomyomyo.
Offline philfrei
« Reply #16 - Posted 2011-12-25 22:08:37 »

@AbstractChaos:

In terms of doing things where the "general architecture" handles as much as is reasonable, IMHO, it is quite acceptable to use a Timer object to run your game loop with passive rendering. (I am imagining ra4king with fingers in his ears singing "la la la" while I say this. Wink)

With a Timer, one can set a "TimerTask" to repeat indefinitely at a given interval, which circumvents the need to manage cycle time consistency. Quite a few people here don't like this method, but I think it is fine for games where you have some slack, aren't trying to eke the max out of every cpu cycle. Note that there are two different repeating modes, one where TimerTasks go end-on-end (and cycle times can slip), another where the system does its best to keep the starting times absolutely on track.

Basically, one writes a TimerTask that will do the following:

1) call update() on all updateable objects (which could be in a collection)
2) call reprint() on the display screen.

The calling code specifies the duration, in milliseconds, between the calls to this TimerTask. Pretty simple!

"Killer Game Programming in Java" analyzes the Timer as an option (not their first choice either) and concludes that the java.util.timer (as opposed to the swing.timer) has decent resolution, pretty comparable to their regular game loop. The inaccuracy due to the OS/system clock issue still pertains, as does the solution already mentioned. The concurrency issues that arise with util.Timer seem quite manageable to me. Again, some folks strongly disagree. I think that learning to code in a thread-safe way is generally a good thing.

Since Java 1.5, a ScheduledThreadPoolExecutor is considered a superior option to a Timer. This is what I plan to do try in place of my Timer-based game loop, when I'm ready to refactor Hexara.

I haven't dealt with full screen mode, but the Java Tutorials devotes a full section just for demanding graphical applications, which includes info on this. If you haven't seen it yet, you might want to check it out:
http://docs.oracle.com/javase/tutorial/extra/fullscreen/index.html

"It's after the end of the world! Don't you know that yet?"
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

rwatson462 (37 views)
2014-12-15 09:26:44

Mr.CodeIt (31 views)
2014-12-14 19:50:38

BurntPizza (62 views)
2014-12-09 22:41:13

BurntPizza (99 views)
2014-12-08 04:46:31

JscottyBieshaar (60 views)
2014-12-05 12:39:02

SHC (74 views)
2014-12-03 16:27:13

CopyableCougar4 (77 views)
2014-11-29 21:32:03

toopeicgaming1999 (138 views)
2014-11-26 15:22:04

toopeicgaming1999 (127 views)
2014-11-26 15:20:36

toopeicgaming1999 (38 views)
2014-11-26 15:20:08
Resources for WIP games
by kpars
2014-12-18 10:26:14

Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50
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!