Xbox LIVE Indie Games
Sort Discussions: Previous Discussion Next Discussion
Page 1 of 1 (13 posts)

Movement lag

Last post 1/9/2010 6:54 AM by noon. 12 replies.
  • 1/2/2010 10:04 PM

    Movement lag

    EDITED:
    You may skip directly to this post

    Or real the thread from the start :

    Hello,
    Below is a really simple Game class that just render a point moving from left to right.
    If anyone can test it and tell me if he sees the point "lagging" ?
    If you don't want to compile it here is the executable : http://dl.free.fr/fYLfoyFak/TestGame.zip  (clic on the link "Telecharger ce fichier")

    On my computer the lag happens sometime right away or after a little time. 
    The point movement is smooth, then it jumps in a jerky way, become smooth again, jumps, etc...

    I coded this simple test because I had the same issue on a "real" case. 
    Does anyone have a good explaination ? Is there any way to get a continious movement ?

    Thanks


        public class Game1 : Microsoft.Xna.Framework.Game 
        { 
            GraphicsDeviceManager graphics; 
            SpriteBatch spriteBatch; 
            public int point = 0; 
            Texture2D whiteTexture; 
     
            public Game1() 
            { 
                graphics = new GraphicsDeviceManager(this); 
                Content.RootDirectory = "Content"
                graphics.PreferredBackBufferWidth = 1024; 
                graphics.PreferredBackBufferHeight = 32; 
                InactiveSleepTime = TimeSpan.Zero; 
                TargetElapsedTime = TimeSpan.FromSeconds(1 / 60.0f); 
            } 
     
            protected override void LoadContent() 
            { 
                whiteTexture = new Texture2D(GraphicsDevice, 1, 1, 1, TextureUsage.None, SurfaceFormat.Color); 
                Color[] pixels = { Color.White }; 
                whiteTexture.SetData(pixels); 
                spriteBatch = new SpriteBatch(GraphicsDevice); 
            } 
     
            protected override void Update(GameTime gameTime) 
            { 
                if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) 
                { 
                    this.Exit(); 
                } 
     
                // update the position 
                point = (point + 5) % GraphicsDevice.Viewport.Width; 
     
                base.Update(gameTime); 
            } 
     
            protected override void Draw(GameTime gameTime) 
            {    
                GraphicsDevice.Clear(Color.Black); 
                spriteBatch.Begin(); 
                spriteBatch.Draw(whiteTexture, new Rectangle(point, GraphicsDevice.Viewport.Height / 2, 2, 2), Color.White); 
                spriteBatch.End(); 
                base.Draw(gameTime); 
            } 
        } 

  • 1/2/2010 10:15 PM In reply to

    Re: Movement lag

    Works fine here...    Not sereing any jumping, or lag.   Might look at task man and see how much cpu its taking, or what else is running in the background that might cause it to lag.

    The modulous on the window size will make it a few pixels off each time it resets to start from the left again, but besides that did't notice anything wierd or wrong.
  • 1/2/2010 10:26 PM In reply to

    Re: Movement lag

    To get a smooth movement you should make the movement time-aware something like:

    point = (point + gameTime.elapsedGameTime.Milliseconds) % GraphicsDevice.Viewport.Width; 

    (could be some typo's in it)
  • 1/2/2010 10:48 PM In reply to

    Re: Movement lag

    @Drel :

    Thanks for your feedback. 
    The game uses 100% of a core, 25% of total CPU (I'm on a quad core)
    No other application take some cpu (except the taskmgr and dwm which is vista window manager but its just 1%)

    I'm starting to think i'm crazy :)



  • 1/2/2010 11:03 PM In reply to

    Re: Movement lag

    The time between two calls of the updatemethod is not guaranteed constant.
    So if you correct this by using Gametime in your movement it will look smooth.
  • 1/2/2010 11:16 PM In reply to

    Re: Movement lag

    Marinus Holkema:
    To get a smooth movement you should make the movement time-aware something like:
    Thanks for your feedback.

    I'm using fixed timestep, so gameTime.elapsedGameTime.Milliseconds is constant every frames.
    dt : 0,0166667

    Even if I use the dt, I can see the lag (I tried)

    You gave me the idea to try with a variable time step (see the code below)
    With this code I don't see any lag.

    Any idea how to have a smooth movement using a fixed timestep ?

    smooth, variable time step code :

        public class Game1 : Microsoft.Xna.Framework.Game 
        { 
            GraphicsDeviceManager graphics; 
            SpriteBatch spriteBatch; 
            public float point = 0; 
            Texture2D whiteTexture; 
     
            public Game1() 
            { 
                graphics = new GraphicsDeviceManager(this); 
                Content.RootDirectory = "Content"
                graphics.PreferredBackBufferWidth = 1024; 
                graphics.PreferredBackBufferHeight = 32; 
                InactiveSleepTime = TimeSpan.Zero; 
                IsFixedTimeStep = false
            } 
     
            protected override void LoadContent() 
            { 
                whiteTexture = new Texture2D(GraphicsDevice, 1, 1, 1, TextureUsage.None, SurfaceFormat.Color); 
                Color[] pixels = { Color.White }; 
                whiteTexture.SetData(pixels); 
                spriteBatch = new SpriteBatch(GraphicsDevice); 
            } 
     
            protected override void Update(GameTime gameTime) 
            { 
                if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) 
                { 
                    this.Exit(); 
                } 
     
                float dt = (float)gameTime.ElapsedGameTime.TotalSeconds; 
                point = (point + 400 * dt) % GraphicsDevice.Viewport.Width; 
                Console.WriteLine("dt : " + dt); 
     
                base.Update(gameTime); 
            } 
     
            protected override void Draw(GameTime gameTime) 
            {    
                GraphicsDevice.Clear(Color.Black); 
                spriteBatch.Begin(); 
                spriteBatch.Draw(whiteTexture, new Rectangle((int)Math.Round(point), GraphicsDevice.Viewport.Height / 2, 2, 2), Color.White); 
                spriteBatch.End(); 
                base.Draw(gameTime); 
            } 
        } 

  • 1/2/2010 11:39 PM In reply to

    Re: Movement lag

    Marinus Holkema:
    The time between two calls of the updatemethod is not guaranteed constant.
    In practice, for this sample, it is constant : 

    float dt = (float)gameTime.ElapsedGameTime.TotalSeconds;
    Console.WriteLine("dt : " + dt);

    dt : 0,0166667
    dt : 0,0166667
    dt : 0,0166667
    dt : 0,0166667
    dt : 0,0166667
    dt : 0,0166667
    dt : 0,0166667
    dt : 0,0166667

    I cannot get a dt with a different value.

    By the way I edited my last post in case you read it earlier.
  • 1/3/2010 12:54 AM In reply to

    Re: Movement lag

    Right now the only way I found to get a smooth movement with this sample is to use a variable time step.
    Here is how I understand why I get some lags with fixed time step and none with variable: 

    When using a variable time step with VSync On, the method Update and Draw takes a very little time, and we spend most time waiting for the VSync.
    Therefore we are (almost) sure to arrive at time for the VSync.

    When using a fixed time step with VSync On, the method Update and Draw takes the same little time, but I think the internal game class will wait some time to be sure we get a constant dt of 1/60. Quoting Shawn Hargreaves from http://blogs.msdn.com/shawnhar/archive/2007/07/25/understanding-gametime.aspx : 
    What if your Update + Draw takes less than 1/60 of a second? Also simple. Here we call Update, then call Draw, then look at the clock, notice we have some time left over, so wait around twiddling our thumbs until it is time to call Update again.
     So maybe the time passed waiting to get a fixed dt is sometime too long and therefore we miss a VSync. Here is an illustration : 

     
    U   = Update 
    D   = Draw 
    P   = Present (swap buffer) 
    V   = VSync  
    --- = VSync wait 
    *** = Xna Gameloop wait 
     
     
    Variable Dt VSync On : 
     
             V1        V2          V3         V4 
             |         |           |          | 
     UDP-----| UDP-----| UDP-------| UDP------| 
     
     
    Fixed Dt VSync On : 
     
             V1        V2          V3         V4 
             |         |           |          | 
     UD*****P| UD****** UD******P--| UD******P| 
     

    On the 2nd VSync, the Fixed method miss the VSync.
    It seems plausible because I don't think there is anyway to know when the VSync will happend.

    Now, could this hypothesis explain the lag ? I'm really not sure.

  • 1/4/2010 7:14 PM In reply to

    Re: Movement lag

    It would be nice if I could get more feedbacks about whether people see the point lag or not.
    To test, you just have to copy paste the code below and run it.

    According my test, sometime the point do not jerk, but if you move the game window, it will freeze the game, and after the point will start to lag.

    If you think it's lagging you can HOLD Space to switch to a Variable time step and see the difference. The point will become green.
    On my computer it stops the lag.

    I'm also interested in the reason of this behavior. Thanks!

    using System; 
    using Microsoft.Xna.Framework; 
    using Microsoft.Xna.Framework.Graphics; 
    using Microsoft.Xna.Framework.Input; 
     
    namespace TestGame 
        public class Game1 : Microsoft.Xna.Framework.Game 
        { 
            GraphicsDeviceManager graphics; 
            SpriteBatch spriteBatch; 
            public float point = 0; 
            Texture2D whiteTexture; 
     
            public Game1() 
            { 
                graphics = new GraphicsDeviceManager(this); 
                Content.RootDirectory = "Content"
                graphics.PreferredBackBufferWidth = 1024; 
                graphics.PreferredBackBufferHeight = 32; 
                InactiveSleepTime = TimeSpan.Zero; 
                IsFixedTimeStep = true
            } 
     
            protected override void LoadContent() 
            { 
                whiteTexture = new Texture2D(GraphicsDevice, 1, 1, 1, TextureUsage.None, SurfaceFormat.Color); 
                Color[] pixels = { Color.White }; 
                whiteTexture.SetData(pixels); 
                spriteBatch = new SpriteBatch(GraphicsDevice); 
            } 
     
            protected override void Update(GameTime gameTime) 
            { 
                if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) 
                { 
                    this.Exit(); 
                } 
     
                // Hold Space to use a variable timestep 
                IsFixedTimeStep = !Keyboard.GetState().IsKeyDown(Keys.Space); 
     
                float dt = (float)gameTime.ElapsedGameTime.TotalSeconds; 
                point = (point + 400 * dt) % GraphicsDevice.Viewport.Width; 
     
                base.Update(gameTime); 
            } 
     
            protected override void Draw(GameTime gameTime) 
            { 
                GraphicsDevice.Clear(Color.Black); 
                spriteBatch.Begin(); 
                spriteBatch.Draw(whiteTexture, new Rectangle((int)Math.Round(point) - 2, GraphicsDevice.Viewport.Height / 2 - 2, 4, 4), IsFixedTimeStep ? Color.White : Color.Lime); 
                spriteBatch.End(); 
                base.Draw(gameTime); 
            } 
        }  
     

  • 1/5/2010 4:56 PM In reply to

    Re: Movement lag

    I'm still not sure but it seems the internal XNA game loop may make the drawing lag (under certains conditions).
    I created a small project on codeplex to test this issue.
    I would like to understand why this is happening, so I need to get some feedbacks about wether you see the point lag or not. You just need to run the application, follow the steps described below and reply.


    To download it : Sources + binary
    To test the lag:
    1. Launch the game
    2. Move the window during 1 second to make the game freeze
    3. Stop moving the window and look at the point movement
    At this point you should see the point lag (doing undesire jumps). Then you can change the settings :

    • Removing the VSync : should not change anything to the lag but you will see some tearing
    • Set IsFixedTimeStep to FALSE : should remove the lag no matter if the VSync in On or Off (if Off you should have a hug framerate, so it's not really a good test case)
    • Changing point size : help to see the VSync tearing.

    If you have any ideas for the lag reasons...

    Thanks!

  • 1/8/2010 10:42 PM In reply to

    Re: Movement lag

    Any feedbacks, ideas ?
  • 1/9/2010 2:35 AM In reply to

    Re: Movement lag

    Feedback: This topic has been discussed here so many times, people are probably sick to death of discussing ;)

  • 1/9/2010 6:54 AM In reply to

    Re: Movement lag

    Thanks for replying. I had searched the forum before, but I couldn't find anything on the subject.
    Maybe you inspried my search queries since I found this thread : http://forums.xna.com/forums/p/9934/53561.aspx#53561

    Shawn Hargreaves:
    So, you have to accept that Windows games will always drop a frame every now and then. The next question is, what should your game do to recover when this happens? You have basically three options: 
    • Do nothing, and just loose some time. Not good, and very obvious to the player.
    • In your next update, account for how much time has been lost, and move all your objects slightly further to compensate for it. This is the behavior you get if you set IsFixedTimestep = false. Trouble is, this accounting makes your update logic more complex.
    • Use IsFixedTimestep = true, and don't write any special code in your update method. In this case the framework will keep track of how much time has been lost, and once that adds up to enough to make up a whole extra Update, we will call Update an extra time to catch up with where we ought to be.
    [...]
    Because of how the human eye works. The simpler your game, the more obvious the glitching will be. 

    I agree with that, but seems to me the lags or jumps are also due to the way the xna gameloop try to catchup a drop of framerate. It seems pretty periodic and predictible if you have tested the binary.
    Instead of lagging one frame (or a little more) and doing the catchup, the lags continue during 20 seconds (more or less) until it stops.

    Thanks anyway
Page 1 of 1 (13 posts) Previous Discussion Next Discussion