This is one of the things that still confuses me about QML / QtQuick: How shall I implement a simple game like pong that uses a loop?
I googled a bit and looked through similar questions here but none of them addressed the following:
I want to create a simple game like pong that uses a loop. In this loop first all the objects are updated (in case of pong the ball and the bars) and then everything is rendered. For the rendering part I think QML will do the job once all the properties are set.
I want to use QML and QtQick and not QGraphicsScene.
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.
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.
I had a similar question when I first started with Qt and got the same answers you're getting (which are correct). It's a different way of thinking than if you had come from using say, SDL.
I want to add an approach that lets you have some control over the updates. It's been a while since someone shared this with me, but from what I remember, it has something to do with ensuring a consistent update frequency.
Regardless of whether or not it's an improvement over just using a simple timer or not, having some actual code will help get you started. In addition, having the delta (to calculate the position of the ball and paddles) is something you'd have to do yourself, which this code already does for you.
Here's the meat of 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;
}
}
It's used in C++ like 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);
}
}
}
Since this example (quickpather) is QML-based, it has a complex setter for connecting to the timer. If you don't need stuff to be in QML like the example is, you can just create the timer in C++ and connect to its update signal directly wherever necessary:
connect(mTimer, &GameTimer::updated, foo, &MyGameObject::update);
// ...
connect(mTimer, &GameTimer::updated, bar, &MyOtherGameObject::update);
The delta is in seconds (1.0 == one second).
You can take anything you need from the example to help you get started with your game.
To answer some of your questions directly:
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.
I wouldn't recommend doing the logic in QML/JavaScript as this game does. C++ is better suited to this (aka faster) than JavaScript. Things like scripting are well suited for JavaScript though.
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.
My "engine" uses C++ for all of the logic (except scripts, which are kept relatively small) and QML for the GUI and also the entities (animations, sprites, etc.).
I don't think there's any documentation about this exact topic (games written in C++ with QML frontends), but there are some QML-based game examples:
http://doc.qt.io/qt-5/qtquick-demos-maroon-example.html
http://doc.qt.io/qt-5/qtquick-demos-samegame-example.html
You don't need a game loop in QML, the whole thing is event driven and powered by an underlying event loop anyway.
You can readily tap into that, use timers, signals, animations and what not out of the box.
Game loop are locking in nature. And in QML you can only use the main thread. And thou shalt not lock the main thread - it has to spin or your app will stop responding.
Related
I am using Qt to build a ray tracer with GUI. The ideal effect is to paint a pixel immediately after computing the RGB value of that pixel, as in most professional renderer. But I find out that my tracer could only display the entire rendered image after the loop below:
for(int i=0; i<row; ++i)
for(int j=0; j<column; ++j) {
compute pixel value;
painter.drawPoint(i, j);
}
I am drawing to the central widget of the mainwindow. I reimplemented QWidget paintEvent function and put the loop above in this function. It seems that paintEvent only display the whole screen after being executed once and in the process it gives me this:
I don't know if this is just how paintEvent works or I am doing something wrong.
Anyway, it cannot display pixel in real time. And this is very unsatisfying for an interactive tracer. I hope you guys can provide some explanations and/or solutions. A million thanks!
The OS is giving you the "not responsive" alert because you are doing all the calculation in the GUI thread.
This means that the event loop is stuck at doing your havy calculations and can't process other events.
On a Windows system, this means it won't react to Windows messages. That's why after a certain time the OS tells you that the application is not responsive.
You should perform your heavy calculations in a separated thread, pass the results to the GUI thread when you want to update the GUI and let the GUI thread perform the rendering.
Apart from that, you should consider painting to a backbuffer, as suggested in the comments (although please note that QPixmap is not thread safe).
QPainter::drawPoint() is very slow and it is an unefficient way to paint the whole central area.
Please have a look at the documentation here for more details on how to keep the GUI responsive.
I'm porting over a OpenGL application from a win32 project to a Qt project.
In the win32 project I simply had a mainloop that kept executing the next frame as soon as the previous was finished.
In the tutorials I find about Qt and OpenGL, they're using timers to control the update of the scene. However, I'd like to render as many frames as frequent as possible - how to do that?
However, I'd like to render as many frames as frequent as possible - how to do that?
Not with Qt. Qt takes full control of the event loop thus not giving you any means of directly performing idle operations. The standard way to perform idle operations in Qt is to use a QTime with a timeout of 0.
Another possibility was using a second thread just for OpenGL operations. However to work reliably you should create a dedicated OpenGL context for that one thread.
Qt simply is not the right toolkit for those kinds of program where the primary task of the main loop is rendering pictures and input and event management are only secondary.
Try calling update() at the end of your paint handler.
That will queue up another repaint event.
The intrinsic principles of Qt and OpenGL are not about rendering as soon as possible, but it's rendering whenever we want (huge difference).
You have to ask for the system max framerate (search for samples in OpenGL i'm sorry I don't rememember where I saw that). Once you've done that, just create a timer based on this max framerate, so you'll get what you want.
However, I'd like to render as many frames as frequent as possible - how to do that?
Use QTimer with zero interval.
Sometimes I have to implement a feature like customized drag & drop. The code may goes like this:
bool mouse_down = false;
Vec2 mouse_pos;
void on_mouse_down() {
mouse_down = true;
mouse_pos = cursor_pos();
}
void on_mouse_move() {
if(mouse_down) {
Vec2f c = cursor_pos();
Vec2f d = c - mouse_pos;
// dragging. make objects tracing the cursor.
// ...
}
}
void on_mouse_up() {
mouse_down = false;
// dropped
// ...
}
I know this works fine, but I donnot like redundant variables and separated procedures for something like this at all. In IP(imperative programming) maybe it's unavoidable; my question is, is there a better way to deal with this kinda thing in FP(functional programming)? Any ideas and suggestions are appreciated, no matter whatever programming languages, Lisp, Scheme, F#, Ruby, etc. or some better way to do this in IP?
Since nobody attempted an answer for a day, I'll give it a shot. I understand the problem that you are discussing, but the answer should likely depend on the operating system, language and its runtime library.
The general idea would be that when mouse goes down, you spawn off an asynchronous computation. This computation "blocks" on events, and processes them in its own loop as fetched, doing what you need to do; it exists when the mouse button does up. While this looks like it works like an imperative thread, in reality, when the computation gets "blocked", it just yields control to where it was started from (the main GUI thread invoking the mouse down event, presumably). In such a way, the state is encapsulated into what looks like a lexically local scope of the computation. That magic has to be handled by the runtime of the language, so this is as far as we can get with the answer in a language ans OS-agnostic way.
As for an example of such implementation, check this answer and an article by Tomas Petricek, both discussing your question but in a narrow setting of Windows, .NET and F#. There is a book by the same Perticek, Real World Functional Programming: With Examples in F# and C#, where the same ideas are expressed, surprisingly, in C#, not usually regarded a functional language. Chapter 16, if my memory serves me, is yours.
As for encapsulating the state in an IP/OO language program, you can create an instance of a class in your mouse_down handler. The instance would register itself with the runtime to receive other mouse and UI events, process them, do all the work and, when needed (mouse goes up or the windowing system cancels capture mode), unregisters and destroy itself. Not as elegant as a functional language would allow, but still much better that keeping mutable state in a general UI class.
i wan't to use Native OpenGL in the paint function of my widgets(QPainter), to improve performance.
i saw that there is function QPainter::begin/endNativePainting(), that can help me.
but i can't find examples for that...
i wanted to know if those functions are low cost, or evry use of them reduce performance?
2.can i define beginNativePainting() and endNativePainting(), in general for all the widgets i use, instead of using that in every paint function i have.
tnx for any help....
There is some basic example code right in the documentation: http://doc.qt.io/qt-4.8/qpainter.html#beginNativePainting
The functions themselves should be fairly low-cost, but calling them might still cause a noticeably overhead, because Qt has to flush its internal painting queue on the beginNativePainting() call and probably has to assume that everything is changed as soon as endNativePainting() is called.
For the second part I am not sure if I understand what you are aiming at. Basically if you have a QPainter object, you can call beginNativePainting() once. But you have to match it with an endNativePainting() call. So the usual place would be the paint() method.
Qt is using a range of OpenGL functionalities to implement its 2D painting, including custom shaders and various frame buffers. It puts OpenGL into a pretty messy state.
beginNativePainting / endNativePainting are there to allow Qt's drawing engine to save this context and retrieve it once the user is done drawing.
It would have been nice to have the xxxNativePainting methods do the contrary (i.e. automatically save and restore user configuration of OpenGL), but since Qt allows to call OpenGL primitives directly, saving the global state is nigh impossible without tons of code and potential serious performance hit.
Instead, these methods simply save Qt's internal OpenGL state and, rather than having user code start in a configuration that would be meaningless anyway (and likely to change with each new Qt release), reset OpenGL to a "neutral" state.
It means that, inside a begin/end section, you will start with a clean slate: no shader linked, no vertex array, most of global parameters reset, etc.
Contrary to a simple QGLWidget / PaintGL scenario where you can afford to setup the global OpenGL state once and for all and simply call the rendering primitives each frame, you will have to restore pretty much everything just after the call to beginNativePainting (link/bind your shaders, set global parameters, select and enable various buffers, etc).
It also means that you should use native painting sparringly. Having each single widget do custom painting might soon bring your rendering to its knees.
The new Animation Framework in Qt 4.6+ is based on QTimeLine which has 'void setUpdateInterval(int interval)' public function. Based on QTimeLine as well, QGraphicsItemAnimation could access this function, but the new animation framework classes (e.g. QPropertyAnimation) can't! Is the animation framework locked to the about 60 updates per second which corresponds to a pixel-by-pixel transition of 60 pixels on screen per second only (for QPropertyAnimation animating position property) or is there a way to increase this without reimplementing everything?
I think there are some hardware limitations and also some limits with how the OS/Qt handles some of the painting. The Qt Main Loop has something to do with it also.
In my experience, double buffering and repainting only the regions that need to be repainted will give you the smoother animations that you are looking for. Also make sure that your graphics are close to the size that you are actually painting them. Increasing the interval of refresh won't help most monitors because they don't refresh faster than 60 Hz.
Here is a link that may be helpful.
Qt works hard to optimize and get the graphics to look nice on a lot of platforms, and I know that as they are preparing for Qt 5, that there are some more changes to how the raster engine works.
I've also seen a demonstration similar to what is discussed here in person where they showed the frames per seconds of refreshes they could get with painting tiles in a game. Here is a link to a video discussing it. It goes into tweaking the performance of Qt for a particular game implementation, and what helps and what doesn't.
Here's my solution for Qt 4.8:
// You need qt source code to access QUnifiedTimer for QAnimationDriver
// Alternatively, copy'n'paste only the declaration for QUnifiedTimer class.
#include <qt/src/corelib/animation/qabstractanimation_p.h>
...
// In the animation thread, set the update timing interval.
// The smaller the interval, the more updates and more CPU consumption.
int animationTimingInterval = update_interval_in_msecs_u_want;
QUnifiedTimer::instance()->setTimingInterval(animationTimingInterval);