4

Even though i have some experience in c#, this is my First game in C#. I am trying to set up the minimal skeleton of the game. I heard that Tick Event is a bad approarch for creating the main game loop.

This is the main concept of what I am trying to implement:

Program.cs

//Program.cs calls the Game Form.
Application.Run(new Game());

Game.cs

public partial class Game : Form
{
    int TotalFramesCount = 0;
    int TotalTimeElapsedInSeconds = 0;

    public Game()
    {
        InitializeComponent();
        GameStart();
    }

    public void GameStart()
    {
        GameInitialize();

        while(true)
        {                
            GameUpdate();                
            TotalFramesCount++;
            CalculateTotalTimeElapsedInSeconds();
            //Have a label to display FPS            
            label1.text = TotalFramesCount/TotalTimeElapsedInSeconds;
        }
    }

    private void GameInitialize()
    {
        //Initializes variables to create the First frame.
    } 

    private void GameUpdate()
    {
        // Creates the Next frame by making changes to the Previous frame 
        // depending on users inputs.           
    }     

    private void CalculateTotalTimeElapsedInSeconds()
    {
        // Calculates total time elapsed since program started
        // so that i can calculate the FPS.            
    }  

}

Now, this will not work because the while(true) loop blocks the Game Form from initializing. I found some solutions to this, by using System.Threading.Thread.Sleep(10); or Application.DoEvents();, but I didn't manage to make it work.

To explain why I want to implement this code here is an example of the above code in use:
Lets say I want my game to do the following:
Smoothly move a 100x100 Black colored Square from point (x1,y1) to (x2,y2) and backwards, in a loop and display the FPS in the label1 of the above code. With the above code in mind, I could possibly use TotalTimeElapsedInSeconds variable to set the speed of the movement to be relevant with the Time and not the Frames, as the Frames will differ on each machine.

// Example of fake code that moves a sqare on x axis with 20 pixels per second speed
private void GameUpdate()
{
int speed = 20;
MySquare.X = speed * TotalTimeElapsedInSeconds;
}

The reason i though of using a while(true) loop is that I will get the best FPS I can on each machine.

  • How could I implement my idea on actual code ? (just the basic skeleton is what i am looking for)
  • How could I set a max of, lets say 500 FPS to make the code "lighter" to run? instead of trying to produce as many frames as possible which I suspect will needlesly over-use the CPU(?)
dimitris93
  • 4,155
  • 11
  • 50
  • 86
  • You should separate the code that updates your UI in another thread. Check this question for more info: http://stackoverflow.com/questions/661561/how-to-update-the-gui-from-another-thread-in-c – Filippos Karapetis Nov 02 '14 at 21:08
  • @FilipposKarapetis I am looking for something significantly more specific than this reply, since i never needed to create a thread for my programs thus far, therefore I have no experience on how to code that. – dimitris93 Nov 02 '14 at 21:14
  • You should look into the pipeline of a graphics engine (any graphics engine will be good enough) to see how they manage to achieve this kind of thing. You should have an asynchronous process managing this pipeline. Take a look into the `Task` class of .NET which is very useful to create asynchronous tasks. – Matt Ko Nov 02 '14 at 21:19
  • 2
    I suggest you to use the **XNA** or **WaveEngine** framework which already contain those built-in functions. And yes, the tick event is a really bad approach. Moreover 500 Fps is way too much, lock them to 60 Fps which is the best frame rate limit. – Omar Nov 02 '14 at 21:30
  • 1
    Give a look to this answer on [how to create a game loop on winforms](http://gamedev.stackexchange.com/questions/67651/what-is-the-standard-c-windows-forms-game-loop). – Omar Nov 02 '14 at 21:35
  • I want to emphasize what @OmarMahili said. The idea of a game loop originated in environments that did not have a message loop. A Windows message loop serves the same purpose as the original game loop. So for Windows Forms we don't need an additional loop. If you understand how Windows works then you can use the message loop built into Windows Forms (Application.Run). – Sam Hobbs Mar 30 '18 at 21:22

2 Answers2

8

Frame rate has nothing to do with smoothness. Even if you accomplish 500 frames/sec the movement will be choppy or worse. The trick is to synchronize with your monitor refresh rate. So for a monitor with 60Hz you need 60 frames/sec no more no less. You can't do that by using a loop in C#. You need DirectX or XNA. These frameworks can synchronize your drawings with the vertical scan of your monitor.

Daniel Mann
  • 57,011
  • 13
  • 100
  • 120
  • How is 60FPS better than 500 ? – dimitris93 Nov 02 '14 at 21:27
  • Anyway, I don't think this reply addresses my question to the point that its worth posting as a valid answer. I don't understand why you'd bother posting this as an answer to my question – dimitris93 Nov 02 '14 at 21:37
  • 1
    @Shiro You said *Smoothly move a 100x100 Black colored Square...* and I answered that you can't do it. You need directX. That is the answer. – γηράσκω δ' αεί πολλά διδασκόμε Nov 02 '14 at 21:39
  • I have already managed to move a a 100x100 Black colored Square smoothly by using a Tick function every 10ms, and it works pretty good, now i'd like someone to guide me on how to create the `basic skeleton of a game loop`, which remains my main question and the title of my post. – dimitris93 Nov 02 '14 at 21:42
  • 1
    _I don't understand why you'd bother posting this as an answer to my question_ I'm afraid the __I don't understand__ part is the problem. Staying in synch can't be achieved by running slow __or__ fast.. – TaW Nov 02 '14 at 22:43
  • 3
    Most monitors refresh at 60hz (60 times per second) - it's almost pointless to render many times over this number of FPS as the monitor can't display the frames that are rendered in between. If you don't lock the update to the screen refresh it results in tearing (the monitor draws part of one graphics frame and part of the next frame and so on) - this can result in a noticeable artefact which can be quite distracting in game: http://en.wikipedia.org/wiki/Screen_tearing – Charleh Nov 03 '14 at 11:25
  • 1
    The reason I said "almost" pointless is that it depends if you want to sacrifice visual fidelity for super-responsive gameplay. You can notice the difference between a 60FPS shooter and one running at 100FPS (not really visually though), there's some input lag associated with vsync which can be eliminated by turning it off. I used to play shooters at 100FPS and it made a big difference to the feel of multiplayer twitch games. – Charleh Nov 03 '14 at 11:28
0

You need to make own thread to that while(true)-loop:

Thread thread = new Thread(new ThreadStart(GameStart));
thread.Priority = ThreadPriority.Lowest;
InitializeComponent();
thread.Start();

Check this blog post to get more coding intuition: https://praybook2.blogspot.com/2020/04/this-now-advanced-stuff.html

Tough it loop fast. There are many disadvantages by using the threads, consider using some ready built game engine --like Godot; where all these kinds of small problems are fixed beforehand, use threads only when they are needed.

rmaleki
  • 581
  • 1
  • 9
  • 31
Narutofan
  • 9
  • 6