gpt4 book ai didi

c# - 将 2D 图形绘制到表单似乎滞后/减慢我的程序

转载 作者:太空狗 更新时间:2023-10-30 00:33:15 25 4
gpt4 key购买 nike

我刚开始学习 .NET,所以这很可能是一个严重的 n00b 错误:

我正在尝试制作一个简单的乒乓球游戏,使用一个表单然后System::Drawing::Graphics 类将游戏绘制到窗体中。

我的代码的重要部分如下所示:

(主游戏循环):

void updateGame()
{
//Update Game Elements
(Update Paddle And Ball) (Ex. paddle.x += paddleDirection;)
//Draw Game Elements
//Double Buffer Image, Get Graphics
Bitmap dbImage = new Bitmap(800, 600);
Graphics g = Graphics::FromImage(dbImage);
//Draw Background
g.FillRectangle(Brushes::White, 0, 0, 800, 600);
//Draw Paddle & Ball
g.FillRectangle(Brushes::Black, paddle);
g.FillRectangle(Brushes::Red, ball);
//Dispose Graphics
g.Dispose();
//Draw Double Buffer Image To Form
g = form.CreateGraphics();
g.DrawImage(dbImage, 0, 0);
g.Dispose();
//Sleep
Thread.sleep(15);
//Continue Or Exit
if(contineGame())
{
updateGame();
}
else
{
exitGame();
}
}

(表单初始化代码)

void InitForm()
{
form = new Form();
form.Text = "Pong"
form.Size = new Size(800, 600);
form.FormBorderStyle = FormBorderStyle::Fixed3D;
form.StartLocation = StartLocation::CenterScreen;
Application::Run(form);
}

附言。这不是确切的代码,我只是凭内存写的,所以这是任何错别字或错误的名称,或一些与初始化表单有关的重要代码行将来自。

这就是代码。我的问题是游戏肯定不是每 15 毫秒(约 60 fps)更新一次,它的运行速度要慢得多,所以我要做的是每次将桨/球移动更大的距离以补偿它不更新很快,这看起来很糟糕。

简而言之,在绘制图形时,某些东西会大大降低游戏速度。我觉得它与我的双缓冲有关,但我无法摆脱它,因为那会产生一些令人讨厌的闪烁。我的问题是,我该如何摆脱这种滞后?

最佳答案

此代码有几个问题会严重影响应用性能:

  1. 每帧创建一个大的位图缓冲并且不处理它
  2. 在 WinForms 已经很好地实现了这种行为的情况下实现双缓冲
  3. updateGame() 是递归的,但它不一定是递归的
  4. 在 GUI 线程中调用 Thread.Sleep()

代码示例,它使用单独的线程来计算游戏滴答声和 WinForms 内置双缓冲:

static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new GameWindow());
}

class GameWindow : Form
{
private Thread _gameThread;
private ManualResetEvent _evExit;

public GameWindow()
{
Text = "Pong";
Size = new Size(800, 600);
StartPosition = FormStartPosition.CenterScreen;
FormBorderStyle = FormBorderStyle.Fixed3D;
DoubleBuffered = true;

SetStyle(
ControlStyles.AllPaintingInWmPaint |
ControlStyles.OptimizedDoubleBuffer |
ControlStyles.UserPaint,
true);
}

private void GameThreadProc()
{
IAsyncResult tick = null;
while(!_evExit.WaitOne(15))
{
if(tick != null)
{
if(!tick.AsyncWaitHandle.WaitOne(0))
{
// we are running too slow, maybe we can do something about it
if(WaitHandle.WaitAny(
new WaitHandle[]
{
_evExit,
tick.AsyncWaitHandle
}) == 0)
{
return;
}
}
}
tick = BeginInvoke(new MethodInvoker(OnGameTimerTick));
}
}

private void OnGameTimerTick()
{
// perform game physics here
// don't draw anything

Invalidate();
}

private void ExitGame()
{
Close();
}

protected override void OnPaint(PaintEventArgs e)
{
var g = e.Graphics;
g.Clear(Color.White);

// do all painting here
// don't do your own double-buffering here, it is working already
// don't dispose g
}

protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
_evExit = new ManualResetEvent(false);
_gameThread = new Thread(GameThreadProc);
_gameThread.Name = "Game Thread";
_gameThread.Start();
}

protected override void OnClosed(EventArgs e)
{
_evExit.Set();
_gameThread.Join();
_evExit.Close();
base.OnClosed(e);
}

protected override void OnPaintBackground(PaintEventArgs e)
{
// do nothing
}
}
}

可以进行更多改进(例如,仅使部分游戏画面无效)。

关于c# - 将 2D 图形绘制到表单似乎滞后/减慢我的程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12888211/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com