C#简单的2d游戏-使基本的游戏循环
本文关键字:游戏 循环 2d 简单 | 更新日期: 2023-09-27 18:28:53
尽管我在c#方面有一些经验,但这是我在c#中的第一个游戏。我正在尝试设置游戏的最小骨架。我听说Tick Event
是创建主游戏循环的糟糕方法。
这是我试图实现的主要概念:
程序.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.
}
}
现在,这将不起作用,因为while(true)
循环阻止了游戏窗体的初始化。通过使用System.Threading.Thread.Sleep(10);
或Application.DoEvents();
,我找到了一些解决方案,但我没能成功。
为了解释为什么我要在这里实现此代码,请参见正在使用的上述代码的示例:
假设我希望我的游戏执行以下操作:
平滑地在循环中将100x100 Black colored Square
从点(x1,y1)
移动到(x2,y2)
并向后移动,并在上述代码的label1
中显示FPS。考虑到以上代码,我可以使用TotalTimeElapsedInSeconds
变量来设置与Time
而非Frames
相关的移动速度,因为每台机器的Frames
都不同。
// 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。
- 如何在实际代码中实现我的想法?(我要找的只是基本骨架)
- 我如何设置最大值,比方说500 FPS,以使代码运行起来"更轻松"?而不是试图产生尽可能多的帧,我怀疑这会不必要地过度使用CPU(?)
帧速率与平滑度无关。即使你达到500帧/秒,运动也会有起伏甚至更糟。诀窍是与显示器的刷新率同步。因此,对于60Hz的显示器,您需要60帧/秒。在C#中使用循环是不能做到这一点的。您需要DirectX或XNA。这些框架可以使您的绘图与显示器的垂直扫描同步。
您需要为while(true)-loop:创建自己的线程
Thread thread = new Thread(new ThreadStart(GameStart));
thread.Priority = ThreadPriority.Lowest;
InitializeComponent();
thread.Start();
查看此博客文章以获得更多编码直觉:https://praybook2.blogspot.com/2020/04/this-now-advanced-stuff.html
艰难的循环很快。使用线程有很多缺点,可以考虑使用一些现成的游戏引擎,比如Godot;如果所有这些小问题都是事先解决的,那么只在需要的时候使用线程。