Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (540)
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  
  Why is this stuttering?  (Read 1378 times)
0 Members and 1 Guest are viewing this topic.
Offline joeyismusic

Junior Devvie





« Posted 2012-04-28 23:00:21 »

Here's a demo of the applet

http://www.joeysturgis.com/roguelike

Here's the game loop:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
   private void gameLoop3(long ufreq) {
      long nanosInSecond = 1000L * 1000L * 1000L;
      long updateFrequency = ufreq;
      long updateInterval = nanosInSecond / updateFrequency;
      long nextUpdateTick = System.nanoTime();
      while (true) {
         long start = System.nanoTime();
         for (long now = System.nanoTime(); now > nextUpdateTick; nextUpdateTick += updateInterval) {
            this.update();
         }
         process_time += System.nanoTime() - start;
         render();
         Sync.sync(60);
      }
   }


Here's sync:

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  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
113  
114  
115  
116  
117  
118  
119  
120  
121  
122  
123  
124  
125  
126  
127  
128  
129  
130  
131  
132  
133  
134  
135  
136  
137  
138  
139  
140  
141  
142  
143  
144  
145  
146  
147  
148  
149  
150  
151  
152  
153  
154  
155  
156  
157  
158  
159  
160  
161  
162  
163  
164  
165  
166  
167  
168  
169  
170  
171  
172  
173  
/*
 * Copyright (c) 2002-2012 LWJGL Project
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of 'LWJGL' nor the names of
 *   its contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package com.ingamedev.util;

/**
* A highly accurate sync method that continually adapts to the system
* it runs on to provide reliable results.
*
* @author Riven
* @author kappaOne
*/

public class Sync {

   /** number of nano seconds in a second */
   private static final long NANOS_IN_SECOND = 1000L * 1000L * 1000L;

   /** The time to sleep/yield until the next frame */
   private static long nextFrame = 0;
   
   /** whether the initialisation code has run */
   private static boolean initialised = false;
   
   /** for calculating the averages the previous sleep/yield times are stored */
   private static RunningAvg sleepDurations = new RunningAvg(10);
   private static RunningAvg yieldDurations = new RunningAvg(10);
   
   
   /**
    * An accurate sync method that will attempt to run at a constant frame rate.
    * It should be called once every frame.
    *
    * @param fps - the desired frame rate, in frames per second
    */

   public static void sync(int fps) {
      if (fps <= 0) return;
      if (!initialised) initialise();
     
      try {
         // sleep until the average sleep time is greater than the time remaining till nextFrame
         for (long t0 = getTime(), t1; (nextFrame - t0) > sleepDurations.avg(); t0 = t1) {
            Thread.sleep(1);
            sleepDurations.add((t1 = getTime()) - t0); // update average sleep time
         }
   
         // slowly dampen sleep average if too high to avoid yielding too much
         sleepDurations.dampenForLowResTicker();
   
         // yield until the average yield time is greater than the time remaining till nextFrame
         for (long t0 = getTime(), t1; (nextFrame - t0) > yieldDurations.avg(); t0 = t1) {
            Thread.yield();
            yieldDurations.add((t1 = getTime()) - t0); // update average yield time
         }
      } catch (InterruptedException e) {
         
      }
     
      // schedule next frame, drop frame(s) if already too late for next frame
      nextFrame = Math.max(nextFrame + NANOS_IN_SECOND / fps, getTime());
   }
   
   /**
    * This method will initialise the sync method by setting initial
    * values for sleepDurations/yieldDurations and nextFrame.
    *
    * If running on windows it will start the sleep timer fix.
    */

   private static void initialise() {
      initialised = true;
     
      sleepDurations.init(1000 * 1000);
      yieldDurations.init((int) (-(getTime() - getTime()) * 1.333));
     
      nextFrame = getTime();
     
      String osName = System.getProperty("os.name");
     
      if (osName.startsWith("Win")) {
         // On windows the sleep functions can be highly inaccurate by
         // over 10ms making in unusable. However it can be forced to
         // be a bit more accurate by running a separate sleeping daemon
         // thread.
         Thread timerAccuracyThread = new Thread(new Runnable() {
            public void run() {
               try {
                  Thread.sleep(Long.MAX_VALUE);
               } catch (Exception e) {}
            }
         });
         
         timerAccuracyThread.setDaemon(true);
         timerAccuracyThread.start();
      }
   }

