Privacy policyContactsAbout siteOpinionsGitHubDonate
© EVILEG 2015-2018
Recommend hosting
TIMEWEB

How to make game using Qt - Lesson 1. Control of object

GameDev, getasynckeystate, QGraphicsItem, QGraphicsScene, Qt, WinAPI, написать игру

With this lesson begins a series of articles on how to write a play on Qt. In the previous article it was told about the system of positioning of graphical elements QGraphicsItem in the graphic scene QGraphicsScene . It was painted a triangle and placed in the center of the graphic scenes, the dimensions of which were 500 by 500 pixels. And now it is time to revive this triangle, but rather to begin to control it.

We make technical lesson assignment:

  • A graphic scene is located in the Window with dimensions of 500 by 500 pixels (this is already done in the previous lesson);
  • In the center of the graphic scene is a red triangle (which also has been done in the previous lesson);
  • The triangle should move when you press the Up arrow, Down, Left, Right;
  • Triangle should not go beyond a graphic scene, that is, should be limited by the size of the graphic scene.

Note. This project uses of WinAPI, so the project is suitable for use in the Windows operating system, but only algorithm that is used in this lesson is applicable to Linux and MacOS. So if you want to write a game for these operating systems, you will need to use the library of the OS for asynchronous processing keystrokes.

Project Structure

  • Triangle.pro - profile project, created by default, and in this project does not require korrektirovaki;
  • main.cpp - the file from which you start the application, the file is called a widget, which will be located in the graphic scene with a triangle, which we will manage;
  • widget.h - header file, called a widget with a graphic scene;
  • widget.cpp - File widget source code;
  • triangle.h - header file class Triangle, which is inherited from QGraphicsItem;
  • triangle.cpp - class source code file Triangle.

mainwindow.ui

The interface design simply throws QGraphicsView in the widget. Nothing more is required.

widget.h

This file is only to declare a graphical scene, the triangle object, which will manage, as well as a timer counts on which to test the state of the keyboard keys, we'll manage the triangle on the graphic scene.

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QGraphicsScene>
#include <QShortcut>
#include <QTimer>

#include <triangle.h>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

private:
    Ui::Widget      *ui;
    QGraphicsScene  *scene;     /// We declare a graphic scene
    Triangle        *triangle;  /// and triangle
    QTimer          *timer;     /* We declare the game a timer, 
                                 * by which will be changing the position of an object 
                                 * on the stage when exposed to the keyboard keys
                                 * */
};

#endif // WIDGET_H

widget.cpp

This file initializes the graphic scene, and its size, in a graphical scene rendered the field border, where a triangle will move. But the key point is to initialize a timer signal processing of which will be made changes in the state of graphic scenes, and will change the coordinates of the triangle position, tracking the state of the keyboard keys.

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    this->resize(600,600);          /// Defining the size of the widget, ie the window
    this->setFixedSize(600,600);    /// Fix a widget sizes

    scene = new QGraphicsScene();   /// Initialize the graphics scene
    triangle = new Triangle();      /// Initialize triangle

    ui->graphicsView->setScene(scene);  /// Set the graphic scene in qgraphicsView
    ui->graphicsView->setRenderHint(QPainter::Antialiasing);    /// Install anti-aliasing
    ui->graphicsView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); /// Disable scroll vertically
    ui->graphicsView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); /// Disable scroll horizontally

    scene->setSceneRect(-250,-250,500,500); /// Set the graphic scenes

    scene->addLine(-250,0,250,0,QPen(Qt::black));   /// Adding a horizontal line through the center
    scene->addLine(0,-250,0,250,QPen(Qt::black));   /// Add a vertical line through the center 

    /* In addition, we draw a limited area in the graphic scene */
    scene->addLine(-250,-250, 250,-250, QPen(Qt::black));
    scene->addLine(-250, 250, 250, 250, QPen(Qt::black));
    scene->addLine(-250,-250,-250, 250, QPen(Qt::black));
    scene->addLine( 250,-250, 250, 250, QPen(Qt::black));

    scene->addItem(triangle);   /// Adding to the scene triangle
    triangle->setPos(0,0);      /// Set the triangle in the center of the stage

    /* Initialize the timer and call processing slot timer signal from Triangle 20 times per second. 
     * By controlling the speed counts, respectively, 
     * control the speed of change in the state of graphic scenes
     * */
    timer = new QTimer();
    connect(timer, &QTimer::timeout, triangle, &Triangle::slotGameTimer);
    timer->start(1000 / 50);
}

