Java-Gaming.org Hi !
Featured games (90)
games approved by the League of Dukes
Games in Showcase (781)
Games in Android Showcase (233)
games submitted by our members
Games in WIP (857)
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  
  The game loop  (Read 336 times)
0 Members and 1 Guest are viewing this topic.
Offline hadezbladez

Junior Devvie


Medals: 4
Projects: 1
Exp: 2 years


Insert Personal Text


« Posted 2019-02-11 19:47:52 »

Hey guys! its been awhile  Cool
So lets get into the meat of the problem as the title mention
I still didnt get it about making good game loop and heres the project

https://github.com/hadezbladez/DodgeThis_project/tree/master  Pointing

and heres the code

   private void gameLoop(int loopingPreferences){
      long now = 0; long lastTime = System.nanoTime();
      long deltaTime = 0; long deltaFixComb = 0; long nanoSecond = 1000000000l;
      threadSleeping(1);

      while(running){
         if(loopingPreferences == COMBINE_updateAndRender){
            now = System.nanoTime();
            deltaFixComb += ((now - lastTime) * fps) ;
            lastTime = now;
            systemControls(); //<< this thing handle the input from system or controller
            
            if(deltaFixComb >= nanoSecond){
               updateMechanism(loopingPreferences, 0);
               renderMechanism(loopingPreferences, 0, false);
               deltaFixComb -= nanoSecond;
            }
            
            if(loop_memoryProcess_Model == memorySafe){threadSleeping(1); Thread.yield();}//<< doesnt cause frameRate drops
            threadSleeping(1);
         }
         else if(loopingPreferences == LIMITupdate_MAXIMUMrender){}
         else if(loopingPreferences == SEPARATE_updateAndRender){//using this does change fps
            //timings
            now = System.nanoTime();
            deltaTime = now - lastTime;
            lastTime = now;
            systemControls();
            
            updateMechanism(loopingPreferences, deltaTime);
            renderMechanism(loopingPreferences, deltaTime, false);
            
            if(loop_memoryProcess_Model == memorySafe){threadSleeping(1); Thread.yield();}//<< optional and causing frameRate drops
         }
      }
      
   }

yes, i make the game loop that doesnt catch any decimal point. at first, I thought that thing are making the game lags but, it still didnt solve anything. The green box still can get jaggy and it did look like something was off. Was the problem the render itself, my computer specification, that was the limit of java or something? i dont know. at this point, i dont have any idea fix the jaggy box thingy  Huh  Huh  Huh  Huh  Huh
Offline VaTTeRGeR
« Reply #1 - Posted 2019-02-11 21:26:59 »

Sleep is very inaccurate depending on your operating system, if you really want very accurate sleep you need to spin-wait for the last few milliseconds. You probably don't need sleep that accurate for your game though, but i added this method anyway so you can try it out.

And simplify some stuff, don't over-complicate your loop, use some proper formatting, etc.


This is how a simple but accurate version could look like.

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  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
   private void gameLoop() {

      // http://lmgtfy.com/?q=1s%2F60+in+nanoseconds
      // The ideal time for one iteration of the loop in ns
      long tLoop = TimeUnit.SECONDS.toNanos(1) / fps;

      // The timestamp of the beginning of the loop in ns
      long tBegin;
     
      // The time that was spent in the previous iteration of the loop in ns
      long tDelta;
     

      // remember to make running volatile if you change it from another thread!
      while ( running ) {
         
         // We need one measurement at the beginning.
         tBegin = System.nanoTime();

         systemControls();

         updateMechanism(tDelta);
         renderMechanism(tDelta, false);

         // Sleep for the duration of the frame minus the time already spent rendering/updating.
         try {
            sleepNanos( tLoop - ( System.nanoTime() - tBegin ) );
         } catch (InterruptedException e) {
            // TODO: handle exception
         }
         
         // The actual loop time can be calculated now as we have finished the loop.
         tDelta = System.nanoTime() - tBegin;
      }
   }

   // The accuracy of your sleep method could be around ~3ms - try some values!
   final static long SLEEP_PRECISION = TimeUnit.MICROSECONDS.toNanos(2500);
   
   // The approximate time it takes to return after yield, should be very small.
   final static long SPIN_YIELD_PRECISION = TimeUnit.MICROSECONDS.toNanos(500);

   // This will sleep if far away and spin near the target time, depending on your settings above.
   // Visit https://stackoverflow.com/a/2986919 for the source of this method and further info!
   public static void sleepNanos (long nanoDuration) throws InterruptedException {
     
        final long end = System.nanoTime() + nanoDuration;
       
        long timeLeft = nanoDuration;

        do {
            if (timeLeft > SLEEP_PRECISION)
                Thread.sleep (1);
            else
                if (timeLeft > SPIN_YIELD_PRECISION)
                    Thread.yield();

            timeLeft = end - System.nanoTime();
        } while (timeLeft > 0);
    }


TimeUnit outputs long values, do not use it to convert nanoseconds to milli/seconds, you'll loose precision.

Check out this explanation of the effects of Thread.yield() vs Thread.sleep(): https://stackoverflow.com/questions/11480912/thread-sleep-or-thread-yield

If you really want to uncouple rendering and updating you need to do much much more work than this, they basically aren't uncoupled (meaning: they don't block each other) as long as they are running in the same thread. Don't try it until you understand multi-threading and synchronization well enough, the gain to cost ratio is very low for a small game.

To enhance the waiting mechanism further you could use the previous delta value to fine-tune the next sleep cycle, but it should be good as it is right now. Another thing you could do is add some limits and checks to the values, to make sure times don't go negative or super large.
Offline hadezbladez

Junior Devvie


Medals: 4
Projects: 1
Exp: 2 years


Insert Personal Text


« Reply #2 - Posted 2019-02-12 05:49:33 »

I use sleep when for debugging since it takes less CPU usage on task manager and yes it might be the problem i try its not that thing that can get laggy.
Yes, i think my game-loop is too complicated i will manage it.

Thanks for the idea about a game loop  Grin
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline VaTTeRGeR
« Reply #3 - Posted 2019-02-12 10:09:54 »

In case you didn't get the memo ... i didn't post this so you can be inspired Roll Eyes this is so you can try out the clean version and see if your issue persists.

If this doesn't fix it you have a problem elsewhere, maybe with vsync or with the code you use to move your box object.
Offline philfrei
« Reply #4 - Posted 2019-02-12 19:20:09 »

A long time ago we had posts about a hack that would kick the clock into a higher gear, getting around the rather large granularity of the default clock used by Windows OS. Does this still pertain? Or has Microsoft upped the granularity of their default system clocking? It seems to me that Windows is now fine in this regard.

[Found this: http://www.java-gaming.org/topics/thread-sleep-in-gameloop/36423/msg/345479/view.html#msg345479]

For me, I've always preferred using timers. The "game loop" becomes a "TimerTask" or equivalent that is called repeatedly.

Even as far back as "Killer Game Programming in Java" the authors conceded that using the util.Timer (but NOT the Swing.Timer!) was as performant as the sleep methods being described.

Goetz's "Java Concurrency in Practice" makes a good case for using ExecutorService in place of util.Timer. For non-JavaFX programs, this is my go-to choice. Among other benefits, you can configure the timer to execute as close as possible to the desired timing interval (i.e., it tries to correct itself if an iteration takes longer than it should).

My top preference is the JavaFX AnimationTimer. It is simple, clear, easy to code and works perfectly well imho. A drawback for some will be that it is set to 60 fps and I don't know of any way to change that rate. But with so many monitors still refreshing at 60fps, I'm not clear what is gained by a faster game-loop rate that couldn't be implemented at 60fps.

music and music apps: http://adonax.com
Pages: [1]
  ignore  |  Print  
 
 

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

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

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

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

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

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

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

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

nelsongames (2123 views)
2018-04-24 18:15:36

nelsongames (2817 views)
2018-04-24 18:14:32
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

Deployment and Packaging
by gouessej
2018-08-22 08:03:45

Deployment and Packaging
by philfrei
2018-08-20 02:33:38

Deployment and Packaging
by philfrei
2018-08-20 02:29:55

Deployment and Packaging
by philfrei
2018-08-19 23:56:20
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!