0

I've tried to search for this on google and stackoverflow, but I'm not sure what to call it, so I can't find it.

How would I make a "loop" for the C# program, that runs every, say, 100 milliseconds? Similar to what Minecraft calls "ticks", or GameMaker calls "steps".

I can't figure out how to do this. I'm using visual studio, and I have a main window. There are things that I want to execute constantly, so I'm trying to figure out how to make a "step" or "update" function.

Servy
  • 202,030
  • 26
  • 332
  • 449
Dominoed
  • 123
  • 3
  • 15
  • 1
    use `while` and [`Timer`](http://msdn.microsoft.com/en-us/library/system.timers.timer.aspx)? – default Aug 20 '13 at 14:55
  • 3
    You should be using some sort of game design framework that would provide this for you. Are you not? – Servy Aug 20 '13 at 14:57
  • 1
    You can use XNA, which have an update and draw method made for that purpose. But I think XNA is dead, you can look at MonoGame too. – Pierre-Luc Pineault Aug 20 '13 at 14:57
  • For the sake of argument, would a loop with a Thread.Sleep(100); do the job? – Austin T French Aug 20 '13 at 15:03
  • I actually tried: `int stepTime = 10;` `while (true)` `{` `Thread.Sleep(1000/stepTime);` `}` But it didn't work. – Dominoed Aug 20 '13 at 15:05
  • 2
    @AthomSfere That would only work if the code of your loop takes 0ms to run. It won't. Next, `Sleep` doesn't have sufficient precision for most games; it would end up oversleeping too much. – Servy Aug 20 '13 at 15:07
  • So, even if all the loop for the sleep thread did was sleep, fire procedure, sleep (isolated in its own thread even) an absolute no go, as its way too imprecise. – Austin T French Aug 20 '13 at 15:09
  • @Servy How do those game design frameworks do this? Is this not possible to do in .Net - do they do it in C++ instead? – Gjeltema Aug 20 '13 at 15:10
  • @AthomSfere I would imagine so, yes, although I'm not an expert in the field of game programming, but I do know that `Sleep` doesn't have very high precision. The OS is free to wait quite some time before re-enabling the thread, if it wants. – Servy Aug 20 '13 at 15:11
  • 1
    @Gjeltema I don't know. I'm not an expert in the field. I know enough to know that I wouldn't want to solve the problem; I'd use a game design API rather than risk doing it wrong. – Servy Aug 20 '13 at 15:12
  • 1
    related: http://gamedev.stackexchange.com/questions/651/tips-for-writing-the-main-game-loop – Servy Aug 20 '13 at 15:19
  • 1
    Fixing the problem of timer drift from the `work + Sleep(period)` method is algorithmically straight-forward, you just set the Sleep timer based on `previous-timer + Period` rather than `current-time + Period`. Fixing the problems of OS scheduling delay and timing imprecisions, however, is a whole other story. Servy's right, unless you want to go to C++ and unmanaged code (and even then, it's not trivial), you'll need some assist from a game design framework. – RBarryYoung Aug 20 '13 at 15:31
  • If you make the 'step's variable length, you can then do all your physics based on the time elapsed from the last tick. You should move your focus away from finding a fast accurate timer, to finding a way to perform step calculations often while getting an accurate measure of the time between them. I think this is typically done with a loop, not a timer, where the loop will check the time from an accurate measure (maybe stopwatch?) to determine how much to move the world forward in that step. – mao47 Aug 20 '13 at 17:06

3 Answers3

0

If you want it to run for 100 ms you would do this

System.Timers.Timer timer = new System.Timers.Timer(100);
public void Initialize(object sender, EventArgs e)
{
  timer.Elapsed+=Elapsed;
}
public void Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
  //do stuff
}

Something else you can do, however I don't think this one is as efficient

        using System.Threading;

        Thread th = new Thread(new ThreadStart(delegate
        {
            while (true)
            {
                Thread.Sleep(100);
                //do stuff
            }
        }));

Or, you can download monogame to make more elaborate games in c#

http://www.monogame.net/

It has its own gameTime control.

ismellike
  • 629
  • 1
  • 5
  • 14
  • 2
    The precision of a `Timer` is insufficient for a game loop. It's precision is +/- like 16 ms or something like that. A game can't have that kind of variance. – Servy Aug 20 '13 at 15:00
  • Then do you have any suggestions, Servy? – Dominoed Aug 20 '13 at 15:10
  • Then when and how would I call `Initialize`? I tried to do it but I don't know what arguments to call. – Dominoed Aug 20 '13 at 15:31
  • You can just double click on your form and Form1_Load should be created. You can right click>refractor>rename it to Initialize. – ismellike Aug 20 '13 at 15:35
  • @user2697979 Nope; if I did, i'd have posted an answer. I'm not a game design expert. I know enough about the subject to know that it's a *very* hard problem to solve, and this is nowhere near what a real solution will take. – Servy Aug 20 '13 at 15:45
  • To your edit; sleeping for 100 ms won't run the code every 100 ms, because the code he's running will (likely) take longer than 0ms to run. Also note that even `Thread.Sleep` doesn't have sufficient precision to use in the context of a game loop, so even if you calculated the appropriate time to sleep after doing work it still is rather likely to end up over sleeping, thus causing the game to lag. – Servy Aug 20 '13 at 15:47
  • Your best option for making a time based game is to download the monogame sdk. – ismellike Aug 20 '13 at 15:49
  • @ismellike Note that suggesting the OP use a game framework (which one isn't that important; they all have this) isn't technically an answer to the question, it's just a comment. – Servy Aug 20 '13 at 15:52
  • That's actually where I first tried to call it. I put `Initialize()` in the `formMain_Load` function. It says it needs arguments, so what arguments should I use? – Dominoed Aug 20 '13 at 16:06
  • (object sender, EventArgs e) – ismellike Aug 20 '13 at 16:10
  • So when I'm calling it I should use `Initialize(sender, e)`? – Dominoed Aug 20 '13 at 16:22
  • Oh, you don't actually call it, you can just put this inside of the formMain_Load 'timer.Elapsed+=Elapsed;' – ismellike Aug 20 '13 at 16:28
  • Oh that makes much more sense :P I was calling `Initialize` in `formMain_Load`. – Dominoed Aug 20 '13 at 17:22
-1

You could use the Timer control which can be set to tick at a given interval. The interval property is in Milliseconds so you would need Timer1.Interval = 100;

Steven Wood
  • 2,675
  • 3
  • 26
  • 51
  • 2
    The precision of a `Timer` is insufficient for a game loop. It's precision is +/- like 16 ms or something like that. A game can't have that kind of variance. – Servy Aug 20 '13 at 15:01
-2

Are you thinking of a Timer?

http://msdn.microsoft.com/en-us/library/system.timers.timer.aspx

Generates recurring events in an application.

Arran
  • 24,648
  • 6
  • 68
  • 78
  • 2
    The precision of a `Timer` is insufficient for a game loop. It's precision is +/- like 16 ms or something like that. A game can't have that kind of variance. – Servy Aug 20 '13 at 14:58