Widget::~Widget()
{
    delete ui;
}

triangle.h

And now we proceed to the program code that is responsible for the graphic object, which we will operate. The class inherits from QObject to work with signals and slots , as well as QGraphicsItem .

#ifndef TRIANGLE_H
#define TRIANGLE_H

#include <QObject>
#include <QGraphicsItem>
#include <QPainter>
#include <QGraphicsScene>

/* Connect the library is responsible for the use WinAPI. 
 * This library is required to check the status of asynchronous keys
 * */
#include <windows.h>

class Triangle : public QObject, public QGraphicsItem
{
    Q_OBJECT
public:
    explicit Triangle(QObject *parent = 0);
    ~Triangle();

signals:

public slots:
    void slotGameTimer();

protected:
    QRectF boundingRect() const;
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);

private:
    qreal angle;    // The angle of rotation of the graphic object

};

#endif // TRIANGLE_H

triangle.cpp

Drawing a triangle is taken from the previous lesson on the positioning of graphical elements in the graphic scene, but redrawing in a slot that will handle the signal from the timer, and the initialization of the primary rotation of the object has a new piece of code.

Rotate an object is given in degrees of variable angle and set setRotation() function, which was inherited from QGraphicsItem . Also for monitoring the status of the keyboard keys used by the function of the WinAPI , namely GetAsyncKeyState() , which is the code button determines the state of the button itself. Each signal from QTimer class object is checked keystrokes and changing the position of the triangle depending on their condition.

#include "triangle.h"

Triangle::Triangle(QObject *parent) :
    QObject(parent), QGraphicsItem()
{
    angle = 0;     
    setRotation(angle);    
}

Triangle::~Triangle()
{

}

QRectF Triangle::boundingRect() const
{
    return QRectF(-25,-40,50,80);  
}

void Triangle::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
        QPolygon polygon;   //
        
        polygon << QPoint(0,-40) << QPoint(25,40) << QPoint(-25,40);
        painter->setBrush(Qt::red);    
        painter->drawPolygon(polygon);  
        Q_UNUSED(option);
        Q_UNUSED(widget);
}

void Triangle::slotGameTimer()
{
    /* Alternately checks for key presses
     * using the asynchronous reception state of the keys
     * is provided WinAPI
     * */
    if(GetAsyncKeyState(VK_LEFT)){
        angle -= 10;        // Set turn 10 degrees to the left
        setRotation(angle); // Rotate object
    }
    if(GetAsyncKeyState(VK_RIGHT)){
        angle += 10;        // Set turn 10 degrees to the right
        setRotation(angle); // Rotate object
    }
    if(GetAsyncKeyState(VK_UP)){
        setPos(mapToParent(0, -5));     /* Move the object 5 pixels forward to retranslate them
                                         * in the coordinate system of the graphic scene
                                         * */
    }
    if(GetAsyncKeyState(VK_DOWN)){
        setPos(mapToParent(0, 5));      /* Move the object 5 pixels backward to retranslate them
                                         * in the coordinate system of the graphic scene
                                         * */
    }

    /* Check output of bounds. If the subject is beyond the set boundaries, then return it back
     * */
    if(this->x() - 10 < -250){
        this->setX(-240);       // left
    }
    if(this->x() + 10 > 250){
        this->setX(240);        // right
    }

    if(this->y() - 10 < -250){
        this->setY(-240);       // top
    }
    if(this->y() + 10 > 250){
        this->setY(240);        // bottom
    }
}

Примечание

To ensure that the project is compiled with MSVC build a set, add the following lines to pro project file:

