Java-Gaming.org    
Featured games (81)
games approved by the League of Dukes
Games in Showcase (480)
Games in Android Showcase (110)
games submitted by our members
Games in WIP (547)
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  
  [SOLVED] Skip frames  (Read 803 times)
0 Members and 1 Guest are viewing this topic.
Offline Yemto

Junior Member


Exp: 3 years



« Posted 2013-08-16 12:07:16 »

I have trouble with my game loop. The one I have can cause objects to get stuck or teleport through other objects. I know it's caused when the FPS is low and the game tries to put the objects where they are suppose to be. But it ignore hit detection. My idea is to make the game not render all the frames when it runs slow, to try to get more time for the logic. But I'm not sure how to do that.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
@Override
    public void run(){
        while(true){
            double delta = (System.nanoTime() - lastUpdate) / 1000000000.0;
            lastUpdate = System.nanoTime();
           
            world.update(delta);
            screen.repaint();
           
            if(!maximumFps){
                //100000 convert nanosecound into milisecound. It's what 1 milisecound is in nanosecounds
               try{ Thread.sleep((lastUpdate-System.nanoTime() + optimalTime) / 1000000); }catch(Exception e){}
            }else{
                try{ Thread.sleep(1); }catch(Exception e){}
            }
        }
    }
Offline sirkarpfen

Junior Member


Medals: 2
Exp: 2 years



« Reply #1 - Posted 2013-08-16 12:17:49 »

What exactly are you doing inside world.update() (i think thats your global "gamelogic update" method)? Also are you using any libraries or pure java2d? A bit of code of screen.repaint() and world.update() would be very helpfull.

Also this:

1  
try{ Thread.sleep(1); }catch(Exception e){}


won't cause any noticable change to the current behavior, as you set the thread to sleep for just 1 millisecond.
Offline Herjan
« Reply #2 - Posted 2013-08-16 12:23:52 »

I thought ur loop was really weird...

I like to program loops like this:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
public void run(){
   long start, end, time, sleeptime;
   while(true){
      try{
         start = System.currentTimeMillis();
         
         tick();
         render();
               
         end = System.currentTimeMillis();
         time = end - start;
         sleeptime = 1000/60 - time;
         if( sleeptime < 0 ) sleeptime = 0;
         Thread.sleep(sleeptime);
      }catch(Exception e){}
   }
}


Oh, and about skipping frames, never do actions based on frames, but on time...

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

Junior Member


Medals: 2
Exp: 2 years



« Reply #3 - Posted 2013-08-16 12:33:05 »

I thought ur loop was really weird...

The loop wasn't that bad, and doesn't cause framelags. And where does he do actions based on frames? He updates the game using the delta time (as everybody should do) Smiley.

An advice to both of you:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
/* Works but isn't very nice nor very capable of 
 * beeing used in a "serious" game because it will just loop infinitely. */

while(true) {
...
}

/* This one is quite better, because you can control the condition better.
 * If you choose to quit your game and maybe move back to a menuscreen
 * you could stop with running = false: */

while(running) {
...
}
Offline Yemto

Junior Member


Exp: 3 years



« Reply #4 - Posted 2013-08-16 12:44:28 »

Okay, I going to fix the while(true) issue later. The problem I have is that, at low fps the objects will jump through other objects, since I'm currently using...

1  
2  
3  
4  
5  
@Override
    public void update(double delta){
        addX(25.0 * delta);
        addY(25.0 * delta);
    }


...to move objects. what I need to do is let the game logic catch up with the frames. That way I was thinking of doing that is to not skip frames. So the game logic still act like it's running in 60 fps, when the player only see 30
Offline sirkarpfen

Junior Member


Medals: 2
Exp: 2 years



« Reply #5 - Posted 2013-08-16 12:55:48 »

So lets say your delta time is about 0.01 seconds. It means you're moving your object about 0.25 pixels every frame and that means (with a framerate of about 60 fps) you move your objects 15 pixels every second. If you check for collisions every frame, there should be no problem at all.

You're gamelogic happens every frame, so you cannot "limit" it to the frames. That means every time something is drawn, the gamelogic is calculated before. Also you're logic doesn't "skip" frames, as your frames don't skip frames. if you halt your gameLoop because of fps limitation (thread.sleep()), no logic will be done, but also no rendering will be done.

Another case would be, if you would use a seperate thread for your gamelogic. But i don't think thats the case here.
Offline Yemto

Junior Member


Exp: 3 years



« Reply #6 - Posted 2013-08-16 13:05:36 »

So lets say your delta time is about 0.01 seconds. It means you're moving your object about 0.25 pixels every frame and that means (with a framerate of about 60 fps) you move your objects 15 pixels every second. If you check for collisions every frame, there should be no problem at all.

You're gamelogic happens every frame, so you cannot "limit" it to the frames. That means every time something is drawn, the gamelogic is calculated before. Also you're logic doesn't "skip" frames, as your frames don't skip frames. if you halt your gameLoop because of fps limitation (thread.sleep()), no logic will be done, but also no rendering will be done.

Another case would be, if you would use a seperate thread for your gamelogic. But i don't think thats the case here.

You don't understand the issue. if the framerate becomes to low, the detla time can go up to 0.99 which can cause the object to jump through other objects, because it will be teleported 24 px.

Anyway, I know my code don't skips frames. That is what I'm trying to implement. Let say I have two threads. one for game logic, and one for the frames. Wouldn't that cause issues/instability?
Offline opiop65

JGO Kernel


Medals: 154
Projects: 7
Exp: 3 years


JumpButton Studios


« Reply #7 - Posted 2013-08-16 13:18:32 »

No, don't do this. Having two threads is a terrible idea. This forum has a whole board dedicated to things like loops. Just search for game loop and implement one of them.

Offline Yemto

Junior Member


Exp: 3 years



« Reply #8 - Posted 2013-08-16 13:26:16 »

No, don't do this. Having two threads is a terrible idea. This forum has a whole board dedicated to things like loops. Just search for game loop and implement one of them.

That's what I thought, and guess how I  got hold of this one I have, I was thinking of having some if statement to skill screen.repaint(); to skip frames. But I'm not exactly sure how to do it.
Offline SHC
« Reply #9 - Posted 2013-08-16 13:28:24 »

If the framerate becomes to low, the detla time can go up to 0.99 which can cause the object to jump through other objects, because it will be teleported 24 px.

That's a known problem with variable timestep game loops. A solution is to make frames of constant length by using fixed timestep game loop. Now, let's make a game loop that keeps the game logic at the same rate and renders a frame if the maximum fps is not reached.

Let's start by making some variables for the game loop.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
long now = getCurrentTime();
long gameTime = getCurrentTime();

// Updates per second
long ups = 60;
// The time to update the logic once.
long timeForLogic = 1000 / 60;

// For frame skipping
int framesSkipped= 0;
int maxFrameSkip = 5;  // Skip a maximum of 5 frames before rendering

// For fps count
int fps = 0;
int frames = 0;
long lastFpsCount = getCurrentTime();

Here,
getCurrentTime()
is just a method that returns the current time in milliseconds. Now, let's write the inner game loop. For better results, we separate rendering and logic.

First, we need to only update the logic only when it is required. Did you notice that
gameTime
variable? It's is what we use to check when the update is required.

So if the condition
now + timeForLogic > gameTime
is met, we need to update. Ok, but wee also need to check for frame limiting. So change the condition to
(now + timeForLogic > gameTime) && (framesSkipped < maxFrameSkips)
to make sure we render a frame in between. So now the code for the game loop will be

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  
while (running)
{
    framesSkipped = 0;
    now = getCurrentTime();

    // Update only when required
   while ((now + timeForLogic > gameTime) && (framesSkipped < maxFrameSkips))
    {
        world.update();

        gameTime += timeForLogic;
        framesSkipped++;
    }

    // Render to screen
   screen.repaint();
   
    // calculate fps
   frames++;

    if (now - lastFpsCount >= 1000)
    {
        fps = frames;
        frames = 0;
    }
}

And now, this limits the updates you have to do in a second, but rendering how many frames it can. Be careful that it uses the total cpu. To limit that, just sleep by 1 ms at the end of fps count.

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Herjan
« Reply #10 - Posted 2013-08-16 13:33:37 »

The loop wasn't that bad, and doesn't cause framelags. And where does he do actions based on frames? He updates the game using the delta time (as everybody should do) Smiley.

The title is: "Skip frames" and:
Quote
My idea is to make the game not render all the frames when it runs slow, to try to get more time for the logic.

This doesnt look like using time

Offline opiop65

JGO Kernel


Medals: 154
Projects: 7
Exp: 3 years


JumpButton Studios


« Reply #11 - Posted 2013-08-16 14:08:00 »

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  
long lastTime = System.nanoTime();
          double nsPerTick = 1000000000D / 60D; //~60fps
     
      int ups = 0;
      int fps = 0;
     
      long lastTimer = System.currentTimeMillis();
      double delta = 0;
     
      while(game loop not quit blub) {
         long now = System.nanoTime();
         delta += (now - lastTime) / nsPerTick;
         lastTime = now;
         boolean renderOK = false;
         while(delta >= 1) {
            ups++;
            update();
            delta -= 1;
            renderOK = true;
         }
         if(shouldRender) {
            fps++;
            render();
         }
         if(System.currentTimeMillis() - lastTimer >= 1000) {
            lastTimer += 1000;
            System.out.println("frames: " + fps + " | updates: " + ups);
            fps = 0;
            ups = 0;
         }
      }

Use this. Just found it on the forum, I also use game loops like this and they have never failed me. Smaller code doesn't always make for better code.

Offline GNecro1
« Reply #12 - Posted 2013-08-16 14:17:10 »

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  
//will get the fps
public int finalFrames = 0;

public void run() {
      long lastTime = System.nanoTime();
      final double amountOfTicks = 60.0;
      double ns = 1000000000 / amountOfTicks;
      double delta = 0;
      int ticks = 0;
      int frames = 0;
      long timer = System.currentTimeMillis();

      while (run) {
         long now = System.nanoTime();
         delta += (now - lastTime) / ns;
         lastTime = now;
         if (delta >= 1) {
            tick();
            ticks++;
            delta--;
         }
         draw();
         frames++;
         if (System.currentTimeMillis() - timer > 1000) {
            timer += 1000;
            finalFrames = frames;
            frames = 0;
            ticks = 0;
         }
      }
   }

Java freak! Cheesy
Offline Yemto

Junior Member


Exp: 3 years



« Reply #13 - Posted 2013-08-16 15:16:54 »

I ended up with

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  
@Override
    public void run(){
        long lastTime = System.nanoTime();
        double ticksPerSec = 120.0;
        double tickTime = 1000000000.0 / ticksPerSec;
       
        long time = System.currentTimeMillis();
        int ticks = 0;
       
        double delta = 0;
        while(running){
            long now = System.nanoTime();
            delta += (now - lastTime) / tickTime;
            lastTime = now;

            while(delta >= 1){
                world.update(0.01);
                delta -= 1; ticks++;
            }
           
            if(System.currentTimeMillis()-time >= 1000){
                time = System.currentTimeMillis();
                System.out.println("T:"+ticks);
                ticks = 0;
            }
           
            screen.repaint();            
            try{ Thread.sleep(2346); }catch(Exception e){}//<-- only for testing
       }
    }


the reason why i don't reset delta in the while(running) loop is to let delta build up to 1 or higher, in which the while(delta) loop subtract that. with help of the sleep function I tested to run the game in 2 fps, and with 700 fps. I timed it and in both cases the objects had traveled the same distance.
Offline SHC
« Reply #14 - Posted 2013-08-16 15:26:17 »

@Yemto

There are two things to say on your loop.

  • System.currentTimeMillis()
    is not reliable across platforms. It is known to be lagging by 16-56 ms on windows. Always use
    System.nanoTime()
  • And why are you sleeping for a large time?
    Thread.sleep(2346)

Glad that it's solved but those are my doubts and suggestions.

Offline opiop65

JGO Kernel


Medals: 154
Projects: 7
Exp: 3 years


JumpButton Studios


« Reply #15 - Posted 2013-08-16 15:35:50 »

Please for the love of god take out that sleep call. Don't be lazy, code it yourself. The sleep function may not work properly and can mess up your loop timing. If I'm correct.

Offline Yemto

Junior Member


Exp: 3 years



« Reply #16 - Posted 2013-08-16 16:22:04 »

@Yemto

There are two things to say on your loop.

  • System.currentTimeMillis()
    is not reliable across platforms. It is known to be lagging by 16-56 ms on windows. Always use
    System.nanoTime()
  • And why are you sleeping for a large time?
    Thread.sleep(2346)

Glad that it's solved but those are my doubts and suggestions.

Thanks, I didn't know that about currentTimeMillies, and Thread.sleep was only for testing the code when it can't run optimally.

Please for the love of god take out that sleep call. Don't be lazy, code it yourself. The sleep function may not work properly and can mess up your loop timing. If I'm correct.

for the love of god, read the comment in the code, and I needed help, someone provided me with a code that worked. I took a look at it and kept testing and changing it so it fitted with what I wanted.
Offline opiop65

JGO Kernel


Medals: 154
Projects: 7
Exp: 3 years


JumpButton Studios


« Reply #17 - Posted 2013-08-16 19:16:29 »

Ok, I'm sorry I completely missed the comment. I just saw a sleep call and immediately was a little angry... sorry again!

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.

atombrot (25 views)
2014-08-19 09:29:53

Tekkerue (24 views)
2014-08-16 06:45:27

Tekkerue (23 views)
2014-08-16 06:22:17

Tekkerue (13 views)
2014-08-16 06:20:21

Tekkerue (20 views)
2014-08-16 06:12:11

Rayexar (58 views)
2014-08-11 02:49:23

BurntPizza (38 views)
2014-08-09 21:09:32

BurntPizza (30 views)
2014-08-08 02:01:56

Norakomi (37 views)
2014-08-06 19:49:38

BurntPizza (67 views)
2014-08-03 02:57:17
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

List of Learning Resources
by SilverTiger
2014-07-31 11:54:12

HotSpot Options
by dleskov
2014-07-08 01:59:08
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!