   /**
    * Get the system time in nano seconds
    *
    * @return will return the current time in nano's
    */

   private static long getTime() {
      //return (Sys.getTime() * NANOS_IN_SECOND) / Sys.getTimerResolution();
      return System.nanoTime();
   }

   private static class RunningAvg {
      private final long[] slots;
      private int offset;
     
      private static final long DAMPEN_THRESHOLD = 10 * 1000L * 1000L; // 10ms
      private static final float DAMPEN_FACTOR = 0.9f; // don't change: 0.9f is exactly right!

      public RunningAvg(int slotCount) {
         this.slots = new long[slotCount];
         this.offset = 0;
      }

      public void init(long value) {
         while (this.offset < this.slots.length) {
            this.slots[this.offset++] = value;
         }
      }

      public void add(long value) {
         this.slots[this.offset++ % this.slots.length] = value;
         this.offset %= this.slots.length;
      }

      public long avg() {
         long sum = 0;
         for (int i = 0; i < this.slots.length; i++) {
            sum += this.slots[i];
         }
         return sum / this.slots.length;
      }
     
      public void dampenForLowResTicker() {
         if (this.avg() > DAMPEN_THRESHOLD) {
            for (int i = 0; i < this.slots.length; i++) {
               this.slots[i] *= DAMPEN_FACTOR;
            }
         }
      }
   }
}


Here's render:

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  
   public void render() {
      frames++;
      frame_count++;
     
      long start = System.nanoTime();

      Graphics2D g = tmp.createGraphics();
      g.setColor(Color.black);
      g.fillRect(0, 0, WIDTH, HEIGHT);
     
      level.draw_edge_persepctive(g, SpriteType.ranger, x, y, pixel_x, pixel_y, 13, 9);
     
      for(Entity e : entities) {
         e.render(g, level.p_screen_x, level.p_screen_y);
      }
     
      Font.printString(tmp, "Rogu3", 4, 4, 5, 0x65DE31, 0x454545);
      Font.printString(tmp, "Power: " + score, 4, Font.h * 2 + 4, 24, 0xFA1122, 0x911122);
      Font.printString(tmp, "Entities: " + Level.ent_count, 4, Game.HEIGHT - (Font.h * 2) - 4, 24, 0xFFFFFF, 0x000000);
      Font.printString(tmp, "FPS: " + fps, 800 - 80 - 16, 4, 50, 0xABABAB, 0x232323);
     
      announce(g);
     
      g.drawImage(Art.border, 0, 0, 8, 8, 0, 0, 8, 8, null);
      g.drawImage(Art.border, Game.WIDTH - 8, 0, Game.WIDTH, 8, 24, 0, 32, 8, null);
      g.drawImage(Art.border, 0, Game.HEIGHT - 8, 8, Game.HEIGHT, 0, 24, 8, 32, null);
      g.drawImage(Art.border, Game.WIDTH - 8, Game.HEIGHT - 8, Game.WIDTH, Game.HEIGHT, 24, 24, 32, 32, null);
     
      for(int ix = 0; ix <= 50; ix ++) {
         g.drawImage(Art.border, 8 + (ix * 16), 0, 8 + (ix * 16) + 16, 8, 8, 0, 24, 8, null);
      }
      for(int ix = 0; ix <= 50; ix ++) {
         g.drawImage(Art.border, 8 + (ix * 16), Game.HEIGHT - 8, 8 + (ix * 16) + 16, Game.HEIGHT, 8, 24, 24, 32, null);
      }
      for(int iy = 0; iy <= 34; iy ++) {
         g.drawImage(Art.border, 0, 8 + (iy * 16), 8, 8 + (iy * 16) + 16, 0, 8, 8, 24, null);
      }
      for(int iy = 0; iy <= 34; iy ++) {
         g.drawImage(Art.border, Game.WIDTH - 8, 8 + (iy * 16), Game.WIDTH, 8 + (iy * 16) + 16, 24, 8, 32, 24, null);
      }

      g.dispose();
      g = getGraphics();
      if(g != null) {
         g.drawImage(tmp, 0, 0, null);
         g.dispose();
         flip();//show's the bufferstrategy
      }
     
      render_time = System.nanoTime() - start;
     
      if (System.nanoTime() > next_frame_count) {
         next_frame_count = System.nanoTime() + 1000000000;
         fps = frame_count;
         frame_count = 0;
         System.out.println("FPS: " + fps + ", Process Time: " + process_time / 60 + " Render Time: " + render_time);
         process_time = 0;
      }
   }


