2
\$\begingroup\$

I'm having a bit of trouble with my code meant to create a scrolling background of random-ish ones and zeros. When moving to the right (or left), it scrolls smoothly for a few seconds, stops/jerks, then starts scrolling smoothly again. I've spent an entire day now trying to iron out this issue and nothing that I've done makes it any better.

Here is my isolated code:

    namespace TestScrollyNumbers
    {
public class Game1 : Microsoft.Xna.Framework.Game
{
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;

    public Game1()
    {
        graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";
        graphics.PreferredBackBufferHeight = 768;
        graphics.PreferredBackBufferWidth = 1366;
        graphics.IsFullScreen = false;
        graphics.ApplyChanges();
    }

    KeyboardState CKBS = new KeyboardState();

    Random Randomness = new Random();

    Texture2D NumberScrolly1;
    Texture2D NumberScrolly2;
    Texture2D NumberScrolly3;
    Texture2D NumberScrolly4;
    Texture2D NumberScrolly5;

    float XPosScroll = 0;
    float XPosScrollVel = 0;

    int i = 0;
    int meh = 1;

    public List<Texture2D> BackgroundScrollyTextures = new List<Texture2D>();

    public List<float> ScrollyNumberXPos = new List<float>(); //This list contains the final X positions for the number bars.
    public List<float> ScrollyNumberXStart = new List<float>(); //This will be used to calculate the final X positions for each bar.

    public List<int> ScrollyNumberMultiplier = new List<int>(); //List of Y position multipliers so that I can calculate the Ypos in the draw command.
    public List<int> ScrollyNumberType = new List<int>(); //List of randomized textures for each bar.

    protected override void Initialize()
    {
        base.Initialize();

        BackgroundScrollyTextures.Add(NumberScrolly1);
        BackgroundScrollyTextures.Add(NumberScrolly2);
        BackgroundScrollyTextures.Add(NumberScrolly3);
        BackgroundScrollyTextures.Add(NumberScrolly4);
        BackgroundScrollyTextures.Add(NumberScrolly5); //Add all of the possible textures to the list of textures so that each number in the "ScrollyNumberType" list can correspond to a texture. 
    }

    protected override void LoadContent()
    {
        spriteBatch = new SpriteBatch(GraphicsDevice);

        NumberScrolly1 = Content.Load<Texture2D>("NumbersForBackground1");
        NumberScrolly2 = Content.Load<Texture2D>("NumbersForBackground1");
        NumberScrolly3 = Content.Load<Texture2D>("NumbersForBackground1");
        NumberScrolly4 = Content.Load<Texture2D>("NumbersForBackground1");
        NumberScrolly5 = Content.Load<Texture2D>("NumbersForBackground1"); //Loading :P
    }
    protected override void UnloadContent()
    {

    }

    protected override void Update(GameTime gameTime)
    {

        if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
            this.Exit();

        CKBS = Keyboard.GetState(); //Current Key Board State

        if (meh == 1)
        {
            for (i = 0; i < 18; i++)
            {
                ScrollyNumberMultiplier.Add(Randomness.Next(0, 11));
                ScrollyNumberType.Add(Randomness.Next(0, 5));
                ScrollyNumberXStart.Add(i * 80); //Each bar is 80 pixels wide
                ScrollyNumberXPos.Add(0);
            }
            meh = 0;
        }

        if (CKBS.IsKeyDown(Keys.Right))
        {
            XPosScrollVel += .6f;
        }
        if (CKBS.IsKeyDown(Keys.Left))
        {
            XPosScrollVel -= .6f;
        } //Scrolling - add to the velocity

        XPosScrollVel *= .9f;
        XPosScroll += XPosScrollVel; //Add the current X Velocity to the X Scroll

        for (i = 0; i < ScrollyNumberType.Count; i++)
        {
            if (ScrollyNumberXPos[i] < -79)
            {
                ScrollyNumberXStart[i] += 1440; //Instead of creating a new bar, use the bar that just went off of the screen and give it a new Y pos value
                ScrollyNumberMultiplier[i] = Randomness.Next(0, 11);
            }
            if (ScrollyNumberXPos[i] > 1365)
            {
                ScrollyNumberXStart[i] -= 1440; //Same thing as before, except reverse.
                ScrollyNumberMultiplier[i] = Randomness.Next(0, 11);
            }
            ScrollyNumberXPos[i] = ScrollyNumberXStart[i] - XPosScroll; //final XPos = where it started, plus how many times it's gone across the screen, minus how much you've scrolled.
        }

        base.Update(gameTime);
    }

    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.Black);

        spriteBatch.Begin();

        for (i = 0; i < ScrollyNumberType.Count; i++)
        {
            spriteBatch.Draw(BackgroundScrollyTextures[ScrollyNumberType[i]], new Vector2((int)ScrollyNumberXPos[i], (-37 - 56 * ScrollyNumberMultiplier[i])), null, Color.White, 0, new Vector2(0, 0), new Vector2(1, 1), SpriteEffects.None, 0);
        } //And then draw everything.

        spriteBatch.End();

        base.Draw(gameTime);
    }
}

}

You can use this image to test my code (I didn't include the four others as that would make this post unnecessarily long) if you don't know the answer right away:

For anyone wondering, I use Microsoft Visual C# 2010 Express and XNA Game Studio 4.0.

\$\endgroup\$
20
  • 1
    \$\begingroup\$ Try graphics.IsFullScreen = true; otherwise the issue is most likely due to the GPU being shared. \$\endgroup\$ Jul 21 '15 at 4:45
  • \$\begingroup\$ Hmm no, that didn't work. Same behavior. As for my computer lagging, I thought I already ruled that out with an inconclusive time test, but I guess I'll try again...? I don't think it'll make much of a difference though. \$\endgroup\$ Jul 21 '15 at 5:22
  • \$\begingroup\$ Okay I closed everything else down except for my project and it still has the same glitchy movement. Surely there's nothing special with my game and I'm not the only person who has laggy movement. Is there a fix for this? What I'm doing shouldn't be hard for my computer (or any computer for that matter) to handle... \$\endgroup\$ Jul 21 '15 at 5:32
  • \$\begingroup\$ Did you try multiply your movement by gametime? Otherwise profile it by checking how long the functions for drawing this image takes. If there is no difference in time then the FPS drop should be coming from somewhere else. \$\endgroup\$
    – Madmenyo
    Jul 21 '15 at 9:01
  • \$\begingroup\$ My guess is the freezes come fron the garbage cycles. I think you can check that using the performance monitor tool (perfmon). \$\endgroup\$
    – Felsir
    Jul 21 '15 at 15:21
1
\$\begingroup\$

I've found a possible solution. Set this.IsFixedTimeStep to false.

What this does is syncs Update to Draw so that the game gets updated only as the screen can be drawn. That means that if the game were to lag the game physics (if done in update) would go slower, but it's probably worth it if this graphical glitch is annoying you.

I found another post on the issue so it appears that it is not new. http://xboxforums.create.msdn.com/forums/p/75475/459289.aspx

\$\endgroup\$
6
  • \$\begingroup\$ Thank you! That worked and got rid of about 90-95% of the movement glitches in my program. \$\endgroup\$ Jul 22 '15 at 4:02
  • \$\begingroup\$ You need to modify your code to make it time dependant because without the fixed timestep your code is depending on the speed of the machine running it. Even so, in a fixed timestep there is no guarantee you'll get 60 updates per second so including timing is always a sound practise. \$\endgroup\$
    – Felsir
    Jul 22 '15 at 5:02
  • \$\begingroup\$ @Felsir well yes if the game is dependent on a fixed speed then yes. But it seems the original post did not want choppy animations, and fixing the timestep / allowing skipped frames for time dependency appears not to be the goal here, but rather smooth animations. Also some games are more fun to play slowly rather than more laggy. ;) \$\endgroup\$
    – Superdoggy
    Jul 22 '15 at 5:43
  • \$\begingroup\$ I have to disagree here. If the game uses a fixed timestep, XNA tries to give you 60 frames per second. It may not always be the case, thus timing is still the best way to go. If you set the IsFixedTimestep=false, the game just calls update and draws as fast as the code allows (either limited by performance of the code or to the vsync of the monitor- which can be disabled by setting SynchronizeWithVerticalRetrace = false). Either way, you have no guarantee the update is called in exactly the same frequency on all hardware. I do agree that laggy games are not fun to play though! \$\endgroup\$
    – Felsir
    Jul 22 '15 at 7:06
  • \$\begingroup\$ @Scratchifier I am not convinced that unfixing the timestep fixes the issue- it just changes the timing (hence "got rid 90-95% of the glitches" this is probably because the Update() method is called less often because it now runs in sync with the Draw() method). Have you tried a release build and run the EXE? It might be due to garbage collection and the debugger requiring to update it's internals? \$\endgroup\$
    – Felsir
    Jul 22 '15 at 7:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.