Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (526)
Games in Android Showcase (127)
games submitted by our members
Games in WIP (593)
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  
  I don't understand why this stutters?  (Read 4286 times)
0 Members and 1 Guest are viewing this topic.
Offline joeyismusic

Junior Devvie





« Posted 2012-04-12 22:24:39 »

Here are two game loops... one is of my creation, the other is the game loop from Minicraft

I can't figure out why my update's "stutter" and his are super smooth...

Here's mine:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
   public static final long nano_milli = 1000000L;
   public static final long nano_sec = 1000000000L;
   public static final long milli_per_sec = 1000L;
   public static final long ups = 32;

   long update_frame = 0;
   long update_frame_length = (milli_per_sec / ups) * nano_milli;
   private void gameLoop2() {
      while (running) {

         now = System.nanoTime();

         while (update_frame + update_frame_length <= now) {
            update();
            update_frame += update_frame_length;
         }
         
         render();
         try{ Thread.sleep(2); } catch(Exception e) {}
      }
   }


Here's his:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
   private void gameLoop() {
      long lastTime = System.nanoTime();
      double unprocessed = 0;
      double nsPerTick = 1000000000.0 / 60;

      while (running) {
         long now = System.nanoTime();
         unprocessed += (now - lastTime) / nsPerTick;
         lastTime = now;
         boolean shouldRender = true;
         while (unprocessed >= 1) {
            update();
            unprocessed -= 1;
            shouldRender = true;
         }

         try { Thread.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); }

         if (shouldRender) {
            render();
         }

      }
   }
Offline _Al3x

Senior Devvie


Medals: 7


Indie Games FTW!


« Reply #1 - Posted 2012-04-12 22:31:37 »

Hello there Smiley
I'm not sure if it's legal to post that code... I mean, it has copyrights, right?

Offline joeyismusic

Junior Devvie





« Reply #2 - Posted 2012-04-12 22:33:35 »

It's legal. The source is freely available.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline maxking1234

Senior Newbie





« Reply #3 - Posted 2012-04-12 22:34:00 »

Hello there Smiley
I'm not sure if it's legal to post that code... I mean, it has copyrights, right?

I think Notch released it as open source
Offline joeyismusic

Junior Devvie





« Reply #4 - Posted 2012-04-12 22:35:32 »

The legality of Minicraft's source is a nice conversation and all, but could we answer my question? I could have said it was from a friend and you'd have no idea it came from Minicraft, therefore its origin is irrelevant.

Thanks!
Offline ra4king

JGO Kernel


Medals: 355
Projects: 3
Exp: 5 years


I'm the King!


« Reply #5 - Posted 2012-04-12 23:11:07 »

Your loops runs at 32FPS while his runs at 60FPS Wink

In your code, the main inaccuracy I see is that you divide milli_per_sec by ups then multiply by nano_milli. It would be much more efficient and would result in more accurate update if you just divide nano_sec by ups.

In Notch's code, that "shouldRender" variable looks useless because it's always true, unless he has a bug where it should be set to false at first, only to be set to true when update() is called.

I never liked Notch's loop. It is way too inaccurate due to counting by 'ticks' (unprocessed) instead of nanoseconds or milliseconds.

Offline joeyismusic

Junior Devvie





« Reply #6 - Posted 2012-04-12 23:18:55 »

Ok, even at 60 FPS mine still has a "jump" every second or so it seems;

His shouldRender variable is actually useful because there are some stages of the loop where no update is necessary, therefore nothing is rendered;
It is set to false at the beginning of every loop, and if the math works out a certain way, shouldRender isn't set to true;
It's kind of tricky;

Anyways, I am using his loop with success for the time being;
It's for a roguelike, so I don't really need interpolation;
Offline joeyismusic

Junior Devvie





« Reply #7 - Posted 2012-04-12 23:20:26 »

Oops you're right, it is always set to true;

I think its supposed to be declared as false until proven true. I tried it and it worked;
Offline joeyismusic

Junior Devvie





« Reply #8 - Posted 2012-04-13 01:25:00 »

Your loops runs at 32FPS while his runs at 60FPS Wink

