9

I'm developing a game with QtQuick 2 (Qt5.2) QML and C++. I want most of the game-logic in C++ (I don't want to do it with JS), and I'm trying to use QStateMachines for a lot of the logic.

Now my question is, how do I implement a proper game-loop in that scenario?

The game has for example objects that are moving from and to certain waypoints on the screen, so I think I can't do everything state/event-based. At some point I need to say "my object should move 10 pixels in direction x every second". So for example when my object is in its state "moving", it should move by a certain amount every second and then of course check for some conditions if it has to switch the state (e.g. to "attacking").

Now all the demos in the Qt-examples and on the web seem to be either fully event-based (e.g. four-in-a-row-wins-like) or written in JavaScript. So I am a bit lost here.

One idea I could find was to create a QTimer with a timer of e.g. 30ms and connect that QTimer's timeout() signal to an advance() slot of every moving object, and start that timer before 'return app.exec();'. Like this:

QTimer timer;
QObject::connect(&timer, SIGNAL(timeout()), &scene, SLOT(advance()));
timer.start(1000 / 33);
return app.exec();

and then each object (e.g. the Mouse) has a

void Mouse::advance(int step)

However, this requires a QGraphicsScene and I'm not sure how well that goes with a QtQuick/QML project on Android/iOS.

Is that a good solution? Or is my view of the problem somehow wrong and I don't need a game loop to accomplish my goal?

The solution shouldn't use any desktop-only stuff from Qt, i.e. it should work on Android, iOS and desktops.

Ela782
  • 5,041
  • 5
  • 53
  • 66

2 Answers2

9

That's the way to go: QTimer. Here you find some detailed example on it:

  • A typical loop for game in Qt:

    int main(int argc, char* argv[]) { 
    //    init stuff
            while(game.isRunning()) {
                    a.processEvents(); //(a is a QApplication created during the init, should use a better name i guess)
                    QTime currentTime= QTime::currentTime();
                    int timeSinceLastUpdate = lastUpdate.msecsTo(currentTime);
                    while(timeSinceLastUpdate>updateTimeStep){
                            game.update();
                            timeSinceLastUpdate-=updateTimeStep;    
                            lastUpdate=lastUpdateaddMSecs(updateTimeStep);
                    }
                    renderer.setInterpolateFraction(static_cast<float>(timeSinceLastUpdate)/static_cast<float>updateTimeStep);
                    renderer.renderGameObjects();
                    renderer.renderGUI();
                    renderer.swap();    
            }
            a.exit();
            return 0; 
    }
    

Source: Game loop in Qt

That's should be enough info for you to get started.

plasmacel
  • 8,183
  • 7
  • 53
  • 101
  • 1
    Hm, here http://qt-project.org/forums/viewthread/18783 people suggest using processEvents() is bad style. What about a solution like here http://qt-project.org/doc/qt-4.8/graphicsview-collidingmice.html ? I'll update my question in a second to include a short example. – Ela782 Mar 02 '14 at 10:55
  • Did you checked the video? – Daniela Martínez Mar 02 '14 at 12:13
  • Do you mean the youtube video you linked by Jamie King? Yes, and I don't particularly think this guy uses good coding practices, so I don't really trust this guy on telling me how to do things properly. I'm not so sure firing that timer as often as possible is a good idea, and you don't even know the time interval between firings if you do it like this. That's why I ask for a good and proper solution here. – Ela782 Mar 02 '14 at 13:12
  • 1
    I don't think your game loop is correct Qt game loop. And the source you cite is indeed a SDL-based game loop transliterated to Qt without using any of the advanced tools Qt provides. And you also use 100% CPU with that construct, so Im downvoting it. – Ariel M. Jan 08 '16 at 19:30
  • 4
    @ArielM. - Instead of down voting, you could provide a better answer with more detailed solution, links, tutorial, or example. That would a smarter way to contribute in the discussion. – Daniela Martínez Feb 25 '16 at 23:19
2

Usual game loop of simple game can look like this (not sure if I understand you correctly though).

Each class that represents game object have 2 public methods: update(); and render(); On each call of QTimer object you iterate over all game objects and call their update method. After it you repeat the same for render method();

In update methods each object decides what to do on game map (move/shot/stand/...) and changes its coordinates/properties. In render methods each object just draws itself on display.

str14821
  • 243
  • 1
  • 10