Java-Gaming.org    
Featured games (81)
games approved by the League of Dukes
Games in Showcase (499)
Games in Android Showcase (118)
games submitted by our members
Games in WIP (568)
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  
  big performence drop after switching to time corrected movement  (Read 3653 times)
0 Members and 1 Guest are viewing this topic.
Offline No_Germs

Junior Member





« Posted 2005-09-08 08:32:32 »

up until now, my game (a side scroller) worked on fixed-time movement, meaning the amount of movement done every gameloop iteration was of fixed size.
this was achieved by creating a method Move() in my Entity class, from which all other game entities inherit:
class Entity
{
//...
   public void Move()
   {
       X+=XSpeed;
       Y+=YSpeed;
   }
}
class Main
{
     Entity[] Entities;
     public void Move()
     {
          for(int i=0;i<Entities.length;i++)
          {
               Entities.Move();
          }
     }
     public void Draw()
     {
          for(int i=0;i<Entities.length;i++)
          {
               Entities.Draw();
          }
     }
     public void run()
     {
          while(true)
          {
              Move();
              Draw();
              try
              {
                  Thread.sleep(1);
              }
              catch(Exception e)
              {
              }
          }
     }
     public static void Main(String[] args)
     {
          Thread t=new thread(this);
          t.start();
     }
}
(this is just a simplified version, the real move() method is a little more complicated)
now, i know this is isn't the correct method for doing this, because i move the Entities by a fixed amount regardless of how much time has passed. so i've started using time-corrected movement, that meant turning Entity.Move() to
   public void Move(float Time)
   {
       X+=XSpeed*Time;
       Y+=YSpeed*Time;
   }