In your code, the main inaccuracy I see is that you divide milli_per_sec by ups then multiply by nano_milli. It would be much more efficient and would result in more accurate update if you just divide nano_sec by ups.

In Notch's code, that "shouldRender" variable looks useless because it's always true, unless he has a bug where it should be set to false at first, only to be set to true when update() is called.

I never liked Notch's loop. It is way too inaccurate due to counting by 'ticks' (unprocessed) instead of nanoseconds or milliseconds.

I did what you said about changing the calculation and it fixed the problem! Wow thanks!
Offline Screem
« Reply #9 - Posted 2012-04-13 01:27:20 »

Setting shouldRender to false after updating just caps the game at 60 FPS. The only reason it is never set to false is because Notch forgot to change it; he kept it true to see how fast the game ran while he was coding it.

Honestly, I wouldn't use Notch's game loop from Minicraft as an example. It was created in a haste since he had a time limit of 48 hours when making Minicraft. There are plently of amazing game loop example on the forums here, just look in the "Articles and tutorials" section. Cheesy

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline ra4king

JGO Kernel


Medals: 355
Projects: 3
Exp: 5 years


I'm the King!


« Reply #10 - Posted 2012-04-13 01:27:55 »

That's because you were losing 2/3 of a millisecond due to your innacurate calculation Smiley

@Screem, you mean setting it to false on line 10, right before the while loop, and then setting it to true when updating Wink

Offline joeyismusic

Junior Devvie





« Reply #11 - Posted 2012-04-13 01:32:19 »

Setting shouldRender to false after updating just caps the game at 60 FPS. The only reason it is never set to false is because Notch forgot to change it; he kept it true to see how fast the game ran while he was coding it.

Honestly, I wouldn't use Notch's game loop from Minicraft as an example. It was created in a haste since he had a time limit of 48 hours when making Minicraft. There are plently of amazing game loop example on the forums here, just look in the "Articles and tutorials" section. Cheesy

I have spent a week on game loops and ended up with either stuff I couldn't understand (so I will not use it until I understand it, because I'm not learning),
or stuff that just either didn't work or was too complex to get working in my lack of understanding...

I think the loop here is fine and simple for what I am doing. I am fine with strict limitations as well.

That said, I do agree that his loop was made in a hurry and probably isn't that great. I've seen a lot of stuff on the web, and even own quite a few books about it... the truth is I'm still not very satisfied with what I've found. The only book that comes close is Killer Game Programming, but his end solution tries to sleep for some calculated amount of time which ends up being completely an unreliable amount of time slept.
Offline joeyismusic

Junior Devvie





« Reply #12 - Posted 2012-04-13 01:51:59 »

That's because you were losing 2/3 of a millisecond due to your innacurate calculation Smiley

@Screem, you mean setting it to false on line 10, right before the while loop, and then setting it to true when updating Wink

if unprocessed isn't greater than or equal to 1, then shouldRender will remain false (when the code is fixed)
Offline ra4king

JGO Kernel


Medals: 355
Projects: 3
Exp: 5 years


I'm the King!


« Reply #13 - Posted 2012-04-13 01:56:08 »

That's because you were losing 2/3 of a millisecond due to your innacurate calculation Smiley

@Screem, you mean setting it to false on line 10, right before the while loop, and then setting it to true when updating Wink

if unprocessed isn't greater than or equal to 1, then shouldRender will remain false (when the code is fixed)
Correct.

Setting shouldRender to false after updating just caps the game at 60 FPS. The only reason it is never set to false is because Notch forgot to change it; he kept it true to see how fast the game ran while he was coding it.

Honestly, I wouldn't use Notch's game loop from Minicraft as an example. It was created in a haste since he had a time limit of 48 hours when making Minicraft. There are plently of amazing game loop example on the forums here, just look in the "Articles and tutorials" section. Cheesy
...or stuff that just either didn't work or was too complex to get working in my lack of understanding...
Check out Riven's super simplified game loop and super accurate sleeping method..

Offline joeyismusic

Junior Devvie





« Reply #14 - Posted 2012-04-13 02:00:33 »

Is there any way to use that without LWJGL?

