Fortsetzung des Themas, wie man ein Spiel in Qt schreibt. Nachdem die Fliege, die Äpfel frisst, in den vorherigen Artikeln erstellt wurde, ist es an der Zeit, einen Feind dafür zu schaffen. Und der Feind von Fly , wie Sie wissen, Spinne . Die Erstellung von Spielfiguren, die am unmittelbaren Leben Ihrer Hauptfigur teilnehmen, zeichnet nicht nur die Animation von Aktionen und Bewegungen sowie die Logik der Reaktionen auf die Aktionen des Spielers, sondern auch künstliche Intelligenz, deren Logik entsprechend das Verhalten der Spielfigur wird bestimmt. Somit geben wir dem Spiel eine neue Bedeutung, nicht nur möglichst viele Äpfel zu essen, sondern auch um jeden Preis zu überleben.
Lassen Sie uns das Verhalten Spider in dieser Version des Spiels definieren. Was sollte er tun? Ja, die häufigste aller Aktionen ist die Jagd auf Fliege , jage sie einfach über das Spielfeld.
Wir werden dem Spiel auch eine Schaltfläche hinzufügen, um das Gameplay zu starten und anzuhalten, und das Wichtigste, was wir hinzufügen werden, ist Game Over.
Feind der Fliege in der Projektstruktur
Wie bei Fly wird der Projektstruktur eine zusätzliche Klasse hinzugefügt, die für das Objekt Spider verantwortlich ist.
- Spider.h - Header-Datei der Klasse, die für den Spider verantwortlich ist
- Spider.cpp - Quelldatei verantwortlich für Spider
spinne.h
Der Unterschied zwischen dieser Datei und der Heading-Datei einer Fliege besteht darin, dass darin ein Spieltimer deklariert ist, der für das Verhalten der Spinne verantwortlich ist, also der Feind der Fliege getaktet wird nicht vom Timer im Kern des Spiels, sondern von seinem eigenen internen Timer. Auch wenn die Spinne initialisiert wird, wird ihr Ziel, dh Fly , in sie gelegt, dem sie unermüdlich folgt. Künstliche Intelligenz ist in diesem Fall unverschämt primitiv, mehr braucht es derzeit aber nicht.
#ifndef SPIDER_H #define SPIDER_H #include <QObject> #include <QGraphicsItem> #include <QGraphicsScene> #include <QPainter> #include <QTimer> #include <QDebug> class Spider : public QObject, public QGraphicsItem { Q_OBJECT public: explicit Spider(QGraphicsItem * target, QObject *parent = 0); ~Spider(); void pause(); // Сигнал для инициализации паузы signals: void signalCheckGameOver(); // Сигнал на вызов состояния Game Over public slots: protected: QRectF boundingRect() const; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); private: qreal angle; // Угол поворота графического объекта int steps; // Номер положения ножек паука int countForSteps; // Счетчик для изменения полоэения ножек QTimer *timer; // Внутренний таймер паука, по которому инициализируется его движение QGraphicsItem * target; // Цель паука, данный объект приравнивается объекту Мухи private slots: void slotGameTimer(); // Слот игрового таймера паука }; #endif // SPIDER_H
spinne.cpp
Spider Quellcode ist Fly Quellcode ähnlich, mit dem Unterschied, dass der Spider Slot die Fly Position auf dem Spielfeld verfolgt und Spider zu . wird die Seite fliegt und kriecht ihr hinterher. Und sobald der Feind der Fliege über eines der Objekte in der Grafikszene stolpert, prüft er, ob es sich bei diesem Objekt um eine Fliege handelt, falls ja, wird die Prozedur Game Over initialisiert.
#include "spider.h" #include "math.h" static const double Pi = 3.14159265358979323846264338327950288419717; static double TwoPi = 2.0 * Pi; static qreal normalizeAngle(qreal angle) { while (angle < 0) angle += TwoPi; while (angle > TwoPi) angle -= TwoPi; return angle; } Spider::Spider(QGraphicsItem *target, QObject *parent) : QObject(parent), QGraphicsItem() { angle = 0; // Задаём угол поворота графического объекта steps = 0; // Задаём стартовое положение ножек мухи countForSteps = 0; // Счётчик для отсчета тиков таймера, при которых мы нажимали на кнопки setRotation(angle); // Устанавливаем угол поворота графического объекта this->target = target; // Устанавливаем цель паука timer = new QTimer(); // Инициализируем игровой таймер паука // подключаем сигнал таймера к игровому слоту паука connect(timer, &QTimer::timeout, this, &Spider::slotGameTimer); timer->start(15); // Запускаем таймер } Spider::~Spider() { } QRectF Spider::boundingRect() const { return QRectF(-40,-50,80,100); } void Spider::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { // Рисуем ножки, без ножек паук не догонит муху painter->setPen(QPen(Qt::black, 2)); if(steps == 0){ // Первое положение ножек // Left 1 painter->drawLine(-24,-45,-28,-35); painter->drawLine(-28,-35,-22,-10); painter->drawLine(-22,-10,0,0); // Right 1 painter->drawLine(24,-45,28,-35); painter->drawLine(28,-35,22,-10); painter->drawLine(22,-10,0,0); // Left 2 painter->drawLine(-35,-38,-30,-18); painter->drawLine(-30,-18,-25,-3); painter->drawLine(-25,-3,0,0); // Right 2 painter->drawLine(35,-38,30,-18); painter->drawLine(30,-18,25,-3); painter->drawLine(25,-3,0,0); // Left 3 painter->drawLine(-35,38,-30,18); painter->drawLine(-30,18,-25,3); painter->drawLine(-25,3,0,0); // Right 3 painter->drawLine(35,38,30,18); painter->drawLine(30,18,25,3); painter->drawLine(25,3,0,0); // Left 4 painter->drawLine(-24,45,-28,35); painter->drawLine(-28,35,-22,10); painter->drawLine(-22,10,0,0); // Right 4 painter->drawLine(24,45,28,35); painter->drawLine(28,35,22,10); painter->drawLine(22,10,0,0); } else if (steps == 1){ // Второе положение ножек // Left 1 painter->drawLine(-23,-40,-24,-30); painter->drawLine(-24,-30,-19,-9); painter->drawLine(-19,-9,0,0); // Right 1 painter->drawLine(20,-50,23,-40); painter->drawLine(23,-40,15,-12); painter->drawLine(15,-12,0,0); // Left 2 painter->drawLine(-30,-35,-27,-24); painter->drawLine(-27,-24,-23,-5); painter->drawLine(-23,-5,0,0); // Right 2 painter->drawLine(40,-27,35,-10); painter->drawLine(35,-10,28,-1); painter->drawLine(28,-1,0,0); // Left 3 painter->drawLine(-40,27,-35,10); painter->drawLine(-35,10,-28,1); painter->drawLine(-28,1,0,0); // Right 3 painter->drawLine(30,35,27,24); painter->drawLine(27,24,23,5); painter->drawLine(23,5,0,0); // Left 4 painter->drawLine(-20,50,-27,30); painter->drawLine(-27,30,-20,12); painter->drawLine(-20,12,0,0); // Right 4 painter->drawLine(23,40,24,30); painter->drawLine(24,30,19,9); painter->drawLine(19,9,0,0); } else if (steps == 2){ // Третье положение ножек // Left 1 painter->drawLine(-20,-50,-23,-40); painter->drawLine(-23,-40,-15,-12); painter->drawLine(-15,-12,0,0); // Right 1 painter->drawLine(23,-40,24,-30); painter->drawLine(24,-30,19,-9); painter->drawLine(19,-9,0,0); // Left 2 painter->drawLine(-40,-27,-35,-10); painter->drawLine(-35,-10,-28,-1); painter->drawLine(-28,-1,0,0); // Right 2 painter->drawLine(30,-35,27,-24); painter->drawLine(27,-24,23,-5); painter->drawLine(23,-5,0,0); // Left 3 painter->drawLine(-30,35,-27,24); painter->drawLine(-27,24,-23,5); painter->drawLine(-23,5,0,0); // Right 3 painter->drawLine(40,27,35,10); painter->drawLine(35,10,28,1); painter->drawLine(28,1,0,0); // Left 4 painter->drawLine(-23,40,-24,30); painter->drawLine(-24,30,-19,9); painter->drawLine(-19,9,0,0); // Right 4 painter->drawLine(20,50,27,30); painter->drawLine(27,30,20,12); painter->drawLine(20,12,0,0); } painter->setPen(QPen(Qt::black, 1)); // Левое Жвало QPainterPath path1(QPointF(0, -20)); path1.cubicTo(0, -20, -5, -25, -3, -35); path1.cubicTo(-3,-35,-15,-25,-8,-17); path1.cubicTo(-8,-17,-5,15,0,-20 ); painter->setBrush(Qt::black); painter->drawPath(path1); // Правое Жвало QPainterPath path2(QPointF(0, -20)); path2.cubicTo(0, -20, 5, -25, 3, -35); path2.cubicTo(3,-35,15,-25,8,-17); path2.cubicTo(8,-17,5,15,0,-20 ); painter->setBrush(Qt::black); painter->drawPath(path2); // Голова painter->setBrush(QColor(146, 115, 40, 255)); painter->drawEllipse(-10,-25,20,15); // Тушка painter->drawEllipse(-15, -15, 30, 30); // Жопка painter->drawEllipse(-20, 0, 40,50); painter->setPen(QPen(Qt::white,3)); painter->drawLine(-10,25,10,25); painter->drawLine(0,35,0,15); // Левое глазище painter->setPen(QPen(Qt::black,1)); painter->setBrush(Qt::red); painter->drawEllipse(-8,-23,6,8); // Правое глазище painter->setBrush(Qt::red); painter->drawEllipse(2,-23,6,8); Q_UNUSED(option); Q_UNUSED(widget); } void Spider::slotGameTimer() { // Определяем расстояние до Мухи QLineF lineToTarget(QPointF(0, 0), mapFromItem(target, 0, 0)); // Угол поворота в направлении к Мухе qreal angleToTarget = ::acos(lineToTarget.dx() / lineToTarget.length()); if (lineToTarget.dy() < 0) angleToTarget = TwoPi - angleToTarget; angleToTarget = normalizeAngle((Pi - angleToTarget) + Pi / 2); /* В Зависимости от того, слева или справа находится Муха от Паука, * устанавливаем направление поворота паука в данном тике таймера * Скорость разворота зависит от угла, на который необходимо повернуться пауку * */ if (angleToTarget > 0 && angleToTarget < Pi) { // Rotate left if(angleToTarget > Pi / 5){ angle = -15; } else if(angleToTarget > Pi / 10){ angle = -5; } else { angle = -1; } } else if (angleToTarget <= TwoPi && angleToTarget > (TwoPi - Pi)) { // Rotate right if(angleToTarget < (TwoPi - Pi / 5)){ angle = 15; } else if(angleToTarget < (TwoPi - Pi / 10)){ angle = 5; } else { angle = 1; } } else if(angleToTarget == 0) { angle = 0; } setRotation(rotation() + angle); // Разворачиваемся // Бежим в сторону мухи if(lineToTarget.length() >= 40){ setPos(mapToParent(0, -(qrand() % ((4 + 1) - 1) + 1))); // Двигаем ножками, Dance, dance, Spidy !!! countForSteps++; if(countForSteps == 6){ steps = 1; update(QRectF(-40,-50,80,100)); } else if (countForSteps == 12){ steps = 0; update(QRectF(-40,-50,80,100)); } else if (countForSteps == 18){ steps = 2; update(QRectF(-40,-50,80,100)); } else if (countForSteps == 24) { steps = 0; update(QRectF(-40,-50,80,100)); countForSteps = 0; } } /* Производим проверку на то, наткнулся ли паук на какой-нибудь * элемент на графической сцене. * Для этого определяем небольшую область перед пауком, * в которой будем искать элементы * */ QList<QGraphicsItem *> foundItems = scene()->items(QPolygonF() << mapToScene(0, 0) << mapToScene(-2, -2) << mapToScene(2, -2)); /* После чего проверяем все элементы. * Один из них будет сам Паук - с ним ничего не делаем. * А с остальными высылаем сигнал в ядро игры * */ foreach (QGraphicsItem *item, foundItems) { if (item == this) continue; if(item == target){ emit signalCheckGameOver(); } } /* Проверка выхода за границы поля * Если объект выходит за заданные границы, то возвращаем его назад * */ if(this->x() - 10 < -250){ this->setX(-240); // слева } if(this->x() + 10 > 250){ this->setX(240); // справа } if(this->y() - 10 < -250){ this->setY(-240); // сверху } if(this->y() + 10 > 250){ this->setY(240); // снизу } } /* Функция паузы, отвечает за включение и отключение паузы * */ void Spider::pause() { if(timer->isActive()){ timer->stop(); } else { timer->start(15); } }
widget.h
In der Header-Datei des Anwendungskerns müssen Sie das Objekt definieren, das für den Spider, die Spielstatusvariable und den Pause-Hotkey verantwortlich ist. Sowie Slots für Spielstart, Pause und Game Over Verfahren.
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QGraphicsScene> #include <QGraphicsItem> #include <QShortcut> #include <QDebug> #include <QTimer> #include <QMessageBox> #include <triangle.h> #include <apple.h> #include <spider.h> #define GAME_STOPED 0 #define GAME_STARTED 1 namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = 0); ~Widget(); private: Ui::Widget *ui; QGraphicsScene *scene; /// Объявляем графическую сцену Triangle *triangle; /// и треугольник QTimer *timer; /** Объявляем игровой таймер, благодаря которому * будет производиться изменения положения объекта на сцене * При воздействии на него клавишами клавиатуры * */ QTimer *timerCreateApple; /// Таймер для периодического создания яблок в игре QList<QGraphicsItem *> apples; /// Список со всеми яблоками, присутствующими в игре double count; /// Переменная, которая хранит счёт игре Spider *spider; // Объект Паука QShortcut *pauseKey; // Горячая клавиша, отвечающая за паузу в игре int gameState; /* Переменная, которая хранит состояние игры. * То есть, если игра запущена, то статус будет GAME_STARTED, * в противном случае GAME_STOPED * */ private slots: /// Слот для удаления яблок если Муха наткнулась на это яблоко void slotDeleteApple(QGraphicsItem * item); void slotCreateApple(); /// Слот для создания яблок, срабатывает по таймеру void on_pushButton_clicked(); // Слот для запуска игры void slotGameOver(); // Слот инициализации Game Over void slotPause(); // Слот для обработки паузы }; #endif // WIDGET_H
widget.cpp
Im Vergleich zum Programmcode aus den vorherigen Lektionen muss diese Datei in dieser Lektion gründlich bearbeitet werden. Da das Spiel durch Drücken der Taste pushButton startet, muss der Programmcode zum Initialisieren von Objekten und Starten von Timern in dem Slot platziert werden, an den das Signal der Taste gesendet wird. Es wird auch notwendig, die Pausenfunktion im Spiel zu implementieren, wonach alle Spieltimer gestoppt werden und Objekte sich nicht bewegen oder andere Aktionen ausführen können. Und in dem Slot, der für Game Over zuständig ist, ist es notwendig, das Entfernen aller Objekte aus der Spielszene richtig zu handhaben.
#include "widget.h" #include "ui_widget.h" Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); this->resize(600,640); /// Задаем размеры виджета, то есть окна this->setFixedSize(600,640); /// Фиксируем размеры виджета scene = new QGraphicsScene(); /// Инициализируем графическую сцену ui->graphicsView->setScene(scene); /// Устанавливаем графическую сцену в graphicsView ui->graphicsView->setRenderHint(QPainter::Antialiasing); /// Устанавливаем сглаживание ui->graphicsView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); /// Отключаем скроллбар по вертикали ui->graphicsView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); /// Отключаем скроллбар по горизонтали scene->setSceneRect(-250,-250,500,500); /// Устанавливаем область графической сцены timer = new QTimer(); timerCreateApple = new QTimer(); gameState = GAME_STOPED; pauseKey = new QShortcut(this); pauseKey->setKey(Qt::Key_Pause); connect(pauseKey, &QShortcut::activated, this, &Widget::slotPause); } Widget::~Widget() { delete ui; } void Widget::slotDeleteApple(QGraphicsItem *item) { /* Получив сигнал от Мухи * Перебираем весь список яблок и удаляем найденное яблоко * */ foreach (QGraphicsItem *apple, apples) { if(apple == item){ scene->removeItem(apple); // Удаляем со сцены apples.removeOne(apple); // Удаляем из списка delete apple; // Вообще удаляем ui->lcdNumber->display(count++); /* Увеличиваем счёт на единицу * и отображаем на дисплее * */ } } } void Widget::slotCreateApple() { Apple *apple = new Apple(); // Создаём яблоко scene->addItem(apple); // Помещаем его в сцену со случайной позицией apple->setPos((qrand() % (251)) * ((qrand()%2 == 1)?1:-1), (qrand() % (251)) * ((qrand()%2 == 1)?1:-1)); apple->setZValue(-1); /* Помещаем яблоко ниже Мухи, то есть Муха * на сцене будет выше яблок * */ apples.append(apple); // Добавляем Муху в Список } void Widget::on_pushButton_clicked() { count = 0; ui->lcdNumber->display(count); triangle = new Triangle(); /// Инициализируем муху scene->addItem(triangle); /// Добавляем на сцену треугольник triangle->setPos(0,0); /// Устанавливаем треугольник в центр сцены spider = new Spider(triangle); // Инициализируем паука scene->addItem(spider); // Добавляем паука на сцену spider->setPos(180,180); // Устанавливаем позицию паука /* Подключаем сигнал от паука на проверку состояния GameOver * */ connect(spider, &Spider::signalCheckGameOver, this, &Widget::slotGameOver); /** Инициализируем таймер и вызываем слот обработки сигнала таймера * у Треугольника 100 раз в секунду. * Управляя скоростью отсчётов, соответственно управляем скоростью * изменения состояния графической сцены * */ connect(timer, &QTimer::timeout, triangle, &Triangle::slotGameTimer); timer->start(1000 / 100); /** Раз в секунду отсылаем сигнал на создание яблока в игре * */ connect(timerCreateApple, &QTimer::timeout, this, &Widget::slotCreateApple); timerCreateApple->start(1000); /** Подключаем сигнал от Мухи, в котором передаются Объекты, на которые * наткнулась Муха * */ connect(triangle, &Triangle::signalCheckItem, this, &Widget::slotDeleteApple); ui->pushButton->setEnabled(false); gameState = GAME_STARTED; } void Widget::slotGameOver() { /* Если игра окончена * Отключаем все таймеры * */ timer->stop(); timerCreateApple->stop(); QMessageBox::warning(this, "Game Over", "Мои соболезнования, но Вас только что слопали"); /* Отключаем все сигналы от слотов * */ disconnect(timerCreateApple, &QTimer::timeout, this, &Widget::slotCreateApple); disconnect(triangle, &Triangle::signalCheckItem, this, &Widget::slotDeleteApple); disconnect(spider, &Spider::signalCheckGameOver, this, &Widget::slotGameOver); /* И удаляем все объекты со сцены * */ spider->deleteLater(); triangle->deleteLater(); foreach (QGraphicsItem *apple, apples) { scene->removeItem(apple); // Удаляем со сцены apples.removeOne(apple); // Удаляем из списка delete apple; // Вообще удаляем } /* Активируем кнопку старта игры * */ ui->pushButton->setEnabled(true); gameState = GAME_STOPED; // Устанавливаем состояние игры в GAME_STOPED } void Widget::slotPause() { /* Выполняем проверку на состояние игры, * если игра не запущена, то игнорируем Паузу. * В противном случае или запускаем, или останавливаем все таймеры * */ if(gameState == GAME_STARTED){ if(timer->isActive()){ timer->stop(); timerCreateApple->stop(); spider->pause(); } else { timer->start(1000/100); timerCreateApple->start(1000); spider->pause(); } } }
Ergebnis
Basierend auf den Ergebnissen der durchgeführten Arbeit wird das Spiel nicht mehr endlos sein und der Wert der gewonnenen Punkte wird erheblich steigen.
Auch im Video-Tutorial zu diesem Artikel werden zusätzliche Kommentare gegeben und die Bedienung des Spiels demonstriert.
Vollständige Liste der Artikel dieser Serie:
- Lektion 1. Wie man ein Spiel in Qt schreibt. Objektverwaltung
- Lektion 2. Wie man ein Spiel in Qt schreibt. Animation des Spielhelden (2D)
- Lektion 3. Wie man ein Spiel in Qt schreibt. Interaktion mit anderen Objekten
- Lektion 4. Wie man ein Spiel in Qt schreibt. Der Feind ist der Sinn des Überlebens
- Lektion 5. Wie man ein Spiel in Qt schreibt. Ton von QMediaPlayer hinzufügen
Здравствуй у меня опять проблема как решить? In member function 'void Widget::on_pushButton_clicked()': ошибка: 'class Ui::Widget' has no member named 'pushButton' ui->pushButton->setEnabled(false); : In member function 'void Widget::slotGameOver()': ошибка: 'class Ui::Widget' has no member named 'pushButton' ui->pushButton->setEnabled(true); скрин http://priscree.ru/img/a9de07f8d2a5a0.jpg ^ ^
вставляю кнопку вообще 10 ошибок не определена ссылка на паука и тд
Добавьте через графический дизайнер кнопку в widget.ui и проследите, чтобы название кнопки было pushButton
добавил кнопку все равно много ошибок вот скрины http://priscree.ru/img/e8e0d04f9e232c.jpg http://priscree.ru/img/3fb040824e8665.jpg
ошибки в vtable... Это moc файлы попортились. Нужно удалить build сборку и пересобрать, и если не поможет, то создать новый проект и переписать в него код. Иначе никак.
хорошо попробую переписать все.как напишу отпишусь)
все заработало спасибо еще вопрос у нас препод просит чтобы мы сделали так.чтобы можно было сохранять результаты это возможно ?
Конечно, возможно. Можно сохранять в файл. Можно сохранять в базу данных. Можно даже в реестр писать с помощью QSettings . Мне больше всего нравится база данных для таких целей. По окончании игры можно добавлять результат в базу данных. Также можно добавить кнопку, которая бы открывала окно с результатами.
а как это сделать ? можете помочь если не сложно конечно и есть время
Значит так. Просто писать код за вас я не буду, но подсказать и направить на нужный путь - это без проблем.
Поэтому -> В предыдущем сообщении я дал ссылку на статью с базой данных. Изучите её. Изучите, как добавлять записи в базу данных. Там же показано, как отобразить записи в таблице. А потом попытайтесь по окончании игры сделать добавление строк в базу данных. В коде есть место, где по окончании игры вызывается диалог. Это происходит в слоте slotGameOver . Вот в нём можно сделать добавление записей в базу данных. Также можете добавить кнопку в окно игры, по нажатию которой можно будет вызвать диалог, в котором как раз и будете показывать рекорды. Если есть затруднения с пониманием сигналов и слотов, то изучите следующую статью .
Здравствуйте,
Подскажите, пжлст, как работает этот код :
Самое непонятное - это 5 -ая строчка, зачем добавлять 90 градусов?
не 90 на 45, ошибся
Там неправильный подсчёт был по направлению и полный бардак был с поведением, эти 45 градусов исправляли ситуацию. Точную причину уже совсем не помню.
А вообще все эти расчёты довольно тяжелы для процессора, я подобрал более лёгкий вариант со скалярными векторами. Но статью ещё пока не недописал к сожалению (она пока в разработке).
Здравствуйте! Почему может быть такая ошибка: враг висит в углу, колеблется в нём, но не двигается? По логике код такой же, но вместо орисовки моделей использую спрайты. Со спрайтом "мухи" всё хорошо, а вот "паук" отказывается вести себя нормально. Подозреваю, что ошибка может быть здесь (это код, который идёт вместо отрисовки):
Или же ошибка где-то в управлении "паука", но там код вообще неизменный. (в Spider.cpp, void Spider...)
Добрый день.
Дело тут явно не в методе paint, скорее всего всё-таки есть какая-то ошибка в другом месте. Обычно такое может быть в районе метода slotGamerTimer
Спасибо! На самом деле ошибка оказалась от невнимательности - просто пропустила подключение движения в сторону модели. Теперь всё работает.
Если вам не сложно, могли бы вы, пожалуйста, объяснить, за что отвечают параметры в скобках тут: setPos(mapToParent(0, -(qrand() % ((2 + 1) - 1) + 1)))?
Нашла только такое, не много о чём говорит: (qrand() % ((high + 1) - low) + low). Экспериментально кое-что выяснила, но хотелось бы знать точно)
А ещё вот тут, когда генерировали бананы: banana->setPos((qrand() % (251)) * ((qrand()%2 == 1)?1:-1),
(qrand() % (251)) * ((qrand()%2 == 1)?1:-1));
А так, благодарю за указку на slotGameTimer!
П.С.: я не очень умею пока читать документацию( поэтому прошу помощи у вас, чтобы разобраться с этими параметрами