0

I picked up a tutorial on how to do a game loop where the framerate is always the same no matter how big the rendering space gets or the speed of your CPU. It involves using a time interval, but I've poured over this a hundred times and I can not see why my version does not work, so I don't know if it's mine or if they got it wrong.

the original tutorial can be found here http://www.dreamincode.net/forums/topic/140540-creating-games-with-c%23-part-2/

namespace TileGame
{
    public partial class GameForm : Form
    {
        HiResTimer gameTime = new HiResTimer();

        long startTime;
        long interval = (long)TimeSpan.FromSeconds(1 / 30).TotalMilliseconds;

        Graphics g;
        Graphics imageGraphics;

        Image backBuffer;

        int clientWidth;
        int clientHeight;

        Rectangle image = new Rectangle(0, 0, 40, 50);
        Point direction = new Point(1, 2);

        public GameForm()
        {
            InitializeComponent();
            this.DoubleBuffered = true;
            this.MaximizeBox = false;
            this.FormBorderStyle = FormBorderStyle.FixedSingle;
            this.ClientSize = new Size(320, 240);

            clientHeight = this.ClientRectangle.Height;
            clientWidth = this.ClientRectangle.Width;

            backBuffer = (Image)new Bitmap(clientWidth, clientHeight);
            g = this.CreateGraphics();
            imageGraphics = Graphics.FromImage(backBuffer);
    }

    public void GameLoop()
    {
            gameTime.Start();
            while (this.Created)
        {
                startTime = gameTime.ElapsedMiliseconds;
                GameLogic();
                Render();
                Application.DoEvents();
                while (gameTime.ElapsedMiliseconds - startTime < interval) ;
            }
        }

        private void GameLogic()
        {
            image.X += direction.X;
            image.Y += direction.Y;

            if (image.X < 0)
            {
                image.X = 0;
                direction.X *= -1;
            }

            if (image.Y < 0)
            {
                image.Y = 0;
                direction.Y *= -1;
            }

            if (image.X + image.Width > clientWidth)
            {
                image.X = clientWidth - image.Width;
                direction.X *= -1;
            }

            if (image.Y + image.Height > clientHeight)
            {
                image.Y = clientHeight - image.Height;
                direction.Y *= -1;
            }

        }

        private void Render()
        {
            imageGraphics.FillRectangle(new SolidBrush(Color.Black),
                                    this.ClientRectangle);
            imageGraphics.FillRectangle(new SolidBrush(Color.Blue), image);

            this.BackgroundImage = backBuffer;
            this.Invalidate();

        }
    }
}
  • 1
    I won't be able to solve this, but that would help to know what you mean by "doesn't work"... When you've got a problem with your car, you don't just drop it to the mechanic, you explain why you think there's a problem... – Laurent S. Apr 07 '14 at 09:29
  • _"constant framerate"_ is impossible ;) use of delta time achieves a separation of game units from the framerate. It is an illusion but a good one. – Gusdor Apr 07 '14 at 09:30
  • Oh yeah.. what I mean is that when I have the window at some minuscule resolution, the blue rectangle bounces around super fast, but when the resolution is higher it slows down to where it should be regulated to in all cases. and let's not nit-pick at the details, I'll go with the illusion of simplicity any day over complicating life. – Monte Emerson Apr 07 '14 at 09:33
  • winforms is not a suitable framework for games (nor for anything else I can think of). You should look into using XNA / MonoGame / Unity3D. – Federico Berasategui Apr 07 '14 at 22:52
  • I'm not trying to make a game. I'm trying to learn a concept, and I don't want to install stuff I don't really need. – Monte Emerson Apr 08 '14 at 21:40

2 Answers2

1

Here is your problem:

   long interval = (long)TimeSpan.FromSeconds(1 / 30).TotalMilliseconds;

You are making an integer division, the result will be 0.

Fix it like this, to turn it into a floating point operation:

   long interval = (long)TimeSpan.FromSeconds(1 / 30.0d).TotalMilliseconds;

Your code has other problems, like busy waiting in the while loop, you should put your thread to sleep for the wait time.

thumbmunkeys
  • 20,606
  • 8
  • 62
  • 110
  • thanks, I appreciate the help. I know you're onto something, but not quite sure what yet because the program freezes on start now that it is a decimal value. Now, I'm pretty sure that I need to make sure that I'm saving CPU time to do other stuff. – Monte Emerson Apr 07 '14 at 16:38
1

I don't see anywhere in your code where the GameLoop method is called. Your code worked for me after I changed the 30 to 30d and added this in the end of the Form's constructor:

new Thread(GameLoop) {IsBackground = true}.Start();
Scott Reece
  • 395
  • 1
  • 3
  • 13
  • I have the GameLoop method call on a different class file, it's in the main. I'll try putting it on a new thread like you suggest though. – Monte Emerson Apr 08 '14 at 21:29
  • Ah ok, yes I added it to the for's constructor, however I failed to mention that I did not use a windows forms application template for this project. I Simply created a Console application and I added the appropriate references to get access to the windows forms. this is because I wanted to have a Debug Console window that I could refer to if I needed to know what was happening specifically with my program. ie, print fps, and send debug messages. – Monte Emerson Apr 08 '14 at 21:45