My game runs as a JFrame and as an Applet with no dependencies.
Offline ra4king

JGO Kernel


Medals: 355
Projects: 3
Exp: 5 years


I'm the King!


« Reply #15 - Posted 2012-04-13 02:01:29 »

Of course, just rip out that Sync class and don't forget to include the license Smiley

Offline joeyismusic

Junior Devvie





« Reply #16 - Posted 2012-04-13 02:03:30 »

I am concerned about...

1  
2  
3  
4  
5  
import org.lwjgl.Sys;
...
   private static long getTime() {
      return (Sys.getTime() * NANOS_IN_SECOND) / Sys.getTimerResolution();
   }
Offline ra4king

JGO Kernel


Medals: 355
Projects: 3
Exp: 5 years


I'm the King!


« Reply #17 - Posted 2012-04-13 02:09:18 »

Hmm that looks useless. @Riven, what's the point of multiplying by 1e9 then dividing by 1e9? That just returns Sys.getTime() Tongue

EDIT: That looks like it could be a bug Riven, since it might overflow when multiplying by 1e9!

@Joey, just replace that with "return System.nanoTime()" for now.

Offline _Al3x

Senior Devvie


Medals: 7


Indie Games FTW!


« Reply #18 - Posted 2012-04-13 03:05:27 »

Hey, I'm reading "MINIcraft" now, but earlier I questioned about being legal to post that, because I read "MINEcraft" (facepalm).
To clarify, MINIcraft's code is open to everyone.
Sorry for my previous post if I offended anyone Smiley

Offline joeyismusic

Junior Devvie





« Reply #19 - Posted 2012-04-13 03:08:23 »

haha! That's pretty close to the troll notch pulled on everyone.

One of the last secrets in the game MINECRAFT was a 1 and some-thousandths chance of it saying "MINCERAFT" at the title screen.

A lot of people didn't catch it until he said something about it!
Offline joeyismusic

Junior Devvie





« Reply #20 - Posted 2012-04-13 03:10:03 »

Hmm that looks useless. @Riven, what's the point of multiplying by 1e9 then dividing by 1e9? That just returns Sys.getTime() Tongue

EDIT: That looks like it could be a bug Riven, since it might overflow when multiplying by 1e9!

@Joey, just replace that with "return System.nanoTime()" for now.
Perhaps some systems don't have the timer resolution fixed at 1e9
Online Riven
« League of Dukes »

« JGO Overlord »


Medals: 833
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #21 - Posted 2012-04-13 11:46:08 »

Hmm that looks useless. @Riven, what's the point of multiplying by 1e9 then dividing by 1e9? That just returns Sys.getTime() Tongue

EDIT: That looks like it could be a bug Riven, since it might overflow when multiplying by 1e9!

@Joey, just replace that with "return System.nanoTime()" for now.
Before screaming 'BUG!', you might want to read the docs.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline ReBirth
« Reply #22 - Posted 2012-04-13 12:41:48 »

@ra4king
although it's really simple, sync is not always good.

Offline ra4king

JGO Kernel


Medals: 355
Projects: 3
Exp: 5 years


I'm the King!


« Reply #23 - Posted 2012-04-13 18:00:37 »

Hmm that looks useless. @Riven, what's the point of multiplying by 1e9 then dividing by 1e9? That just returns Sys.getTime() Tongue

EDIT: That looks like it could be a bug Riven, since it might overflow when multiplying by 1e9!

@Joey, just replace that with "return System.nanoTime()" for now.
Before screaming 'BUG!', you might want to read the docs.
That's Sys's docs, but I'm assuming its getTime is the same? I don't quite understand what its docs are saying though :S

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.

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

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

toopeicgaming1999 (15 views)
2014-11-26 15:20:08

SHC (29 views)
2014-11-25 12:00:59

SHC (27 views)
2014-11-25 11:53:45

Norakomi (32 views)
2014-11-25 11:26:43

Gibbo3771 (27 views)
2014-11-24 19:59:16

trollwarrior1 (40 views)
2014-11-22 12:13:56

xFryIx (78 views)
2014-11-13 12:34:49

digdugdiggy (56 views)
2014-11-12 21:11:50
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

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