提问人:duffin01 提问时间:10/11/2022 更新时间:10/13/2022 访问量:292
如何在 Windows 窗体中循环 paint 事件以创建简单的游戏循环?
How do I loop the paint event in Windows Forms to create a simple game loop?
问:
我正在尝试在 C# Visual Studio 中创建一个简单的贪吃蛇游戏作为练习。我对 Windows 窗体应用程序知之甚少,但它似乎是使用箭头访问绘图和用户输入的最简单方法。
这是否是一个很好的框架,可以用于 C# 中这样的简单游戏?
但这是我真正的问题。我正在尝试创建游戏循环,它大约每秒循环一次,并改变接下来要画蛇头的位置。但是我无法弄清楚如何多次调用 Paint 事件。它似乎调用了一次,然后退出。如果我使用 Thread.Sleep() 在 paint 方法中放置一个 while() 循环,它会每秒绘制一个矩形,但我无法访问 KeyEventArgs 或其他任何东西,因为正在运行的代码被困在 Paint 调用中。
我希望最初的绘制调用绘制蛇的起点,然后循环绘制调用,我猜测另一种绘制方法(?),它询问控制器最后按下了哪个按钮,然后在该方向上绘制下一个矩形。执行此操作并创建该游戏循环的预期方法是什么?
我将不胜感激任何信息和知识来帮助我学习这个过程,并欢迎任何其他建议或意见!
这是我当前的代码: '''
public partial class FormMain : Form
{
private readonly int pixelSize;
private readonly int gridSize;
private readonly int center;
private string currDirection;
public FormMain()
{
pixelSize = 30;
currDirection = "right";
// Calculating size of the grid based on the size of the 'pixel'
gridSize = 640 / pixelSize;
// Calculating the starting position of the snake in the center of the screen
center = (gridSize / 2) * pixelSize;
InitializeComponent();
}
private void FormMain_Paint(object sender, PaintEventArgs e)
{
// referencing the Graphics object and setting the color of the snake
Graphics g = e.Graphics;
Pen seaPen = new Pen(Color.MediumSeaGreen);
// This draws the initial center rectangle
Point currentHeadLocation = new Point(center, center);
Rectangle r;
// Here's the loop that should happen every second or so, probably in another method.
while (true)
{
r = new Rectangle(currentHeadLocation, new Size(pixelSize, pixelSize));
g.DrawRectangle(seaPen, r);
if (currDirection.Equals("right"))
{
currentHeadLocation = new Point(currentHeadLocation.X + pixelSize, currentHeadLocation.Y);
}
else if (currDirection.Equals("left"))
{
currentHeadLocation = new Point(currentHeadLocation.X - pixelSize, currentHeadLocation.Y);
}
else if (currDirection.Equals("up"))
{
currentHeadLocation = new Point(currentHeadLocation.X, currentHeadLocation.Y - pixelSize);
}
else if (currDirection.Equals("down"))
{
currentHeadLocation = new Point(currentHeadLocation.X, currentHeadLocation.Y + pixelSize);
}
Thread.Sleep(1000);
}
}
private void FormMain_KeyDown(object sender, KeyEventArgs e)
{
switch(e.KeyCode)
{
case Keys.Left:
currDirection = "left";
break;
case Keys.Right:
currDirection = "right";
break;
case Keys.Up:
currDirection = "up";
break;
case Keys.Down:
currDirection = "down";
break;
}
}
}
'''
答:
0赞
TheJP_
10/13/2022
#1
在这种情况下使用 Thread.Sleep() 几乎总是一个坏主意,因为它会冻结你唯一的线程,这也是你的 UI 线程。
您可能想使用计时器。
简单示例:
public FormMain()
{
//Any other init stuff here
System.Windows.Forms.Timer t = new System.Windows.Forms.Timer(); //Create a timer
t.interval = 1000; //interval time in ms
t.Tick += (s, e) => LoopFunctionName(); //Bind a function to the event whenever the timer reaches its interval
}
public void LoopFunctionName()
{
//Game loop
}
如果要强制重新绘制控件,只需调用 .Invalidate()
评论