Qt + OpenGl - Basics. Part 1
What a beginner will need:
1) Qt Creator (has good built-in documentation and tips while typing). DOWNLOAD
2) doc.qt.nokia.com - the official documentation in English
3) doc.crossplatform.ru - the documentation in Russian
4) Be sure to read about Qt and OpenGL
5) Great article to start learning
What we will do
Since this article is devoted specifically to the basics, our task will be as follows:
1) Disassemble how the application is created
2) How to draw objects
3) How to work with the mouse pointer and events (keystrokes on the keyboard and mouse)
4) Work with the timer
5) Create our first banal game. We will use the timer to randomly move the square. After pointing to the square of the pointer and clicking on it with the left mouse button, in the case of a square, we will add +1 to the points obtained.
Create a project
When you open Qt Creator, we begin to create a new project.
Select the Qt Widget project -> GUI Qt application.
In the Class Information section, uncheck the box to create the form.
As a result of the actions, we get a project with the files:
opengl.pro - necessary to compile our project
mainwindow.h - to declare all global data
main.cpp
mainwindow.cpp - methods of our program
Connecting libraries
In the * .pro file of your project, in the Qt + = line, you need to add opengl in order to enable the use of the opengl library. Other libraries are connected in the same way.
In the mainwindow.h file - if your default name is selected, you need to connect:
#include
#include
#include Predefining for us the necessary methods and variables
Open mainwindow.h
First of all, change:
class MainWindow: public QMainWindow
to
class MainWindow: public QGLWidget
This is because QMainWindow is a class for displaying a simple window, because we will work with opengl, we will need QGLWidget - this is a class for outputting graphics that implements the functions of the OpenGL library.
Now we will predefine variables and methods
protected:
int geese_size; // Сторона квадрата
int point; // набранные очки
int gdx, gdy; // Координаты квадрата
int cax, cay, cbx, cby; // Координаты курсора (текущие и начальные(при зажатии клавиши мыши) для выделение области)
int wax ,way; // Размеры окна нашей программы
bool singling; // Для выделение области, если true то рисуем прямоугольник по координатам cax, cay, cbx, cby
void self_cursor(); // метод для рисования своего курсора
void initializeGL(); // Метод для инициализирования opengl
void resizeGL(int nWidth, int nHeight); // Метод вызываемый после каждого изменения размера окна
void paintGL(); // Метод для вывода изображения на экран
void keyPressEvent(QKeyEvent *ke); // Для перехвата нажатия клавиш на клавиатуре
void mouseMoveEvent(QMouseEvent *me); // Метод реагирует на перемещение указателя, но по умолчанию setMouseTracking(false)
void mousePressEvent(QMouseEvent *me); // Реагирует на нажатие кнопок мыши
void mouseReleaseEvent(QMouseEvent *me); // Метод реагирует на "отжатие" кнопки мыши
void singling_lb(); // Рисуем рамку выделенной области
void geese(); // Рисуем квадрат по которому кликать для получения очков
We also have one slot, in order to count on the timer the new coordinates of the square to click on.
protected slots:
void geese_coord(); // Определяем координаты объектов
The principle of image construction
QGLWidget is so arranged that the first time the class is initialized, it automatically calls methods in the following order:
At startup: initializeGL () -> resizeGL () -> paintGL ()
When resizing a window: resizeGL () -> paintGL ()
updateGL () calls paintGL ()
initializeGL - must be used for global customization of image construction, which is not necessary to specify when building the frame.
resizeGL - is used to build the size of the window. If during the work the window size changes, but the viewing area does not change, then with an increase in size, unpredictable phenomena can be observed.
paintGL - this method will build each of our frames for display.
glClear(GL_COLOR_BUFFER_BIT); // чистим буфер
glMatrixMode(GL_PROJECTION); // устанавливаем матрицу
glLoadIdentity(); // загружаем матрицу
glOrtho(0,500,500,0,1,0); // подготавливаем плоскости для матрицы
// BlendFunc позволяет работать в альфа режиме, например если нам нужно указывать прозрачность
// glEnable(GL_BLEND);
// glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
qglColor(Qt::white); // Дальше рисуем белым цветом
// renderText позволяет писать текст на экран, так же можно указать различный стиль (читаем QFont)
renderText(10, 10 , 0, QString::fromUtf8("Вы набрали %1 очков:").arg(17), QFont() , 2000);
// glBegin и glEnd - обозначают блок для рисования объекта(начало и конец), glBegin принимает параметр того, что нужно рисовать.
glBegin(GL_POLYGON);
glColor4f(0,1,0, 0.25);// Цвет которым рисовать
glVertex2f(200, 300); // Точка 1 из 4 - отсчет по часовой стрелке
glVertex2f(300, 300);
glVertex2f(300, 400);
glVertex2f(200, 400);
glEnd();
swapBuffers();
Why double buffering
PaintGL does not immediately draw a picture on the screen, but writes it to the buffer, and upon request, swapBuffers () replaces the current image with what appeared in the buffer. By itself, buffering allows you to more correctly replace the image so that there are no jumps on the screen.
Mouse click events
mousePressEvent () - the method is automatically called when the mouse is pressed. In the transmitted parameters, you can get various information, for example, which button was pressed and at what point in the coordinates.
-This event in our example is used to determine where the mouse was clicked, then if our coordinates are in the square field, then add + 1 to our points and rebuild our frame.
- We also use it to determine the initial coordinates for selecting an area on the screen when you clamp and move the pointer.
Mouse Movement Event
mouseMoveEvent () - automatically called when the coordinates of the mouse pointer change. But there is one But, the default is setMouseTracking (false), so the event is fired only when the mouse buttons are pressed, so that the method is called even without clicking, you must setMouseTracking (true).
- We use this method to get the current position of the pointer, to rebuild the selection of the area or draw our own cursor.
Event when the mouse button is “pushed”
mouseReleaseEvent () - automatically called if the mouse button is depressed. It also accepts various parameters.
- In this case, we use the method to erase the area we selected from the screen.
Keyboard Key Event
keyPressEvent () - the method is called on an event when a button on the keyboard is pressed.
- In our example, we use this method in order to redefine the coordinates of our square and move it to a new location.
Timer
QTimer - allows us to create a stream that will listen to signals and run the corresponding slots.
- In this case, we create a timer that will wait 750ms after which it finishes its work by sending us the timeout () signal , but at the end of the signal we will not stop the work, but again start the slot to redefine the coordinates of the square that we need to click on in order to score points.
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(geese_coord()));
timer->start(750);
The task of this material for assimilation.
The ready-made code I laid out works, but with my homework I will modify the code so that when the game starts there will be a greeting, when you click on it, you will be given a minute to get points. After a minute, the number of points scored was displayed and it was proposed to play again.
The conclusion!
Most of the little written here in our first primitive game is simply not needed. But I want to note again: "This is an introductory article, designed to become familiar with Qt + OpenGL ." Also, if you notice programs written in this way can be compiled for any operating environment.
The finished version of the working code can be taken here:
View and download sources
Download the game for windows
Download the game for Linux
PS In the future, if not against, I will continue to write lessons. For example, the next lesson, we will create a game with shooting for example in ducks.
If you have questions - write in the comments or in PM.