我没有写游戏的经验,这周我正在尝试用QT写一个音乐游戏地图的玩家(最终可能成为游戏?);遇到问题,我想我需要一些帮助。
我想在 QOpenGLWidget 上以 60 FPS 的速度显示动画。只是小部件中的一些圆圈移动,CPU使用率很低。但它看起来很滞后。
我通过将默认表面格式的交换行为设置为双缓冲区/三缓冲区来启用垂直同步,并且间隔为 1,我认为这意味着 60 FPS。
我实现了paintGL() 方法并通过QT 的2D 绘图示例所做的QPainter 绘制内容。
计算每个圆的位置的步骤放置在paintGL 方法之外,并且将在调用paintGL 之前运行。
这是程序运行的流程:
- 阅读脚本
- 启动计时器
- 发布事件以调用“tick”程序
- “tick”程序运行,并请求更新窗口。
- paintGL 运行,绘制框架
- 在退出paintGL方法之前,会发布一个调用“tick”的事件
- 我认为现在它等待 VSync 和交换缓冲区
- 调用“tick”,转到第 4 步
编码:
class CgssFumenPlayer : public QOpenGLWidget
{
Q_OBJECT
...
bool Load();
public slots:
void onTick();
protected:
....
void paintGL() override;
QElapsedTimer elapsedTimer;
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QSurfaceFormat fmt;
fmt.setSwapBehavior(QSurfaceFormat::TripleBuffer);
fmt.setSwapInterval(1);
QSurfaceFormat::setDefaultFormat(fmt);
CgssFumenPlayer w;
w.Load();
w.setFixedSize(704, 396);
w.show();
return a.exec();
}
bool CgssFumenPlayer::Load()
{
....
elapsedTimer.start();
QMetaObject::invokeMethod(this, "onTick", Qt::QueuedConnection);
}
void CgssFumenPlayer::onTick()
{
playerContext.currentTime = elapsedTimer.elapsed() / 1000.0;
double f = playerContext.currentTime / (1.0 / 60);
playerContext.currentTime = (int)f * (1.0 / 60);
fumen->Compute(&playerContext);
update();
}
void CgssFumenPlayer::paintGL()
{
QPainter painter;
painter.begin(this);
painter.setRenderHint(QPainter::Antialiasing);
painter.setWindow(0, 0, windowWidth, windowHeight);
painter.fillRect(QRectF(0, 0, windowWidth, windowHeight), QColor().black());
DrawButtons(painter);
DrawIcons(painter, &playerContext);
painter.end();
QMetaObject::invokeMethod(this, "onTick", Qt::QueuedConnection);
}
我尝试了这些方法来获取更多信息:
- 每次进入paintGL方法时通过qDebug()打印当前时间。
似乎有时会掉帧;看起来很明显,距离上次调用的间隔超过30ms。 - 将鼠标移入/移出窗口持续时间动画。它变得滞后的可能性更高。
- 收集计算位置的时间成本,似乎只有很短的时间。
- 在android中运行这个程序,一样甚至更慢。
- 更复杂的游戏可以在我的电脑上流畅运行。我认为硬件足够快。(i7-4800M, GTX 765M)
- 一次又一次地重新启动程序。它现在很流畅(很少或没有发生丢帧),现在很迟钝......我找不到模式。
此外,将动画调整为 30 FPS,因为它看起来总是滞后。
我该如何处理这个问题?
(ps我希望它也可以在android上运行)
这是完整的源代码
https://github.com/sorayuki/CGSSPlayer/releases(cgssplayer.zip,不是源代码)
(我认为cgss-fumen.cpp对这个问题没有影响)
它可以构建在 QTCreator (5.6) 中,没有其他依赖项。
(对于 QT 5.5,它需要添加
CONFIG += c++11
进入 .pro 文件)