Qt Quick 游戏循环
Qt Quick Game Loop
这是仍然让我对 QML/QtQuick 感到困惑的事情之一:我应该如何实现像 pong 这样使用循环的简单游戏?
我在谷歌上搜索了一下,并在此处查看了类似的问题,但其中 none 解决了以下问题:
我想创建一个简单的游戏,例如使用循环的乒乓球。在这个循环中,首先更新所有对象(在乒乓球和酒吧的情况下),然后渲染所有内容。对于渲染部分,我认为一旦设置了所有属性,QML 就会完成这项工作。
我想使用 QML 和 QtQick 而不是 QGraphicsScene。
我见过一些只使用定时器然后调整属性的例子,例如这个:https://github.com/NicholasVanSickle/QtQuickTests/blob/master/Pong.qml但是这真的是这样做的方法吗?在这种情况下,您将拥有更新 QML 属性和计时器的循环,但我不明白它们是如何协同工作的。
还有一些游戏引擎使用了QML。我想知道如何在游戏循环中使用 QML。例如,您可以用 C++ 编写游戏循环,然后在其上使用 QML 吗?或者推荐的方法是什么。遗憾的是,我在任何 Qt 文档中都找不到它。
你不需要 QML 中的游戏循环,整个事情都是事件驱动的,无论如何都由底层事件循环提供支持。
您可以轻松利用它,使用计时器、信号、动画以及其他现成的东西。
游戏循环本质上是锁定的。而在 QML 中你只能使用主线程。并且您不得锁定主线程 - 它必须旋转,否则您的应用将停止响应。
我刚开始使用 Qt 时遇到了一个 similar 问题,得到的答案与您得到的答案相同(正确)。与使用 SDL 相比,这是一种不同的思维方式。
我想添加一种方法,让您可以对更新进行一些控制。已经有一段时间没有人与我分享这个了,但据我所知,它与确保一致的更新频率有关。
不管它是否比仅使用简单的计时器有所改进,拥有一些实际代码将有助于您入门。此外,拥有增量(计算球和桨的位置)是您必须自己做的事情,此代码已经为您完成了。
这是 GameTimer
的内容:
void GameTimer::doUpdate()
{
// Update by constant amount each loop until we've used the time elapsed since the last frame.
static const qreal delta = 1.0 / mFps;
// In seconds.
qreal secondsSinceLastUpdate = mElapsedTimer.restart() * 0.001;
mRemainder += secondsSinceLastUpdate;
while (mRemainder > 0) {
emit updated(delta);
mDateTime = dateFromSimulatedTime();
mRemainder -= delta;
mSimulatedTime += delta;
}
}
它在 C++ 中的用法如 this:
void DirectPather::timerUpdated(qreal delta)
{
QHashIterator<QuickEntity*, DirectPathData> it(mData);
while (it.hasNext()) {
it.next();
QuickEntity *entity = it.key();
DirectPathData pathData = it.value();
if (mSteeringAgent->steerTo(entity, pathData.targetPos, delta)) {
mData.remove(entity);
}
}
}
由于此示例 (quickpather) 是基于 QML 的,因此它有一个复杂的 setter 用于连接到计时器。如果您不需要像示例那样在 QML 中添加内容,您可以在 C++ 中创建计时器并在必要时直接连接到其更新信号:
connect(mTimer, &GameTimer::updated, foo, &MyGameObject::update);
// ...
connect(mTimer, &GameTimer::updated, bar, &MyOtherGameObject::update);
增量以秒为单位(1.0 == 一秒)。
您可以从示例中获取任何您需要的内容来帮助您开始游戏。
直接回答您的一些问题:
I have seen some examples that just use a timer and then adjust the properties, for example this one: https://github.com/NicholasVanSickle/QtQuickTests/blob/master/Pong.qml But is this really the way to do it. In this case you would have the loop that updates the QML properties and the timer as well and I don't understand how the work together.
我不建议像这个游戏那样在 QML/JavaScript 中执行逻辑。 C++ 比 JavaScript 更适合这个(又名更快)。不过,诸如脚本之类的东西非常适合 JavaScript。
Also there are some game engines that use QML. I would like to know how to use QML within a game loop. For example could you write the game loop in C++ and then have QML on top of it? Or what is the recommended way of doing it. Sadly I could not find this in any of the Qt documentation.
我的 "engine" 将 C++ 用于所有逻辑(脚本除外,它们保持相对较小),将 QML 用于 GUI 以及实体(动画、精灵等)。
我认为没有关于这个确切主题的任何文档(使用 QML 前端用 C++ 编写的游戏),但是有一些基于 QML 的游戏示例:
这是仍然让我对 QML/QtQuick 感到困惑的事情之一:我应该如何实现像 pong 这样使用循环的简单游戏?
我在谷歌上搜索了一下,并在此处查看了类似的问题,但其中 none 解决了以下问题:
我想创建一个简单的游戏,例如使用循环的乒乓球。在这个循环中,首先更新所有对象(在乒乓球和酒吧的情况下),然后渲染所有内容。对于渲染部分,我认为一旦设置了所有属性,QML 就会完成这项工作。
我想使用 QML 和 QtQick 而不是 QGraphicsScene。
我见过一些只使用定时器然后调整属性的例子,例如这个:https://github.com/NicholasVanSickle/QtQuickTests/blob/master/Pong.qml但是这真的是这样做的方法吗?在这种情况下,您将拥有更新 QML 属性和计时器的循环,但我不明白它们是如何协同工作的。
还有一些游戏引擎使用了QML。我想知道如何在游戏循环中使用 QML。例如,您可以用 C++ 编写游戏循环,然后在其上使用 QML 吗?或者推荐的方法是什么。遗憾的是,我在任何 Qt 文档中都找不到它。
你不需要 QML 中的游戏循环,整个事情都是事件驱动的,无论如何都由底层事件循环提供支持。
您可以轻松利用它,使用计时器、信号、动画以及其他现成的东西。
游戏循环本质上是锁定的。而在 QML 中你只能使用主线程。并且您不得锁定主线程 - 它必须旋转,否则您的应用将停止响应。
我刚开始使用 Qt 时遇到了一个 similar 问题,得到的答案与您得到的答案相同(正确)。与使用 SDL 相比,这是一种不同的思维方式。
我想添加一种方法,让您可以对更新进行一些控制。已经有一段时间没有人与我分享这个了,但据我所知,它与确保一致的更新频率有关。
不管它是否比仅使用简单的计时器有所改进,拥有一些实际代码将有助于您入门。此外,拥有增量(计算球和桨的位置)是您必须自己做的事情,此代码已经为您完成了。
这是 GameTimer
的内容:
void GameTimer::doUpdate()
{
// Update by constant amount each loop until we've used the time elapsed since the last frame.
static const qreal delta = 1.0 / mFps;
// In seconds.
qreal secondsSinceLastUpdate = mElapsedTimer.restart() * 0.001;
mRemainder += secondsSinceLastUpdate;
while (mRemainder > 0) {
emit updated(delta);
mDateTime = dateFromSimulatedTime();
mRemainder -= delta;
mSimulatedTime += delta;
}
}
它在 C++ 中的用法如 this:
void DirectPather::timerUpdated(qreal delta)
{
QHashIterator<QuickEntity*, DirectPathData> it(mData);
while (it.hasNext()) {
it.next();
QuickEntity *entity = it.key();
DirectPathData pathData = it.value();
if (mSteeringAgent->steerTo(entity, pathData.targetPos, delta)) {
mData.remove(entity);
}
}
}
由于此示例 (quickpather) 是基于 QML 的,因此它有一个复杂的 setter 用于连接到计时器。如果您不需要像示例那样在 QML 中添加内容,您可以在 C++ 中创建计时器并在必要时直接连接到其更新信号:
connect(mTimer, &GameTimer::updated, foo, &MyGameObject::update);
// ...
connect(mTimer, &GameTimer::updated, bar, &MyOtherGameObject::update);
增量以秒为单位(1.0 == 一秒)。
您可以从示例中获取任何您需要的内容来帮助您开始游戏。
直接回答您的一些问题:
I have seen some examples that just use a timer and then adjust the properties, for example this one: https://github.com/NicholasVanSickle/QtQuickTests/blob/master/Pong.qml But is this really the way to do it. In this case you would have the loop that updates the QML properties and the timer as well and I don't understand how the work together.
我不建议像这个游戏那样在 QML/JavaScript 中执行逻辑。 C++ 比 JavaScript 更适合这个(又名更快)。不过,诸如脚本之类的东西非常适合 JavaScript。
Also there are some game engines that use QML. I would like to know how to use QML within a game loop. For example could you write the game loop in C++ and then have QML on top of it? Or what is the recommended way of doing it. Sadly I could not find this in any of the Qt documentation.
我的 "engine" 将 C++ 用于所有逻辑(脚本除外,它们保持相对较小),将 QML 用于 GUI 以及实体(动画、精灵等)。
我认为没有关于这个确切主题的任何文档(使用 QML 前端用 C++ 编写的游戏),但是有一些基于 QML 的游戏示例: