Java-Gaming.org    
Featured games (79)
games approved by the League of Dukes
Games in Showcase (475)
Games in Android Showcase (106)
games submitted by our members
Games in WIP (530)
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  
  Problem using System.nanoTime in kev's invader tut  (Read 2287 times)
0 Members and 1 Guest are viewing this topic.
Offline DarkMortar

Junior Member




Java Padawan


« Posted 2006-10-29 09:13:51 »

Hi, I am trying to impliment the nanoTimer in java5, instead of using the GAGE timer. But i know this is pretty noob my issues, but for some reason, i know this is wrong, but i need help on trying to make the nano time work in the game loop. when i try to run this it says press any key, i press it, and the game is already over because its too fast, i tried another way, and the game just shows grey with a null pointer exception. so there is a thread problem, and is it bad to use a thread for game loops, because i was taught that originally, to use it.
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  
   public void gameLoop() {
      long lastLoopTime = System.nanoTime();
     
      // keep looping round til the game ends
     while (gameRunning) {
         // work out how long its been since the last update, this
        // will be used to calculate how far the entities should
        // move this loop
        long delta = System.nanoTime() - lastLoopTime;
         lastLoopTime = System.nanoTime();

         // update the frame counter
        lastFpsTime += delta;
         fps++;
         
         // update our FPS counter if a second has passed since
        // we last recorded
        if (lastFpsTime >= 1000) {
            container.setTitle(windowTitle+" (FPS: "+fps+")");
            lastFpsTime = 0;
            fps = 0;
         }
         
         // Get hold of a graphics context for the accelerated
        // surface and blank it out
        Graphics2D g = (Graphics2D) strategy.getDrawGraphics();
         g.setColor(Color.black);
         g.fillRect(0,0,800,600);
         
         // cycle round asking each entity to move itself
        if (!waitingForKeyPress) {
            for (int i=0;i<entities.size();i++) {
               Entity entity = (Entity) entities.get(i);
               
               entity.move(delta);
            }
         }
         
         // cycle round drawing all the entities we have in the game
        for (int i=0;i<entities.size();i++) {
            Entity entity = (Entity) entities.get(i);
           
            entity.draw(g);
         }
         
         // brute force collisions, compare every entity against
        // every other entity. If any of them collide notify
        // both entities that the collision has occured
        for (int p=0;p<entities.size();p++) {
            for (int s=p+1;s<entities.size();s++) {
               Entity me = (Entity) entities.get(p);
               Entity him = (Entity) entities.get(s);
               
               if (me.collidesWith(him)) {
                  me.collidedWith(him);
                  him.collidedWith(me);
               }
            }
         }
         
         // remove any entity that has been marked for clear up
        entities.removeAll(removeList);
         removeList.clear();

         // if a game event has indicated that game logic should
        // be resolved, cycle round every entity requesting that
        // their personal logic should be considered.
        if (logicRequiredThisLoop) {
            for (int i=0;i<entities.size();i++) {
               Entity entity = (Entity) entities.get(i);
               entity.doLogic();
            }
           
            logicRequiredThisLoop = false;
         }
         
         // if we're waiting for an "any key" press then draw the
        // current message
        if (waitingForKeyPress) {
            g.setColor(Color.white);
            g.drawString(message,(800-g.getFontMetrics().stringWidth(message))/2,250);
            g.drawString("Press any key",(800-g.getFontMetrics().stringWidth("Press any key"))/2,300);
         }
         
         // finally, we've completed drawing so clear up the graphics
        // and flip the buffer over
        g.dispose();
         strategy.show();
         
         // resolve the movement of the ship. First assume the ship
        // isn't moving. If either cursor key is pressed then
        // update the movement appropraitely
        ship.setHorizontalMovement(0);
         
         if ((leftPressed) && (!rightPressed)) {
            ship.setHorizontalMovement(-moveSpeed);
         } else if ((rightPressed) && (!leftPressed)) {
            ship.setHorizontalMovement(moveSpeed);
         }
         
         // if we're pressing fire, attempt to fire
        if (firePressed) {
            tryToFire();
         }
         
         // we want each frame to take 10 milliseconds, to do this
        // we've recorded when we started the frame. We add 10 milliseconds
        // to this and then factor in the current time to give
        // us our final value to wait for
        try { Thread.sleep(lastLoopTime+10-System.nanoTime()); } catch (Exception e) {}
      }
   }

Offline Kova

Senior Member





« Reply #1 - Posted 2006-10-29 09:50:27 »