A few seconds of running...

FPS: 1, Process Time: 7992 Render Time: 138639760
FPS: 57, Process Time: 161622 Render Time: 9624389
FPS: 60, Process Time: 104913 Render Time: 11918064
FPS: 61, Process Time: 103605 Render Time: 8334624
FPS: 60, Process Time: 101535 Render Time: 12660010
FPS: 61, Process Time: 107089 Render Time: 8015489
FPS: 42, Process Time: 142956 Render Time: 18470568
FPS: 62, Process Time: 129872 Render Time: 8149031
FPS: 60, Process Time: 93706 Render Time: 10992659
FPS: 60, Process Time: 93977 Render Time: 11397550
FPS: 60, Process Time: 89091 Render Time: 12375007
FPS: 60, Process Time: 88103 Render Time: 12378847
FPS: 61, Process Time: 90599 Render Time: 10045067
FPS: 60, Process Time: 105866 Render Time: 11264862
FPS: 61, Process Time: 79250 Render Time: 11252489
FPS: 59, Process Time: 96743 Render Time: 16203345
FPS: 61, Process Time: 104095 Render Time: 13690799
FPS: 61, Process Time: 107302 Render Time: 10396627
FPS: 60, Process Time: 95676 Render Time: 12034540
FPS: 61, Process Time: 95185 Render Time: 12393353
FPS: 61, Process Time: 88039 Render Time: 12382261
FPS: 61, Process Time: 86411 Render Time: 12071659
FPS: 60, Process Time: 91651 Render Time: 13107567
FPS: 61, Process Time: 96309 Render Time: 10673097
Offline StumpyStrust
« Reply #1 - Posted 2012-04-28 23:05:40 »

Are you using a canvas or JPanel?

I see very little stuttering and what little I do see is a slight slowness on refreshing when moving vertically.

I have the same issue when I use a JPanel for rendering instead of a canvas but it does not always happen. I think I might have something to do with monitor refresh rate.

That is just a guess though.

Offline joeyismusic

Junior Devvie





« Reply #2 - Posted 2012-04-28 23:11:27 »

Using canvas. Its really driving me crazy, considering both the update rate and render rate are well within the target rates.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Riven
« League of Dukes »

« JGO Overlord »


Medals: 847
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #3 - Posted 2012-04-28 23:15:48 »

Smooth as butter for me.

Why don't you tell us about your OS, JRE, browser, etc? Smiley

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

Junior Devvie





« Reply #4 - Posted 2012-04-28 23:17:50 »

Windows 7 Pro, , Google Chrome

I just tried adding this
1  
Toolkit.getDefaultToolkit().sync();

and it made it much better O_o

EDIT: spoke too soon! so scratch that, still the same
Offline StumpyStrust
« Reply #5 - Posted 2012-04-28 23:42:04 »

I looked at the stuttering I get which looks identical to yours and tried that line and it still stutters slightly.

I think this has to do with the display because my apps do not stutter on my laptop.

Laptop is win 7 with java6

Desktop is XP java6

Offline Cero
« Reply #6 - Posted 2012-04-29 00:55:40 »

yeah it stutters sometimes

but honestly, I have tried every single gameloop in our big gameloop thread, and none is perfect

