C#简单2d游戏-制作基本游戏循环

C#简单2d游戏-制作基本游戏循环,c#,winforms,C#,Winforms,尽管我在c#有一些经验,但这是我在c#的第一场比赛。我正在尝试设置游戏的最小骨架。我听说,Tick Event是创建主游戏循环的一个糟糕方法 这是我试图实现的主要概念: Program.cs //Program.cs calls the Game Form. Application.Run(new Game()); public partial class Game : Form { int TotalFramesCount = 0; int TotalTimeElapsedI

尽管我在c#有一些经验,但这是我在c#的第一场比赛。我正在尝试设置游戏的最小骨架。我听说,
Tick Event
是创建主游戏循环的一个糟糕方法

这是我试图实现的主要概念:

Program.cs

//Program.cs calls the Game Form.
Application.Run(new Game());
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.            
    }  

}
Game.cs

//Program.cs calls the Game Form.
Application.Run(new Game());
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.            
    }  

}
现在,这将不起作用,因为
while(true)
循环阻止游戏表单初始化。我通过使用
System.Threading.Thread.Sleep(10)找到了一些解决方案
Application.DoEvents(),但我没能成功

要解释我为什么要实现这段代码,这里有一个使用上述代码的示例:
假设我希望我的游戏执行以下操作:
将一个
100x100黑色正方形
从点
(x1,y1)
平滑地向后移动到
(x2,y2)
,并在上述代码的
标签1
中显示FPS。考虑到上述代码,我可以使用
TotalTimeElapsedInSeconds
变量设置移动速度,使其与
时间相关,而不是与
帧相关,因为每台机器上的
帧不同

// 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;
}
我之所以使用
while(true)
循环,是因为我可以在每台机器上获得最好的FPS

  • 如何在实际代码中实现我的想法?(我正在寻找的只是基本骨架)
  • 我如何设置最大值,比如说500fps,使代码运行起来“更轻”?而不是试图产生尽可能多的帧,我怀疑这将不必要地过度使用CPU(?)

    • 帧速率与平滑度无关。即使你完成了500帧/秒,运动也会变得不平稳甚至更糟。诀窍是与监视器刷新率同步。因此,对于60Hz的显示器,您需要60帧/秒的速度。在C#中使用循环无法做到这一点。您需要DirectX或XNA。这些框架可以使您的图形与监视器的垂直扫描同步。

      您需要在while(true)-循环中创建自己的线程:

      查看此博客文章以了解更多编码直觉:


      快一点。使用线程有很多缺点,考虑使用一些现成的游戏引擎——比如戈多;如果所有这些小问题都已事先解决,则仅在需要时使用线程。

      您应该在另一个线程中分离更新UI的代码。查看此问题以了解更多信息:@Filiposkarapetis我正在寻找比此答复更具体的内容,因为迄今为止我从未需要为我的程序创建线程,因此我没有编写线程的经验。你应该查看图形引擎的管道(任何图形引擎都足够好)看看他们是如何做到这一点的。您应该有一个异步进程来管理此管道。查看一下.NET的
      任务
      类,它对于创建异步任务非常有用。我建议您使用已经包含这些内置函数的XNA或WaveEngine框架。是的,滴答声事件是一个非常糟糕的方法。此外,500 Fps太多了,将它们锁定在60 Fps,这是最好的帧速率限制。请看下面的答案。60 Fps比500好多少?@Shiro你说平滑地移动一个100x100的黑色正方形。。。我回答说你做不到。你需要directX。这就是答案。我不明白你为什么要发帖回答我的问题。恐怕我不明白的部分就是问题所在。保持同步不能通过慢速或快速运行来实现。大多数监视器以60hz(每秒60次)刷新-在如此多的FPS上多次渲染几乎是毫无意义的,因为监视器无法显示其间渲染的帧。如果你不将更新锁定到屏幕刷新,它会导致撕裂(显示器会绘制一个图形帧的一部分和下一个图形帧的一部分,依此类推)-这会导致一个明显的伪影,在游戏中会让人分心:我说“几乎”的原因毫无意义的是,这取决于你是否想牺牲视觉逼真度来实现超灵敏的游戏体验。您可以注意到60FPS的shooter和100FPS的shooter之间的区别(虽然不是真正直观的),vsync有一些输入延迟,可以通过关闭它来消除。我以前玩射击游戏的速度是每分钟100帧,这对多人twitch游戏的感觉有很大的影响。