Java-Gaming.org    
Featured games (91)
games approved by the League of Dukes
Games in Showcase (577)
games submitted by our members
Games in WIP (498)
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  
  Game Timer  (Read 2032 times)
0 Members and 1 Guest are viewing this topic.
Offline Pyrodragoon

Junior Member




Art calculated with java...


« Posted 2008-03-08 13:05:26 »

Hi, i´ve got a problem with the timemanagement in my Game.
I searched a lot in these forums, but didn´t get the right idea of
how to manage that my sleep(32) really does sleep exactly 32 ms.
I don´t want to get new stuff for this, just Java 6.0 Update3 and nothing else
because some other people might want to play the game, too, but only
want to install simply Java.

So i hope someone can help me with this   Huh
Thanks
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 605
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #1 - Posted 2008-03-08 14:50:29 »

I've used this one for years:

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  
   public static final void sleep(long ms)
   {
      sleep(ms, true);
   }

   public static final void sleep(long ms, boolean consumeInterrupts)
   {
      final long end = (System.nanoTime()/1000000L) + ms;

      while ((System.nanoTime()/1000000L) < end)
      {
         try
         {
            long togo = end - (System.nanoTime()/1000000L);

            // ensure we don't suffer from OS 'sleep-snapping'
           long sleep = togo / 2 + 1;

            if (sleep > 0)
               Thread.sleep(sleep);
         }
         catch (InterruptedException exc)
         {
            if (consumeInterrupts)
            {
               Thread.currentThread().interrupt();
               Thread.interrupted();
            }
            else
            {
               return;
            }
         }
      }
   }

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

Junior Member




Art calculated with java...


« Reply #2 - Posted 2008-03-08 15:28:13 »

Sorry, in my App. it didn´t help, either way (my old way, or your way )
my max. FPS is now 38.
But it depends on my sleepSetting.
If i say sleep(1);
i get 38 FPS and it sleeps for like 26 ms., not my desired 1 ms, which might indeed be
impossible i guess.
But if i say sleep(32); , which should be possible,
i only get 14 FPS and ist sleeps for like 71 ms.
Why is that?
Here´s the code (i have an ownClass for my Thread for some reasons like FPS-tests):

package Tools.Helpers;

import java.awt.Toolkit;


/*
 * Created on 27.05.2007
 */

public class Threadder extends Thread {
   /*
    ----------------------------------------------
    --------------{Description}--------------
    ----------------------------------------------
   
    */
   //   ##################################################################################################
   //   #######################   ATTRIBUTE      ATTRIBUTE      ATTRIBUTE   ##############################
   //   ##################################################################################################

   //   +++++++++++++++++++++++++++++//
   /*   ---[ Thread ]---*/
   //   +++++++++++++++++++++++++++++//
   public long SLEEP = 200;
   long SLEEP_Backup;
   boolean THREADACTIVE = true;
   boolean isActive = true;

   //   +++++++++++++++++++++++++++++//
   /*   ---[ Listener ]---*/
   //   +++++++++++++++++++++++++++++//
   //---[ Listener, who takes Updates ]---*/
   ThreadderListener listener;


   //   ##################################################################################################
   //   #####################   KONSTRUKTOR   ##########################
   //   ##################################################################################################

   /*||Created on 25.07.2007||*/
   public Threadder(ThreadderListener newListener,int sleep) {
      super();
      listener = newListener;
      SLEEP = sleep;
      SLEEP_Backup = SLEEP;
      start();
   }

   //   ##################################################################################################
   //   ##########################   METHODS    ##############################
   //   ##################################################################################################

   public void run() {
      while(THREADACTIVE){
         //:::[ does actions, like repaint etc. ]::://
         listener.updateTime(1);
         if(isActive){
            listener.redoActions();
         }
         try {
            sleep(SLEEP);
         } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
         }
         listener.updateTime(2);
      }
   }

   //   ==========================================================================
   /*   ===[  ]===   */
   //   ==========================================================================   
   public void disableMe() {
      /*||Created on 31.05.2007||*/
      SLEEP_Backup = SLEEP;
      isActive = false;
      SLEEP = 1000;
   }

   //   ==========================================================================
   /*   ===[ Threadder reset ]===   */
   //   ==========================================================================   
   public void activate() {
      /*||Created on 06.08.2007||*/
      SLEEP = SLEEP_Backup;
      isActive = true;
   }


   //   ##################################################################################################
   //   ##################################################################################################
   //   ##################################################################################################
}

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

Senior Member





« Reply #3 - Posted 2008-03-10 18:32:08 »

The computer timer always has a certain granularity.  I use the millisecond timer (System.currentTimeMillis), and it has a 10-ms granularity on Windows XP, meaning that you always sleep for multiples of 10 ms.  On Linux and Mac, I believe the granularity is 1 ms.

When you use the sleep method you're using, it uses the millisecond timer.  There is a sleep method that uses milliseconds AND nanoseconds, but the real problem is that you're always sleeping the same amount of time.  What you need to do is sleep for the amount of time that's left in the frame.  Some of the time is already used up by the time you spend drawing and updating.  My own main loop code looks 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  
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  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
package cg.puzzlecarnival;
import cg.main.Time;
import cg.puzzlecarnival.gui.GuiAccess;

/**This class executes the main loop.
 * @author Steven Fletcher
 * @since 2007/08/14
 * @version 2008/02/21
 */

