Skip to content

Game Development

What can we say - we like games. And you can use Qt to write some. Questions? Ask here.
829 Topics 4.0k Posts
  • Welcome!

    Pinned
    42
    1 Votes
    42 Posts
    31k Views
    JKSHJ

    Hi,

    [quote author="cseder" date="1423513071"]But Qt has an excellent solution which makes working with OpenGL a lot simpler:
    The QGLWidget class is a widget for rendering OpenGL graphics.

    Read all about it: "QGLWidget docs":http://doc.qt.io/qt-5/qglwidget.html#details.[/quote]QGLWidget is deprecated. Use "QOpenGLWidget":http://doc.qt.io/qt-5/qopenglwidget.html instead.

    Also check out "VoltAir":http://blog.qt.io/blog/2014/07/21/google-labs-voltair-game-built-with-qt/ -- it is a game that Google built on top of Qt Quick.

  • Simple Qt/C++ games

    Unsolved
    67
    6 Votes
    67 Posts
    16k Views
    BondrusiekB

    Simple Ray Casting v2
    alt text
    Source code: https://github.com/Przemekkkth/simple-ray-casting-2-qt-cpp
    Gameplay: https://youtu.be/p9Ebbg9-ays

  • 0 Votes
    11 Posts
    199 Views
    8Observer88

    Place QLabel over QOpenGLWidget

    PySide6, Python:

    fe2ce83d-3eb7-4144-9459-751fa9c9c565-image.png

    main.py

    import sys from OpenGL.GL import (GL_COLOR_BUFFER_BIT, GL_SCISSOR_TEST, glClear, glClearColor, glDisable, glEnable, glScissor, glViewport) from PySide6.QtCore import Qt from PySide6.QtGui import QSurfaceFormat from PySide6.QtOpenGLWidgets import QOpenGLWidget from PySide6.QtWidgets import QApplication, QLabel class OpenGLWidget(QOpenGLWidget): def __init__(self): super().__init__() self.setWindowTitle("OpenGL ES 2.0, PySide6, Python") self.resize(380, 380) self.worldWidth = 200 self.worldHeight = 100 self.worldAspect = self.worldHeight / self.worldWidth surfaceFormat = QSurfaceFormat() surfaceFormat.setDepthBufferSize(24) surfaceFormat.setSamples(4) self.setFormat(surfaceFormat) self.scoreLabel = QLabel("Score: 0", self) self.scoreLabel.setStyleSheet("font-size: 24px;") def initializeGL(self): pass def resizeGL(self, w, h): deviceW = w * self.devicePixelRatio() deviceH = h * self.devicePixelRatio() deviceAspect = deviceH / deviceW if deviceAspect > self.worldAspect: self.viewportWidth = int(deviceW) self.viewportHeight = int(deviceW * self.worldAspect) self.viewportX = 0 self.viewportY = int((deviceH - self.viewportHeight) / 2) else: self.viewportWidth = int(deviceH / self.worldAspect) self.viewportHeight = int(deviceH) self.viewportX = int((deviceW - self.viewportWidth) / 2) self.viewportY = 0 def paintGL(self): glClearColor(0.2, 0.2, 0.2, 1) glClear(GL_COLOR_BUFFER_BIT) glViewport(self.viewportX, self.viewportY, self.viewportWidth, self.viewportHeight) glScissor(self.viewportX, self.viewportY, self.viewportWidth, self.viewportHeight) glClearColor(0.04, 0.62, 0.48, 1) glEnable(GL_SCISSOR_TEST) glClear(GL_COLOR_BUFFER_BIT) glDisable(GL_SCISSOR_TEST) self.scoreLabel.move(self.viewportX / self.devicePixelRatio() + 10, self.viewportY / self.devicePixelRatio() + 10); if __name__ == "__main__": QApplication.setAttribute(Qt.ApplicationAttribute.AA_UseDesktopOpenGL) app = QApplication(sys.argv) w = OpenGLWidget() w.show() sys.exit(app.exec())

    Qt6, C++:

    e6099583-2553-492d-965e-a9f63d9f4aeb-image.png

    main.cpp

    #include <QtGui/QOpenGLFunctions> #include <QtGui/QSurfaceFormat> #include <QtWidgets/QApplication> #include <QtWidgets/QLabel> #include <QtOpenGLWidgets/QOpenGLWidget> class OpenGLWidget : public QOpenGLWidget, private QOpenGLFunctions { public: OpenGLWidget() { setWindowTitle("OpenGL ES 2.0, Qt6, C++"); resize(380, 380); QSurfaceFormat surfaceFormat; surfaceFormat.setDepthBufferSize(24); surfaceFormat.setSamples(4); setFormat(surfaceFormat); m_pScoreLabel = new QLabel("Score: 0", this); m_pScoreLabel->setStyleSheet("font-size: 24px;"); } void initializeGL() override { initializeOpenGLFunctions(); } void resizeGL(int w, int h) override { int deviceW = w * devicePixelRatio(); int deviceH = h * devicePixelRatio(); float deviceAspect = deviceH / (float) deviceW; if (deviceAspect > m_worldAspect) { m_viewportWidth = deviceW; m_viewportHeight = (int) deviceW * m_worldAspect; m_viewportX = 0; m_viewportY = (int) (deviceH - m_viewportHeight) / 2.f; qDebug() << deviceH << m_viewportHeight << m_viewportY; } else { m_viewportWidth = (int) deviceH / m_worldAspect; m_viewportHeight = deviceH; m_viewportX = (int) (deviceW - m_viewportWidth) / 2.f; m_viewportY = 0; } } void paintGL() override { glClear(GL_COLOR_BUFFER_BIT); glClearColor(0.2, 0.2, 0.2, 1); glClear(GL_COLOR_BUFFER_BIT); glViewport(m_viewportX, m_viewportY, m_viewportWidth, m_viewportHeight); glScissor(m_viewportX, m_viewportY, m_viewportWidth, m_viewportHeight); glClearColor(0.04, 0.62, 0.48, 1); glEnable(GL_SCISSOR_TEST); glClear(GL_COLOR_BUFFER_BIT); glDisable(GL_SCISSOR_TEST); m_pScoreLabel->move(m_viewportX / devicePixelRatio() + 10, m_viewportY / devicePixelRatio() + 10); } private: const float m_worldWidth = 200.f; const float m_worldHeight = 100.f; float m_worldAspect = m_worldHeight / m_worldWidth; int m_viewportX; int m_viewportY; int m_viewportWidth; int m_viewportHeight; QLabel *m_pScoreLabel; }; int main(int argc, char *argv[]) { QApplication::setAttribute(Qt::ApplicationAttribute::AA_UseDesktopOpenGL); QApplication app(argc, argv); OpenGLWidget w; w.show(); return app.exec(); }

    qlabel-over-qopenglwidget-opengles2-qt6-cpp.pro

    QT += core gui openglwidgets widgets win32: LIBS += -lopengl32 CONFIG += c++17 SOURCES += \ main.cpp

    It doesn't work on WebAssembly: see demo. Because of this bug: https://bugreports.qt.io/browse/QTBUG-120651 But you can use the patch from the "Gerrit Reviews" (read the comments on the bug report)

    But it works on Android:

    ada173ff-cfc0-4a44-86a5-be4e530c7cc7-image.png

    f7c0e069-3337-4391-8232-cf0676306689-image.png

  • Steam overlay in Qt game

    Solved
    7
    0 Votes
    7 Posts
    174 Views
    SGaistS

    @slymas glad you found out and thanks for sharing ! :-)

  • Smooth character movement

    Unsolved
    27
    0 Votes
    27 Posts
    9k Views
    8Observer88

    I added the next comment to the bug report: https://bugreports.qt.io/browse/QTBUG-123862

    Try to run my example on macOS and Linux. Maybe it is a Windows issue. But requestAnimationFrame works perfectly smoothly on Windows: https://plnkr.co/edit/DebSXYMQ6TlgC7KT?preview It has a fixed 60 FPS, which means that the load on the processor is minimal.

    The worst result was with swapInterval=1, which I had at the beginning (I had not tried other values before). swapInterval with 0 and 10 is better, but not as good as requestAnimationFrame in JavaScript: https://plnkr.co/edit/B5t34XdK3MVi1WNb?preview (it is just a translation animation). I attached a source code "simple-translation-animation" (without rotation and scale animations). I attached EXE files for swapInterval = 0, swapInterval = 1, and swapInterval = 10:

    swapInterval = 0 - simple-translation-animation-opengles2-qt6-cpp-win10x64-exe-swap-interval-0.zip swapInterval = 1 - simple-translation-animation-opengles2-qt6-cpp-win10x64-exe-swap-interval-1.zip swapInterval = 10 - simple-translation-animation-opengles2-qt6-cpp-win10x64-exe-swap-interval-10.zip

    4623e1c6-0872-494d-881f-3b9677f8c17c-image.png

  • 0 Votes
    2 Posts
    83 Views
    8Observer88

    I opened a source code of getScaling and saw how scaling is calculated there: https://glmatrix.net/docs/mat4.js.html#line1197

    export function getScaling(out, mat) { let m11 = mat[0]; let m12 = mat[1]; let m13 = mat[2]; let m21 = mat[4]; let m22 = mat[5]; let m23 = mat[6]; let m31 = mat[8]; let m32 = mat[9]; let m33 = mat[10]; out[0] = Math.hypot(m11, m12, m13); out[1] = Math.hypot(m21, m22, m23); out[2] = Math.hypot(m31, m32, m33); return out; }

    I made the same with qHypot

    #include <QtGui/QMatrix3x3> #include <QtGui/QMatrix4x4> #include <QtGui/QOpenGLFunctions> #include <QtGui/QQuaternion> #include <QtMath> #include <QtOpenGL/QOpenGLWindow> #include <QtWidgets/QApplication> #include <QtWidgets/QWidget> class OpenGLWindow : public QOpenGLWindow, private QOpenGLFunctions { public: OpenGLWindow() { setTitle("OpenGL ES 2.0, Qt6, C++"); resize(350, 350); QMatrix4x4 matrix; matrix.translate(20.f, 80.f, 0.f); matrix.rotate(-90.f, QVector3D(0.f, 0.f, 1.f)); matrix.scale(20.f, 20.f); qDebug() << "Transformation matrix: " << matrix; // Output: 0, 20, 0, 20, // -20, 0, 0, 80, // 0, 0, 1, 0, // 0, 0, 0, 1 // "QMatrix4x4" has a row-major order // Get scaling float sx = qHypot(matrix.row(0)[0], matrix.row(1)[0], matrix.row(2)[0]); float sy = qHypot(matrix.row(0)[1], matrix.row(1)[1], matrix.row(2)[1]); float sz = qHypot(matrix.row(0)[2], matrix.row(1)[2], matrix.row(2)[2]); QVector3D scaling(sx, sy, sz); qDebug() << "Scaling:" << scaling; // Output: QVector3D(20, 20, 1) // Get rotation QMatrix3x3 rotationMatrix; rotationMatrix.data()[0] = matrix.column(0)[0] / sx; rotationMatrix.data()[1] = matrix.column(0)[1] / sy; rotationMatrix.data()[2] = matrix.column(0)[2] / sz; rotationMatrix.data()[3] = matrix.column(1)[0] / sx; rotationMatrix.data()[4] = matrix.column(1)[1] / sy; rotationMatrix.data()[5] = matrix.column(1)[2] / sz; rotationMatrix.data()[6] = matrix.column(2)[0] / sx; rotationMatrix.data()[7] = matrix.column(2)[1] / sy; rotationMatrix.data()[8] = matrix.column(2)[2] / sz; QQuaternion rotation = QQuaternion::fromRotationMatrix(rotationMatrix); qDebug() << "Rotation:" << rotation; // Output: QQuaternion(scalar:0.707107, vector:(0, 0, -0.707107)) // Get translation float tx = matrix.row(0)[3]; float ty = matrix.row(1)[3]; float tz = matrix.row(2)[3]; QVector3D translation(tx, ty, tz); qDebug() << "Translation:" << translation; // Output: QVector3D(20, 80, 0) } void initializeGL() override { initializeOpenGLFunctions(); glClearColor(0.2f, 0.2f, 0.2f, 1.f); } void paintGL() override { glClear(GL_COLOR_BUFFER_BIT); } }; int main(int argc, char *argv[]) { QApplication::setAttribute(Qt::ApplicationAttribute::AA_UseDesktopOpenGL); QApplication app(argc, argv); OpenGLWindow w; w.show(); return app.exec(); } QT += core gui opengl widgets win32: LIBS += -lopengl32 CONFIG += c++17 SOURCES += \ main.cpp

    P.S. The QMatrix4x4 constructor uses row-major order. The glMatrix fromValues method uses column-major order.

  • 1 Votes
    44 Posts
    2k Views
    8Observer88

    I solved the problem with the relative paths to the library! I just added -L before $$PWD like this:

    INCLUDEPATH += $$PWD/libs/fmod-2.2.21-mingw-64-bit/include LIBS += -L$$PWD/libs/fmod-2.2.21-mingw-64-bit/lib/x64 LIBS += -lfmod

    Now you can download the next example and run it in Qt Creator (with MinGW 64) without necessary to set up FMOD or changing the paths in pro-file: play-audio-from-resources-fmod-qt6-cpp.zip (2.51 MB)

  • 0 Votes
    13 Posts
    4k Views
    8Observer88

    I have the same question for WebAssembly: https://forum.qt.io/topic/155454/dealing-with-keyboard-layout-for-input-on-qt-webassembly

  • I want to study by distance learning, do you know Tech?

    Unsolved
    3
    0 Votes
    3 Posts
    180 Views
    No one has replied
  • 1 Votes
    30 Posts
    865 Views
    BondrusiekB

    @Michele-Rossi Hi. I see that this thread is extensive, but I would also like to express my opinion. When it comes to Qt and 3D, I can recommend you one chapter of the book Mastering Qt. Chapter 6 describes how to create a snake 3D game using QtQuick components and uses shaders and models. I think this is a good basis for writing something better later. Fortunately, there is a repository for this book and you can download and test the code. Link to the example: https://github.com/PacktPublishing/Mastering-Qt-5/tree/master/Chapter_06

  • 0 Votes
    4 Posts
    2k Views
    S

    Pro tip,

    always and I mean always be very specific with your Context attributes and with your OpenGL state.

    With ES2/ES3 the context state is manageable it gets bigger with the desktop GL unfortunately but I really recommend to always be very explicit with your state setting in the beginning.

    So for every draw you make, make sure you enable/disable set every state your current draw requires. that means your blending, your stencil, depth test, face culling etc.

    When everything works and you've encoded all this in your rendering code then you can very carefully start omitting redundant state sets.

    Incorrect state is a major source of OpenGL bugs.

    And to make everything what I said above easier, if you're writing your own engine type of thing you really want to accumulate as much state as possible, associate all that with your draw so that your draw takes your geometry, program, state objects and then does as much as possible to make sure the state is exactly what you need and the state that isn't mentioned in your application state is set to a known OpenGL state. For example if your draw doesn't use depth testing then you really want to mention in your code that your depth testing is disabled instead of relying on any implied "default" state in the driver.

    Example

    https://github.com/ensisoft/detonator/blob/master/device/opengles.cpp#L732

  • 1 Votes
    6 Posts
    226 Views
    8Observer88

    @SGaist Sorry for misleading you. It was not a question. Just a note.

  • Q: Qt - [c++] replacing material on a QEntity

    Solved
    3
    0 Votes
    3 Posts
    131 Views
    K

    good. thanks!

  • Q: Qt - [c++] Unknown OpenGL error

    Unsolved
    2
    0 Votes
    2 Posts
    121 Views
    K

    Basically, this is the code, at which the error occurrs:
    (But it is strange, because this happens indeterministic, or at least quite random after some time... the scene got recreated several times, without an error)
    I am confident, that i destroyed oll my entities and components, before the scene gets recreated again.

    ... auto* transparentTileMesh = new Qt3DExtras::QCuboidMesh; transparentTileMesh->setXExtent(1); transparentTileMesh->setYExtent(1); transparentTileMesh->setZExtent(0.001f); auto *transparentEntity = new Qt3DCore::QEntity(_root); transparentEntity->addComponent(transparentTileMesh); Qt3DCore::QTransform *transparentScaleTransform = new Qt3DCore::QTransform; transparentScaleTransform->setScale3D(QVector3D(1,1,1)); transparentScaleTransform->setTranslation(QVector3D(xPos, yPos, zPos + 0.125)); transparentEntity->addComponent(transparentScaleTransform); Qt3DRender::QMaterial* material = new Qt3DExtras::QPhongAlphaMaterial; material->setAmbient(color); material->setDiffuse(color); material->setShininess(shininess); material->setSpecular(specular); material->setAlpha(alpha); material->setSourceAlphaArg(Qt3DRender::QBlendEquationArguments::DestinationColor); ... // this is the function that may cast an error void GeometryObject::setTransparentTexture(Qt3DRender::QMaterial* texture) { if (material!= nullptr) transparentEntity->removeComponent(material); material = texture; transparentEntity->addComponent(material); }

    cheers, kevin

  • 0 Votes
    6 Posts
    195 Views
    JonBJ

    @kevin_d It needs repainting because it was (partially) obscured and now needs to be shown fully again, normal windows behaviour.....

  • 0 Votes
    7 Posts
    261 Views
    Christian EhrlicherC

    @kevin_d said in Q: Qt - [c++] toolTip padding gets lost when showing second time.:

    Good, that I know it is not solvable atm.

    QTBUG-119752 fixed the problem - it works fine for me with Qt 6.8

  • Q: Qt - [c++] texttospeech is not working when QSound plays

    Unsolved
    7
    0 Votes
    7 Posts
    237 Views
    SGaistS

    QSound being asynchronous, you would need to pole its state using the isFinished function and then start the next audio item.

  • How to save the state of qml file using c++

    Unsolved
    9
    0 Votes
    9 Posts
    395 Views
    jeremy_kJ

    @arlyn123 said in How to save the state of qml file using c++:

    @jeremy_k how can I use a connection to actually restore the window that I want to save and to make the loader to still open HomeScreen.qml?

    You might find Loader.setSource(url source, object properties) useful to specify the component to load as well as its properties to restore.

  • 0 Votes
    3 Posts
    260 Views
    johngodJ

    @julienchz
    Hi
    I have created some opengl tutorials check here: https://bitbucket.org/joaodeusmorgado/opengltutorials/src/master/
    I am using QOpenGLWidget, but I use mostly raw opengl, you could easily create a abstract render class, and then reuse it to QOpenGLWidget, or any other frame work of your choice render class.
    Hope it helps

  • This topic is deleted!

    Unsolved
    1
    0 Votes
    1 Posts
    6 Views
    No one has replied