win32-msvc*{
    LIBS += -luser32
}

Result

As a result of this work we have made first steps to ensure that the write off. Namely learned to control the object, that is, our hero-triangle, with whom we also work in future lessons on writing our first game.

A full list of articles in this series:

Video

10% refund of hotel reservation amount on Booking
10% refund of hotel reservation amount on Booking
We offer a link with a 10% return on the amount of the order when booking a hotel through Booking
M

Добрый день,
Подскажите пожалуйста, чем может быть вызвана ошибка
"C:\Android\Qt\Mark\untitled4\triangle.cpp:5: ошибка: undefined reference to `vtable for Triangle'" ?
В конструкторе указывает на наследуемый класс QGraphicsItem и деструктор Triangle.
Я сначала пытался код сам исправить, но ничего не вышло и я просто скопировал Ваш.
Скопировал triangle.h и triangle.cpp.
Что это может быть?

Отвратительная ошибка на самом деле.

В одном случае достаточно прописать Q_OBJECT.
В другом случае достаточно удалить build и пересобрать проект.
Один раз пришлось пересоздавать проект с нуля.
Проблема в том, что какие-то таблицы мок-файлов портятся. До сих пор порой до конца не понимаю, из-за чего такая проблема происходит. Иногда случается из-за добавления новых файлов в проект.
M

Вы как всегда правы, удалить билд и перезапустить было решением проблемы

Comments

Only authorized users can post comments.
Please, Log in or Sign up
МБ
April 21, 2019, 9:40 a.m.
Моисей Бушуев

Qt - Test 001. Signals and slots

  • Result:0points,
  • Rating points-10
AA
April 17, 2019, 7:40 p.m.
Anton Ablin

Qt - Test 001. Signals and slots

  • Result:73points,
  • Rating points1
E
April 17, 2019, 6:16 p.m.
Evgeny

Qt - Test 001. Signals and slots

  • Result:100points,
  • Rating points10
Last comments
April 21, 2019, 4:22 p.m.
Евгений Легоцкой

Через метод setIcon table.horizontalHeaderItem(0).setIcon("qrc://path/to/icon.png")
April 21, 2019, 3:48 p.m.
Евгений Легоцкой

Добрый день! Спасибо за комментарий. Там действительно лучше будет сделать с инициализацией по умолчанию.
U
April 18, 2019, 3:37 p.m.
Unreal_man

А как иконку в хедер задать?
u
April 18, 2019, 2:15 a.m.
uaa

доброго времени,большое спасибо за пример для начинающего)при адаптации к своему проекту столкнулся с таким ньансом:в vepolyline.h в 47 строке нужна инициализация по умолчанию: int m_pointF...
E
April 11, 2019, 12:49 p.m.
Evgeny

Спасибо за ответ) У меня компоновщик на нее ругался просто. Оказалось, просто забыл Q_OBJECT в начале класса указать.
Now discuss on the forum
April 24, 2019, 11:22 a.m.
Ruslan Polupan

Согласен. но ситуация не поменялась. Такое чуство что данные не записываются в модель.
April 24, 2019, 6:20 a.m.
Ruslan Polupan

я так понимаю надо инфорация об устройствах.Я бы пробовал так rust@suse:~> lsblk -PNAME="sda" MAJ:MIN="8:0" RM="0" SIZE="111,8G" RO="0" TYPE="disk" MOUNTPOINT=""NAME="sda1" MAJ:MIN="8...
April 21, 2019, 4:16 p.m.
Евгений Легоцкой

Приветствую Нужно сохранять где-то выбранное значение, а потом восстанавливать его. Или использовать QSettings или добавить метод open(), в который передавать начальные значения для того...
R
April 19, 2019, 9:55 a.m.
RED_Spider

мені важко це зараз навіть перевірити, тому що знайшов коміт, це ще було в 2016 році, і цей код не буде працювати коректно зараз, єдине скажу що це були QThread
Join us in social networks

For registered users on the site there is a minimum amount of advertising