public class MainLoop {
/**Executes the game's main loop.*/
public static void execute() {
   //This variable is used to only skip yielding a certain number of times in a row.
  byte numDelays = 0;
   
   //This variable stores how much time the loop overslept by in the last cycle.
  //Negative values probably won't occur because Thread.sleep shouldn't undersleep.
  long overSleepTime = 0L;
   
   //This variable is used for computing the length of an update phase.
  long lastUpdatePhase = Time.currentTimeMillis();

   while(true) {
      //if the application isn't visible, sleep for half a second
     if(!GuiAccess.isApplicationActive()) {
         try {
            Thread.sleep(500);
         } catch(InterruptedException exception) {}
           
         continue;
      } //end if the frame isn't visible
     
      //figure out the start of the current phase
     long currentCycle = Time.currentTimeMillis();
      long updatePhaseLength = currentCycle - lastUpdatePhase;
      if(updatePhaseLength > period)
         updatePhaseLength = period;
     
      //update the current model
     GuiAccess.updateLogic(period);
      lastUpdatePhase = Time.currentTimeMillis();
   
      //render the game
     GuiAccess.showFrame();
   
      //figure out how long the cycle took
     long timeAfterCycle = Time.currentTimeMillis();
      long cycleLength = timeAfterCycle - currentCycle;
      long sleepTime = period - cycleLength - overSleepTime;
     
      //if some time is left in this cycle
     if(sleepTime > 0) {
         //sleep
        try {
            Thread.sleep(sleepTime);
         } catch(InterruptedException exception) {}
         
         overSleepTime = Time.currentTimeMillis() - timeAfterCycle - sleepTime;
      } //end if some time is left in this cycle
     //else no time is left in this cycle
     else {
         overSleepTime = 0L;
         
         //don't sleep, but yield if absolutely necessary
        numDelays++;
         if(numDelays >= maximumDelaysPerYield) {
            //yield to let other threads execute
           Thread.yield();
            numDelays = 0;
         } //end if there have been too many delays
     } //end else no time is left in this cycle
} //end while forever
} //end execute

//PRIVATE CONSTANTS//////////////////////////////////////////////////////////////////////
//the maximum number of consecutive cycles that can skip the yield
private static final int maximumDelaysPerYield = 16;

//private static final int maximumMillisecondsPerUpdate = 40;
//private static final int millisecondsPerFrameRedraw = 10;

//1000/period frames per second
private static final int period = 40;
} //end class MainLoop


The call to the Time method just calls System.currentTimeMillis.  GuiAccess is the class my paint and update methods are in.

As an aside, I wouldn't suggest switching to System.nanotime.  That particularly timer doesn't work reliably on processors with energy saving capabilities (which is common, especially on laptops) and older dual core AMD processors.
Offline broumbroum

Junior Member





« Reply #4 - Posted 2008-03-10 22:10:18 »

using Swing Timer's does simplify the way your frame rate varies, because even though a process cycle can take much more time than the initial delay, Swing will coalesce the pending cycles in one single cycle and wait for it to finish. Smiley
But as told above in the prev post, a good timer is always more accurate when the timing resolution is well managed with System times, as nanos are at higher resolutions better than millis. But higher resolution (i.e. smaller delays) are rather realized for the Animation framework. Wink

::::... :..... :::::: ;;;:::™ b23:production 2006 GNU/GPL @ http://b23prodtm.webhop.info
on sf.net: /projects/sf3jswing
Java (1.6u10 plz) Web Start pool
dev' VODcast[/ur
Offline Pyrodragoon

Junior Member




Art calculated with java...


« Reply #5 - Posted 2008-03-12 21:01:51 »

Hi again.
I need to thank you a lot. This one did the job  Smiley
My testframe runs almost constantly with 24-25 FPS like I want it.
With your way of solving this problem I can also run it at 50 FPS constantly
but I guess 25 is enough as the human eye sees less  Wink
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 605
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #6 - Posted 2008-03-12 23:15:10 »

I hear that thing about 25fps for the human eye so often, but it's just not true.

I can clearly see the difference between 60 and 80fps. (on a TFT monitor)

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

Junior Member




Art calculated with java...


« Reply #7 - Posted 2008-03-13 01:51:28 »

I think that´s based on the animation/games you look at.
60/80 FPS doesn´t mean every function in the game etc.
runs at 60/80 FPS.
For example, you need to refresh walk-cycles much more than
some effect like raind or a tilebased animation.
So the difference you see between 60 and 80 FPS is what was intended
to be seen different I guess.
Please correct me if I´m wrong, not so long in the business, but that´s what
I explored when playing different games and programming effects like mentioned before.
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.

xsi3rr4x (19 views)
2014-04-15 18:08:23

BurntPizza (15 views)
2014-04-15 03:46:01

UprightPath (28 views)
2014-04-14 17:39:50

UprightPath (13 views)
2014-04-14 17:35:47

Porlus (29 views)
2014-04-14 15:48:38

tom_mai78101 (54 views)
2014-04-10 04:04:31

BurntPizza (111 views)
2014-04-08 23:06:04

tom_mai78101 (212 views)
2014-04-05 13:34:39

trollwarrior1 (181 views)
2014-04-04 12:06:45

CJLetsGame (187 views)
2014-04-01 02:16:10
List of Learning Resources
by Longarmx
2014-04-08 03:14:44

Good Examples
by matheus23
2014-04-05 13:51:37

Good Examples
by Grunnt
2014-04-03 15:48:46

Good Examples
by Grunnt
2014-04-03 15:48:37

Good Examples
by matheus23
2014-04-01 18:40:51

Good Examples
by matheus23
2014-04-01 18:40:34

Anonymous/Local/Inner class gotchas
by Roquen
2014-03-11 15:22:30

Anonymous/Local/Inner class gotchas
by Roquen
2014-03-11 15:05: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!