Offline ra4king

JGO Kernel


Medals: 356
Projects: 3
Exp: 5 years


I'm the King!


« Reply #7 - Posted 2012-04-29 02:48:24 »

Try out this game loop! (And don't forget the sleep trick)

Offline ReBirth
« Reply #8 - Posted 2012-04-29 03:33:25 »

Love your smoke effect. Run smoothly 33fps here, 7 java 7u1 and java 6u24 <-- lazy to update.

Offline joeyismusic

Junior Devvie





« Reply #9 - Posted 2012-04-29 03:52:01 »

reserved. (how do delete posts)
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline joeyismusic

Junior Devvie





« Reply #10 - Posted 2012-04-29 04:13:52 »

Thanks! I really owe it to my artist. :'D
Offline ra4king

JGO Kernel


Medals: 356
Projects: 3
Exp: 5 years


I'm the King!


« Reply #11 - Posted 2012-04-29 04:24:19 »

@ReBirth, you should update, from 24-31 there were significant security holes found with fixes applied. Your system is very vulnerable, no matter if you use Java or not.

Offline theagentd

« JGO Bitwise Duke »


Medals: 366
Projects: 2
Exp: 8 years



« Reply #12 - Posted 2012-04-29 11:57:54 »

VSync.

Myomyomyo.
Offline joeyismusic

Junior Devvie





« Reply #13 - Posted 2012-04-29 19:15:53 »

For anyone curious, this is what ended up working O_o

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  
   private void gameLoop5() {

      if (System.getProperty("os.name").startsWith("Win")) {
         new Thread()
         {

            {
               setDaemon(true);
               start();
            }

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

      long lastTime = 0;
      long nanosInSecond = 1000L * 1000L * 1000L;
      long updateFrequency = 60;
      long updateInterval = nanosInSecond / updateFrequency;
      long nextUpdateTick = System.nanoTime();
      long now = 0;
      long start = 0;
     
      long FPS = 60;

      while (running) {
         long deltaTime = System.nanoTime() - lastTime;
         lastTime += deltaTime;
         start = System.nanoTime();
         for (now = System.nanoTime(); now > nextUpdateTick; nextUpdateTick += updateInterval) {
            this.update();
         }
         process_time += System.nanoTime() - start;
         
         render();
         Toolkit.getDefaultToolkit().sync();
         
         long sleepTime = Math.round((1000000000 / FPS - (System.nanoTime() - lastTime)) / 1000000);
         if (sleepTime < 0) continue;
         
         // this sleeping method uses Thread.sleep(1) for the first 4/5 of
         // the sleep loop, and Thread.yield() for the rest. This gives me an
         // accuracy of about 3-4 microseconds
         long prev = System.nanoTime(), diff;
         while ((diff = System.nanoTime() - prev) < sleepTime) {
            if (diff < sleepTime * 0.8)
               try {
                  Thread.sleep(1);
               }
               catch (Exception exc) {
               }
            else
               Thread.yield();
         }
      }
   }
Offline ra4king

JGO Kernel


Medals: 356
Projects: 3
Exp: 5 years


I'm the King!


« Reply #14 - Posted 2012-04-29 19:22:42 »

At line 46, use "Math.round((1e9/FPS - (System.nanoTime() - lastTime)) / 1e6)", 1e9 and 1e6 are doubles, making the calculation more accurate.

Offline joeyismusic

Junior Devvie





« Reply #15 - Posted 2012-04-29 19:25:19 »

At line 46, use "Math.round((1e9/FPS - (System.nanoTime() - lastTime)) / 1e6)", 1e9 and 1e6 are doubles, making the calculation more accurate.

thanks. btw why does it render over 60 fps tho???
Offline jonjava
« Reply #16 - Posted 2012-04-29 19:25:28 »

The good ol' Matt Daemon;

Should be added to Spronglies FAQ imo.

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.

Mr.CodeIt (22 views)
2014-12-23 03:34:11

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

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

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

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

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

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

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

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

toopeicgaming1999 (151 views)
2014-11-26 15:20:36
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!