Qt Quick 游戏循环

Qt Quick Game Loop

这是仍然让我对 QML/QtQuick 感到困惑的事情之一:我应该如何实现像 pong 这样使用循环的简单游戏?

我在谷歌上搜索了一下,并在此处查看了类似的问题,但其中 none 解决了以下问题:

你不需要 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 的游戏示例: