我正在构建一个Windows MFC应用程序。在某些物体高速碰撞的动画中,我的物理引擎的行为是不可预测的。我相信这与我以某种方式丢帧有关。有人告诉我我没有使用双重缓冲。我以为我是,但我对此仍然很陌生。以下是我在 OnPaint 中绘制屏幕的方式:
#include "pch.h"
#include "framework.h"
#include "ChildView.h"
#include "DoubleBufferDC.h"
void CChildView::OnPaint()
{
CPaintDC paintDC(this); // device context for painting
CDoubleBufferDC dc(&paintDC); // device context for painting
Graphics graphics(dc.m_hDC); // Create GDI+ graphics context
mGame.OnDraw(&graphics);
if (mFirstDraw)
{
mFirstDraw = false;
SetTimer(1, FrameDuration, nullptr);
/*
* Initialize the elapsed time system
*/
LARGE_INTEGER time, freq;
QueryPerformanceCounter(&time);
QueryPerformanceFrequency(&freq);
mLastTime = time.QuadPart;
mTimeFreq = double(freq.QuadPart);
}
/*
* Compute the elapsed time since the last draw
*/
LARGE_INTEGER time;
QueryPerformanceCounter(&time);
long long diff = time.QuadPart - mLastTime;
double elapsed = double(diff) / mTimeFreq;
mLastTime = time.QuadPart;
mGame.Update(elapsed);
}
void CChildView::OnTimer(UINT_PTR nIDEvent)
{
// TODO: Add your message handler code here and/or call default
RedrawWindow(NULL, NULL, RDW_UPDATENOW);
Invalidate();
CWnd::OnTimer(nIDEvent);
}
当我从 CDoubleBufferDC 对象创建图形对象时,这不是创建后台缓冲区吗?然后,我将这个图形对象传递给绘制它的 OnDraw。如果它正在创建后台缓冲区,我对创建前端缓冲区的位置以及何时在屏幕上绘制感到困惑。
以下是我目前对如何工作的想法:
- CPaintDC 对象是前端缓冲区
- CDoubleBufferDC 对象是后台缓冲区
- 图形对象是从 CDoubleBufferDC 对象创建的,我在其上绘制游戏的当前状态
如果是这种情况,何时会将前面的缓冲区替换为在后面创建的新缓冲区?有人可以帮助我理解,如果我还没有使用双重缓冲,有人可以帮助我理解吗?
为了回答您的实际问题,可能发生的情况是您的 CDoubleBufferDC(( 类有一个交换 DC 的析构函数 - 这是一个常见的习语("现代"MFC 版本中的 IIRC CMemDC 也这样做(。所以是的,我认为你在这里使用双重缓冲,即使不小心。对于简单的游戏,您可以在 GDI(+( 中进行绘图,如果整个事情是一个学习练习,这种方式比使用 DirectX 更容易理解。
但是,您确实需要将碰撞检测与绘图例程分离,以便任何丢弃的帧都不会打乱您的计时(也就是说,如果您的事情非常复杂以至于需要花费很多时间 - 在这种情况下,您可能不应该使用 GDI......换句话说,如果您的冲突检测假设每个 OnDraw(( 调用在不到 1/帧速率秒的时间内完成,但这并不总是发生,那么您会在某个时候遇到问题。网上有很多关于如何构建游戏循环的文章;我没有足够的信息将您链接到特定的信息。此外,在 2020 年,使用您正在使用的技术找到一个也不容易......但我确实认为使用简单的OnPaint((/GDI非常适合学习,因为它将隐藏更现代方法所需的大部分复杂性。