and calling this method with the Time Difference from the last game loop iteration as an argument.
problem is, when i did this, my performence have dropped significally-
my game loop worked at 2 miliseconds (without rendering), and now it has dropped to 30 miliseconds...
three questions:
1. what do you think caused the drop? the another argument in the method call, or the extra calculations (they haven't gotten that complicated when i added the time factor)?.
2. maybe i'm doing something wrong and i shouldn't experience such a drop if i work correctly?
3. maybe it's worth reverting back to fixed time movement and trying to stabalize the game loop? after all, a 28 milisec difference is quite alot...
Thanks  in advance, and sorry for the extra long post,
noam Smiley
Offline c_lilian

Senior Member


Projects: 1


Java games will probably rock someday...


« Reply #1 - Posted 2005-09-08 08:44:38 »

Don't rely on System.currentTimeMillis() as it is not accurate (30 ms delay in some OSes, 2ms in others)

Use System.nanoTime() instead, or the Gage Timer, or any other accurate timer.

If you have to stick to currentTimeMillis(), add a "frame step" variable, calculated upon previous frames durations (e.g. sum up the last 100 frames and divide by 100) to your time if it hasn't changed till the last loop.

Lilian

Offline No_Germs

Junior Member





« Reply #2 - Posted 2005-09-08 08:56:42 »

i'm doing exactly that- summing up the time differences and dividing them by the number of frames passed... the time difference between the first method and the sceond is consistently about 28 milisec...
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline c_lilian

Senior Member


Projects: 1


Java games will probably rock someday...


« Reply #3 - Posted 2005-09-08 09:32:07 »

Which timer are you using ? (it's not visible from your sample code)

Could you post your full game loop ?

Lilian

Offline No_Germs

Junior Member





« Reply #4 - Posted 2005-09-08 09:42:35 »

not using a timer.
i'm using a while loop that at the end of i call Thread.sleep to prevent starvation... the actuall gameloop looks almost exactly as the one on the example from  the first message. the difference is in the Entity.Move(float Time) method. in the real case, it does a little more calculaion than what was shown there, as i have some movement methods that the Move(float Time) method calls, for example, i have a Fly(float Time) method that is called by flying objects. an amphibious creature's move(float time) method would look something like this:
class Amphibious extends Entity
{
     //Override of Entity.Move(float Time)
     public void Move(float Time)
     {
          if(UnderWater())
          {
               Swim(Time);
          }
          else
          {
               Walk(Time);
          }
     }
}
i hope i'm getiing through... Smiley
Offline c_lilian

Senior Member


Projects: 1


Java games will probably rock someday...


« Reply #5 - Posted 2005-09-08 09:52:12 »

Strange you have a loop that depends on a time factor and you don't use a timer to know how much time has passed... I must be missing something...

Are you using a Thread.sleep(n) where n!= 1 ?

Offline No_Germs

Junior Member





« Reply #6 - Posted 2005-09-08 10:26:17 »

Oh sorry, i misunderstood you. i thought you asked what Timer am i using as a thread, such as java.swing.Timer...
i meausre my time inside Move() in class Main, like so:
class Main
{
    long Current;
    long Last;
    public void Move()
    {
          Current=system.nanoTime();
          Long T=(float)(Current-Last)/10000000;//Convert to milisec
          Last=Current;
          for(int i=0;i<Entities.length;i++)
          {
               Entities.Move(T);
          }
    }
}
is this wrong for any reason?
Offline tom
« Reply #7 - Posted 2005-09-08 11:45:56 »

i'm using a while loop that at the end of i call Thread.sleep to prevent starvation...

How long do you sleep? Have you tried Thread.yield instead?

Offline c_lilian

Senior Member


Projects: 1


Java games will probably rock someday...


« Reply #8 - Posted 2005-09-08 11:52:19 »

Ok it makes more sense.

There are some typos/errors in your sample code :
-  "Last" should be initialized before move()
- I don't undersand the use of "long", I 'd rather use "double" as it's the format of nanotime() and the type cast to float might be problematic. this is certainly where your problem comes from
- you should divide by 1e9 or 1e6 to work with seconds or millis, but not 1e7 (certainly a typo)


Offline No_Germs

Junior Member





« Reply #9 - Posted 2005-09-08 16:10:45 »

- I don't undersand the use of "long", I 'd rather use "double" as it's the format of nanotime() and the type cast to float might be problematic. this is certainly where your problem comes from
i don't have alot of knowledge about when it's better to cast and when not to.
for example, if i use Math.PI, i usually cast it to a float... i thought that would be easier to process, since you need to preform the operation on fewer Bytes...
and if i have a method that goes like this:
public float DistanceOnX()
{
     return (float)Math.sin(angle);
}
would it be faster if turned it to
public doubleDistanceOnX()
{
     return Math.sin(angle);
}
?
i thought that because a double was larger than a float it would be faster to return a float and not a double. am i wrong again?

besides that, you're right- all typos, sorry for being so sloppy Smiley
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Jackal von ÖRF

Junior Member





« Reply #10 - Posted 2005-09-08 21:32:37 »

Some comments about your coding style... Since you are writing Java, it would be best to write in Java style. It would make it easier for others to read your code. Here are the code conventions by Sun: http://java.sun.com/docs/codeconv/

Some coding style things that stick to my eyes from your code:
- The names of methods and variables should start with a lowercase letter.
- You should use more blank spaces and empty lines (see chapter 8 in the code conventions).
- The opening brace should be at the end of the line that begins the compound statement, like this:
if (condition) {
    statements;
}
- Your main method is capitalized and "new thread" has the class name in lowercase?! Shouldn't those give a compile error?

Also good practice would be (in your run() method) not to catch Exception, but instead InterruptedException or whatever is the actual exception being thrown. Also in most cases leaving a catch block empty is a bad practice.

Offline No_Germs

Junior Member





« Reply #11 - Posted 2005-09-08 21:35:23 »

I 'd rather use "double" as it's the format of nanotime() and the type cast to float might be problematic.
the format of nanotime() is long.
Offline Ask_Hjorth_Larsen

Junior Member




Java games rock!


« Reply #12 - Posted 2005-09-08 22:23:39 »

Hmm, yeah, thread without capital T is rather strange. And what about the Main method? What's going on?

I know no solution to the problem, but I wouldn't use a variable time step. The game model should be completely deterministic in my humble opinion, i.e. no random effects from the sleep stuff. One could always introduce corrections for "sleeping over".

The obvious way to go would be to run a profiler and see where the 28 milliseconds are actually lost.
Offline No_Germs

Junior Member





« Reply #13 - Posted 2005-09-08 22:53:44 »

- Your main method is capitalized and "new thread" has the class name in lowercase?! Shouldn't those give a compile error?
Also good practice would be (in your run() method) not to catch Exception, but instead InterruptedException or whatever is the actual exception being thrown. Also in most cases leaving a catch block empty is a bad practice.
it's just an example... surely, with all the lower\upper case mistakes the code wouldn't compile.

I wouldn't use a variable time step. The game model should be completely deterministic in my humble opinion, i.e. no random effects from the sleep stuff. One could always introduce corrections for "sleeping over".

i think you misunderstood me, i'm not using Thread.sleep to try and adjust the speed of the loop, but to prevent other threads starvation. i could have gone and used Thread.yield instead.
anyway, what are you saying? that i should try and stabalize the gameloop, or are you saying i should check how much time has passed and move the objects accordingly?
Offline c_lilian

Senior Member


Projects: 1


Java games will probably rock someday...


« Reply #14 - Posted 2005-09-09 06:24:45 »

I 'd rather use "double" as it's the format of nanotime() and the type cast to float might be problematic.
the format of nanotime() is long.

Oops, I've mistaken it with sun.misc.Perf timer Smiley

You could start profiling your app just to have a clue where time is spent... may be in the move() methods ? (I use the netbeans profiler)
Also, are you sure of your 28ms duration... how did you measure it ? and dit you try Thread.yield() instead of sleep() ?

Lilian

Offline No_Germs

Junior Member





« Reply #15 - Posted 2005-09-09 11:09:50 »

are you sure of your 28ms duration... how did you measure it ?
and dit you try Thread.yield() instead of sleep() ?
yes, im sure. i just save the result i get from nanoTime() and the result before that and subtract the two, than add up the result to another variable that i then devide by the number of runs to get the average time:

LastTime=CurrentTime;
CurrentTime=System.nanoTime();
Sum+=CurrentTime-LastTime;
NumberOfRuns++;
System.out.println(Sum/NumberOfRuns);
Move();

and i'm using yield, and it didnt' make a difference Smiley
Offline c_lilian

Senior Member


Projects: 1


Java games will probably rock someday...


« Reply #16 - Posted 2005-09-09 12:04:32 »

I give up... try to profile your app to know where time is spent ...

sorry Sad

Lilian

Offline Raghar

Junior Member




Ue ni taete 'ru hitomi ni kono mi wa dou utsuru


« Reply #17 - Posted 2005-09-09 17:05:37 »

Note that your launcher class should be named identically as your application. Using class main as launcher looks horrible. And I hope your slowdown wasn't caused by printing on console. System.out ... is pretty slow
You could use // for your code until you'd increase frame rate again, however if this will not be tested with drawing on screen, it will be useless.
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.

Riven (7 views)
2014-10-02 14:36:20

Pippogeek (41 views)
2014-09-24 16:13:29

Pippogeek (32 views)
2014-09-24 16:12:22

Pippogeek (22 views)
2014-09-24 16:12:06

Grunnt (47 views)
2014-09-23 14:38:19

radar3301 (30 views)
2014-09-21 23:33:17

BurntPizza (65 views)
2014-09-21 02:42:18

BurntPizza (37 views)
2014-09-21 01:30:30

moogie (44 views)
2014-09-21 00:26:15

UprightPath (53 views)
2014-09-20 20:14:06
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!