Taro3

View on GitHub

Qt3Dコードのエントリーポイントの作成

青春時代にスネークゲームをやっていなかった人のために、ここで簡単にゲーム性を覚えておきましょう。

目標は、できるだけ多くのリンゴを食べて最高得点を出すことです。蛇が長くなればなるほど、壁や自分の尻尾を避けるのが難しくなります。ああ、と蛇は、それがリンゴを食べるたびに、より速く、より速くなります。ゲームのアーキテクチャは以下のようになります。

ゲームエリアの上にカメラを配置することで、オリジナルのスネークゲームの2D感を維持しつつ、3Dモデルやシェーダーでスパイスを効かせていきます。

さてさて、この瞬間のために多くのページを費やして準備してきました。いよいよスネーク・プロジェクトを始める時が来ました。ch06-snakeという名前の新しいQtクイック・コントロール・アプリケーションを作成します。プロジェクトの詳細で

  1. 最小限必要なQtのバージョン欄はQt 5.6を選択してください。
  2. ui.qmlファイルのチェックを外します。
  3. ネイティブなスタイリングを有効にするのチェックを外す。
  4. 次へ」をクリックして、以下のキットを選択します。
    • RaspberryPi 2
    • デスクトップ
  5. 次へ」→「完了」をクリックします。

Qt3Dモジュールを追加する必要があります。ch06-snake.proをこのように変更します。

TEMPLATE = app

QT += qml quick 3dcore 3drender 3dquick 3dinput 3dextras
CONFIG += c++11

SOURCES += main.cpp

RESOURCES += \
    snake.qrc

HEADERS +=

target.files = ch06-snake
target.path = /home/pi
INSTALLS += target

Qt3Dが動作するための適切なOpenGLコンテキストを持つために、アプリケーションのエントリーポイントを準備しなければなりません。main.cppを開いて、以下のように更新します。

#include <QGuiApplication>
#include <QtGui/QOpenGLContext>
#include <QtQuick/QQuickView>
#include <QtQml/QQmlEngine>

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    qputenv("QT3D_GLSL100_WORKAROUND", "");

    QSurfaceFormat format;
    if (QOpenGLContext::openGLModuleType() ==
        QOpenGLContext::LibGL) {
        format.setVersion(3, 2);
        format.setProfile(QSurfaceFormat::CoreProfile);
    }
    format.setDepthBufferSize(24);
    format.setStencilBufferSize(8);

    QQuickView view;
    view.setFormat(format);
    view.setResizeMode(QQuickView::SizeRootObjectToView);
    QObject::connect(view.engine(), &QQmlEngine::quit,
        &app, &QGuiApplication::quit);
    view.setSource(QUrl("qrc:/main.qml"));
    view.show();

    return app.exec();
}

このアイデアは、OpenGLを適切に扱うためにQSurfaceFormatを設定し、それをカスタムのQQuickView viewに与えることです。このビューは、このフォーマットを使用して自分自身を描画します。

qputenv(“QT3D_GLSL100_WORKAROUND”,”“)命令は、Raspberry Piなどの組み込みLinuxデバイス上のQt3Dシェーダに関連する回避策です。これにより、一部の組み込みデバイスで必要とされるライトのためのGLSL 1.00のスニペットを別個に用意できるようになります。この回避策を使用しないと、黒い画面が表示され、Raspberry Pi上でプロジェクトを正常に実行できなくなります。


Tip

Qt3d lightsの回避策の詳細はこちら:https://codereview.qt-project.org/#/c/143136/


ここでは、Qt Quickを使ってビューを扱うことにしました。もう一つの方法は、QMainWindowを継承するC++クラスを作成し、それをQMLコンテンツの親にすることです。この方法は、多くの Qt3D のサンプルプロジェクトで見ることができます。どちらも有効で、うまくいきます。QMainWindowアプローチではコードを書く量が多くなりがちですが、C++のみで3Dシーンを作成することができます。

main.cpp ファイルの view が main.qml ファイルを読み込もうとしていることに注意してください。これは main.qml です。

import QtQuick 2.6
import QtQuick.Controls 1.4

Item {
    id: mainView

    property int score: 0
    readonly property alias window: mainView

    width: 1280; height: 768
    visible: true

    Keys.onEscapePressed: {
        Qt.quit()
    }

    Rectangle {
        id: hud

        color: "#31363b"
        anchors.left: parent.left
        anchors.right: parent.right
        anchors.top : parent.top
        height: 60

        Label {
            id: snakeSizeText
            anchors.centerIn: parent
            font.pointSize: 25
            color: "white"
            text: "Score: " + score
        }
    }
}

ここでは、画面上部にある HUD (ヘッドアップディスプレイ) を定義し、そこにスコア (食べたリンゴの数) を表示します。EscapeキーをQt.quit()シグナルにバインドしていることに注意してください。このシグナルはmain.cppでQGuiApplication::quit()シグナルに接続してアプリケーションを終了させています。

これで QML コンテキストが Qt3D コンテンツを歓迎する準備が整いました。main.qmlを以下のように変更してください。

import QtQuick 2.6
import QtQuick.Controls 1.4
import QtQuick.Scene3D 2.0

Item {
    ...

    Rectangle {
        id: hud
        ...
    }

    Scene3D {
        id: scene
        anchors.top: hud.bottom
        anchors.bottom: parent.bottom
        anchors.left: parent.left
        anchors.right: parent.right
        focus: true
        aspects: "input"
    }
}

Scene3D要素は、hudオブジェクトの下の利用可能なスペースをすべて取ります。キーボードイベントを傍受できるように、ウィンドウのフォーカスを取ります。また、Qt3D エンジンがグラフ走査でキーボードイベントを処理できるようにするために、入力面を有効にしています。


戻る