Hi, I am trying to impliment the nanoTimer in java5, instead of using the GAGE timer. But i know this is pretty noob my issues, but for some reason, i know this is wrong, but i need help on trying to make the nano time work in the game loop.
ask yourself what is the difference between 2 timers...


1  
2  
3  
4  
5  
6  
7  
         // we want each frame to take 10 milliseconds, to do this
        // we've recorded when we started the frame. We add 10 milliseconds
        // to this and then factor in the current time to give
        // us our final value to wait for
        try { Thread.sleep(lastLoopTime+10-System.nanoTime()); } catch (Exception e) {}
      }
   }


I don't know about the rest but this is clearly wrong. In comments it says that you want to sleep 10ms, but you are using nano timer and you add 10 ns in sleep() so sleep time here probably goes negative. Convert 10ms to ns, it's * 1 000 000. Scale goes mili - micro - nano. So * 1000 gives micro and another * 1000 gives mili.
Offline Matzon

JGO Knight


Medals: 19
Projects: 1


I'm gonna wring your pants!


« Reply #2 - Posted 2006-10-29 10:20:58 »

that said, nanotime is broken on windows because it uses QPC (QueryPerformanceCounter)

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

Senior Member





« Reply #3 - Posted 2006-10-29 10:23:49 »

huh? could you explain a little bit or give a link to an article? I've heard about time calculating wrong on 2 core cpus since one core returns the time while other one is working with that code and time may become negative, is this it?
Offline Matzon

JGO Knight


Medals: 19
Projects: 1


I'm gonna wring your pants!


« Reply #4 - Posted 2006-10-29 16:44:39 »

no the problem with QPC is that the timer varies according to its speed, which causes all sorts of mayhem on computers with speedstep and other similar power saving:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/Game_Timing_and_Multicore_Processors.asp
Quote
The QueryPerformanceFrequency API will not change frequency while the system is running so this only needs to be called once.

http://support.microsoft.com/default.aspx?sd=msdn&scid=kb;en-us;274323


Offline DarkMortar

Junior Member




Java Padawan


« Reply #5 - Posted 2006-10-30 01:35:16 »

hmm, still problems, i think its really messed up since its all nano, and the delta movements are probably wrong because of the new timing. Sad

Offline Kova

Senior Member





« Reply #6 - Posted 2006-10-30 16:14:01 »

heh, so fix them... you just need to alter algoritham to use different scale, that is trivial to do
Offline DarkMortar

Junior Member




Java Padawan


« Reply #7 - Posted 2006-10-31 06:08:59 »

i did, but there is like a good chance there is a nullpointer problem(an error i usually get if theres a thread problem) even after the tweak, and when it works its still too fast, or the aliens move out of proportion.

Online kevglass

JGO Kernel


Medals: 117
Projects: 23
Exp: 18 years


Coder, Trainee Pixel Artist, Game Reviewer


« Reply #8 - Posted 2006-10-31 06:37:43 »

Might be worth dumping your code somewhere we can see it - hopefully someone can help then.

Kev

Offline DarkMortar

Junior Member




Java Padawan


« Reply #9 - Posted 2006-11-01 01:48:28 »

click free, then type in the code and u can dl it, for eclipse.


http://rapidshare.com/files/1491291/DarkMortar_s_Space_Invaders.rar.html

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

Senior Member





« Reply #10 - Posted 2006-11-01 01:55:54 »

I don't have time now for checking your code, but first you could eliminate everything else except sleep timing, in Thread.sleep() put some constant and see if your game runs good then, like put Thread.sleep(20) for 50fps. If it works fine then go through all sleep code and understand it, if you understand it you wouldn't have this problem.
Offline DarkMortar

Junior Member




Java Padawan


« Reply #11 - Posted 2006-11-01 05:54:47 »

I did try it with a constant before, like my other progs and with this, and it does work, yet the movement is fast, because im using nanosecond, yes its trivial, but apparently im not bright, so.

try { Thread.sleep(10); } catch (Exception e) {}  //100 fps cap

ive done sleep timers before, but i never have made objects move based on modifyed nanoseconds nor milliseconds either based on the current fps.

Online kevglass

JGO Kernel


Medals: 117
Projects: 23
Exp: 18 years


Coder, Trainee Pixel Artist, Game Reviewer


« Reply #12 - Posted 2006-11-01 15:48:59 »

Looks this this bit is the problem:

Quote
public void gameLoop() {
      long lastLoopTime = System.nanoTime();
      
      // keep looping round til the game ends
      while (gameRunning) {
         // work out how long its been since the last update, this
         // will be used to calculate how far the entities should
         // move this loop
         long delta = System.nanoTime() - lastLoopTime;

The delta value in the original version is in milliseconds - so if a second had passed between game loops the value would be 1000. This is then used to work out how far to move the aliens/ship/fpscounter. However, since you've changed it to nanoTime() you'll get 1000000000 in a second I think. So you need to scale this delta value down to milliseconds or adapt every usage of the delta value. I'd go for the first one - divide delta by 1000000 (1 x 10^6)  to fix the value.

Only had a couple of minutes to look but it looks like the most likely issue.

Kev

Offline DarkMortar

Junior Member




Java Padawan


« Reply #13 - Posted 2006-11-02 03:33:49 »

Ok I changed this in the gameloop()

1  
2  
3  
4  
5  
if (lastFpsTime >= 1000000000) {
            container.setTitle(windowTitle+" (FPS: "+fps+")");
            lastFpsTime = 0;
            fps = 0;
         }


and...

1  
try { Thread.sleep(lastLoopTime+100000-System.nanoTime()); } catch (Exception e) {}


and with the entity class i changed the delta movements like this...
1  
2  
x += (delta * dx) / 1000000000;
      y += (delta * dy) / 1000000000;


Well ok, they seem to move at a fair speed, and they animate. But the problem is with the fps counter I think, it starts with saying im getting like 500fps, then it slowly raises to like 1.5k fps, lol. So somethings wrong there. And there is a chance that after i executed the program once theres a null pointer problem with the thread, but every other time after compilization it works again.

Offline Kova

Senior Member





« Reply #14 - Posted 2006-11-02 13:49:03 »

Ok I changed this in the gameloop()

1  
2  
3  
4  
5  
if (lastFpsTime >= 1000000000) {
            container.setTitle(windowTitle+" (FPS: "+fps+")");
            lastFpsTime = 0;
            fps = 0;
         }


this is ok... you increase fps variable each time you render a loop and after a second has passed you have the resaults and reset everything. Show us the part where you increase fps. btw. I don't personally like this way of counting fps since you have resaults every second, I like the one that can calculate fps after each pass through game loop.

and...

1  
try { Thread.sleep(lastLoopTime+100000-System.nanoTime()); } catch (Exception e) {}


why +100000 (0.1ms)? I see in your movement that you are dividing with 1 second, why?
I think this should be +10000000 in sleep() and / 10000000 in x and y.

It is clear that you don't understand this, so I'll try to explain it. First don't just copy the code from tutorials, try to learn from it. Every line of code you write you need to know why are you writing that line. For example, the sleep method. Comment pretty much says it all. You want your game to run at 100 updates a second, so you want to sleep for 10ms. You then remember that your game loop takes some time, like if it is 4ms then you should sleep 6ms. So you try to calculate this. At start of your game loop you record time with nanoTime(). Lets say it is 1000000000. At the end of your game loop you record time again to see how much your game loop was running. It returns 1002000000. So your game loop ran for 2ms and you know you need to sleep for 8ms. That formula you have in sleep could be written like this also, maybe you'll understand this one better:

1  
2  
3  
4  
5  
6  
7  
startTime = System.nanoTime();
...
...game loop
...
afterTime = System.nanoTime();
loopTime = (afterTime - startTime) / 1000000;  // in ns, / 1000000 is to convert to ms
Thread.sleep(10 - loopTime);


let's calculate for example I made up above:
startTime =  1000000000
afterTime =  1002000000
loopTime = (1002000000 - 1000000000) / 1000000 = 2000000 / 1000000 = 2
sleep = (10 - 2) = 8


And there is a chance that after i executed the program once theres a null pointer problem with the thread, but every other time after compilization it works again.
a chance for you to get null pointer is probably one thread using some reference that needs to be initialized by another thread and sometimes first thread goes ahead of second one and tries to use it before second one initialized it. Initialize references before you start other threads that might use them.
Offline DarkMortar

Junior Member




Java Padawan


« Reply #15 - Posted 2006-11-03 02:46:04 »

Well, ok its gotten a little better. My program seems to display the real fps. It says like 65fps, but it sounds right because usually my programs are capped at 65fps in Eclipse IDE for some reason, but if i run it in jBuilder it goes to 95-100 fps like it should.

But the problem is with my entity movements, in order for the movement to be normal, it have to divide it by one second for some reason or its too fast. And my question about System.nanoTime(), is it that all it does is give you the CURRENT time from the system clock in nanoSeconds of when it was used. So it all makes sense now in that way. But my entity movements are whack. And also im not sure if my placment of afterTime and startTime is entirely correct.
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  
public void gameLoop() {
      long startTime = System.nanoTime();
     
      // keep looping round til the game ends
     while (gameRunning) {
         // work out how long its been since the last update, this
        // will be used to calculate how far the entities should
        // move this loop
        long delta = System.nanoTime() - startTime;
         startTime = System.nanoTime();

         // update the frame counter
        lastFpsTime += delta;
         fps++;
         
         // update our FPS counter if a second has passed since
        // we last recorded
        if (lastFpsTime >= 1000000000) {
            container.setTitle(windowTitle+" (FPS: "+fps+")");
            lastFpsTime = 0;
            fps = 0;
         }
         
         // Get hold of a graphics context for the accelerated
        // surface and blank it out
        Graphics2D g = (Graphics2D) strategy.getDrawGraphics();
         g.setColor(Color.black);
         g.fillRect(0,0,800,600);
         
         // cycle round asking each entity to move itself
        if (!waitingForKeyPress) {
            for (int i=0;i<entities.size();i++) {
               Entity entity = (Entity) entities.get(i);
               
               entity.move(delta);
            }
         }
         
         // cycle round drawing all the entities we have in the game
        for (int i=0;i<entities.size();i++) {
            Entity entity = (Entity) entities.get(i);
           
            entity.draw(g);
         }
         
         // brute force collisions, compare every entity against
        // every other entity. If any of them collide notify
        // both entities that the collision has occured
        for (int p=0;p<entities.size();p++) {
            for (int s=p+1;s<entities.size();s++) {
               Entity me = (Entity) entities.get(p);
               Entity him = (Entity) entities.get(s);
               
               if (me.collidesWith(him)) {
                  me.collidedWith(him);
                  him.collidedWith(me);
               }
            }
         }
         
         // remove any entity that has been marked for clear up
        entities.removeAll(removeList);
         removeList.clear();

         // if a game event has indicated that game logic should
        // be resolved, cycle round every entity requesting that
        // their personal logic should be considered.
        if (logicRequiredThisLoop) {
            for (int i=0;i<entities.size();i++) {
               Entity entity = (Entity) entities.get(i);
               entity.doLogic();
            }
           
            logicRequiredThisLoop = false;
         }
         
         // if we're waiting for an "any key" press then draw the
        // current message
        if (waitingForKeyPress) {
            g.setColor(Color.white);
            g.drawString(message,(800-g.getFontMetrics().stringWidth(message))/2,250);
            g.drawString("Press any key",(800-g.getFontMetrics().stringWidth("Press any key"))/2,300);
         }
         
         // finally, we've completed drawing so clear up the graphics
        // and flip the buffer over
        g.dispose();
         strategy.show();
         
         // resolve the movement of the ship. First assume the ship
        // isn't moving. If either cursor key is pressed then
        // update the movement appropraitely
        ship.setHorizontalMovement(0);
         
         if ((leftPressed) && (!rightPressed)) {
            ship.setHorizontalMovement(-moveSpeed);
         } else if ((rightPressed) && (!leftPressed)) {
            ship.setHorizontalMovement(moveSpeed);
         }
         
         // if we're pressing fire, attempt to fire
        if (firePressed) {
            tryToFire();
         }
         
         long afterTime = System.nanoTime();
         
         loopTime = (afterTime - startTime) / 1000000;  // in ns, / 1000000 is to convert to ms
       
         // we want each frame to take 10 milliseconds, to do this
        // we've recorded when we started the frame. We add 10 milliseconds
        // to this and then factor in the current time to give
        // us our final value to wait for
        try { Thread.sleep(10 - loopTime); } catch (Exception e) {}
      }
   }


Problem with entity movements:
1  
2  
3  
4  
5  
public void move(long delta) {
      // update the location of the entity based on move speeds
     x += (delta * dx) / 1000000000;
      y += (delta * dy) / 1000000000;
   }


EDIT: Why is it that with Eclipse IDE, I sometimes get the proper fps. Like i just tryed it right now and it runs at 93 fps. And the movement seems to not move faster than it did at 60 fps, and i tryed it again with even a lower sleep than 10ms, and they move at the same rate, so it seems that the movement alogorithim is working. I also tryed it again with a 60ms delay in sleep, and the game runs at 23 fps and the movement is the same still, and the slow down looks like how 20 fps would look in a game, where its "kinda laggy" so this is a good sign that it works in that sense.

Offline Kova

Senior Member





« Reply #16 - Posted 2006-11-03 19:07:00 »

Well, ok its gotten a little better. My program seems to display the real fps. It says like 65fps, but it sounds right because usually my programs are capped at 65fps in Eclipse IDE for some reason, but if i run it in jBuilder it goes to 95-100 fps like it should.

Never heard of eclipse doing that... or can think how it could happen.

But the problem is with my entity movements, in order for the movement to be normal, it have to divide it by one second for some reason or its too fast. And my question about System.nanoTime(), is it that all it does is give you the CURRENT time from the system clock in nanoSeconds of when it was used. So it all makes sense now in that way. But my entity movements are whack. And also im not sure if my placment of afterTime and startTime is entirely correct.

your afterTime and startTime are good.
No, System.nanoTime() dosen't have anything to do with current system time, as in "date and time". System.nanoTime() returns nanosecond value of some timer which has a random start value. All you can do with nanoTime() is compare to another nanoTime() value to see how much nano seconds has passed between 2 calls, nothing more.

Problem with entity movements:
1  
2  
3  
4  
5  
public void move(long delta) {
      // update the location of the entity based on move speeds
     x += (delta * dx) / 1000000000;
      y += (delta * dy) / 1000000000;
}


from main game loop I see that delta is nano time passed since 2 game updates, so that is loopTime + sleepTime, so that is ~10ms (= 10 000 000ns). Dx and dy are probably speeds that entety moves, in pixels per second. That is why you need to divide by one second.

Let's say 10th of second had passed and if you move 100pix/s (dx = 100) then entety should move 10pixels. 10th of a second is 100ms, which is 100 000 000ns. Formula says:
x += (100 000 000 * 100) / 1000 000 000 = 10 000 000 000 / 1000 000 000 = 10
So as  you see it's all about understanding what are variables storing and what they are for. If you anything of this is unclear to you ask again and say what part.

I'll try to assume some of things that confused you:
dx and dy are speed, why are they named dx and dy? I think it comes from physics as difference over x and difference over y.
why am I dividing by 1s? It's becouse your speed in dx and dy are measured in pixels per second, so if you know how much time has passed since last update (delta) you can calculate how much entety should move to compasate for that time (when you were sleeping, becouse in theory when you are traveling with some speed you never stop moving and since your program sleeps then it should move entety where it should be by calculating where it would end up if it didn't stop moving... this may be unclear to you right away, but if you understand those formulas then you should understand this)

EDIT: so I guess your game loop, movement and fps counter are good now, that is all you had problem with I guess, good luck with learning
Offline DarkMortar

Junior Member




Java Padawan


« Reply #17 - Posted 2006-11-04 02:20:26 »

Ok, cool. The reason I asked about the division of the movements by one second, was becase before you told me to divide it by a lower number, unless you though i was trying to do something else. Because through testing, dividing by one second was the only was it worked, but i just wanted to make sure that my after time and start time were not wrong to see if my movement divisons were wrong. I do know why we are dividing by higher number, because of the nano second scale of course.

I also just synced the animation frames for the nanosecond time, because before they were animating too fast, so its fixed now there too. The reason those dx and dy variables were named that, was well, that was what it is called straight from the tutorial. So ya the movements are synched, the fps seems to tell the truth, and the threads work. Life is all good now  Grin

Thank you sir.

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.

ctomni231 (33 views)
2014-07-18 06:55:21

Zero Volt (29 views)
2014-07-17 23:47:54

danieldean (24 views)
2014-07-17 23:41:23

MustardPeter (26 views)
2014-07-16 23:30:00

Cero (41 views)
2014-07-16 00:42:17

Riven (43 views)
2014-07-14 18:02:53

OpenGLShaders (31 views)
2014-07-14 16:23:47

Riven (30 views)
2014-07-14 11:51:35

quew8 (29 views)
2014-07-13 13:57:52

SHC (64 views)
2014-07-12 17:50:04
HotSpot Options
by dleskov
2014-07-08 03:59:08

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:58:24

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:47:22

How do I start Java Game Development?
by ra4king
2014-05-17 11:13:37

HotSpot Options
by Roquen
2014-05-15 09:59:54

HotSpot Options
by Roquen
2014-05-06 15:03:10

Escape Analysis
by Roquen
2014-04-29 22:16:43

Experimental Toys
by Roquen
2014-04-28 13:24:22
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!