- 1. Враг мухи в структуре проекта
- 2. spider.h
- 3. spider.cpp
- 4. widget.h
- 5. widget.cpp
- 6. Итог
- 7. Видеоурок
Продолжаем тему того, как написать игру на Qt. После того, как в прошлых статьях была создана Муха, которая поедает яблоки, настало время создать ей врага. А Враг Мухи , как известно, Паук . Создание игровых персонажей, которые будут участвовать в непосредственной жизни Вашего главного героя - это не только отрисовка анимации действий и передвижения, а также логика реакций на воздействия игрока, но и искусственный интеллект, в соответствии с логикой которого будет определятся поведение игрового персонажа. Таким образом, мы добавляем в игру новый смысл, не только съесть как можно больше яблок, но и выжить любой ценой.
Определим поведение Паука в данной версии игры. Что же он должен делать? Да самое обычное из всех действий - охотиться на Муху , просто гоняться за ней по игровому полю.
Также добавим в игру кнопку для запуска игрового процесса, и паузу, и самое главное, что добавим - это Game Over.
Враг мухи в структуре проекта
Как и в случае с Мухой в структуру проекта добавляется дополнительный класс, который будет отвечать за объект, которым является Паук .
- spider.h - заголовочный файл класса, отвечающего за Паука
- spider.cpp - файл исходных кодов, отвечающий за Паука
spider.h
Отличие данного файла от заголовочного файла мухи заключается в том, что в нём объявлен игровой таймер, который отвечает за поведение Паука , то есть враг Мухи тактируется не от таймера в ядре игры, а от собственного внутреннего таймера. Также при инициализации паука, в него закладывается его цель, то есть Муха , за которой он неустанно следует. В данном случае искусственный интеллект примитивен до безобразия, но большего на данный момент и не требуется.
- #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
spider.cpp
Исходный код Паука аналогичен исходному коду Мухи , с тем отличием, что в игровом Слоте Паука отслеживается положение Мухи на игровом поле, и Паук разворачивается в сторону Мухи и ползёт за ней. А как только враг мухи натыкается на какой-нибудь из объектов на графической сцене, то он производит проверку, является ли этот объект Мухой , если да, то инициализируется процедура Game Over .
- #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
В заголовочном файле ядра приложения необходимо определить объект, который отвечает за Паука, переменную состояния игры и Горячую клавишу паузы. А также слоты для обработки запуска игры, паузы и процедуры Game Over .
- #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
По сравнению с программным кодом, который был в предыдущих уроках, с данным файлом в этом уроке необходимо основательно поработать. Поскольку игра, стартует по нажатию кнопки pushButton, то и программный код инициализации объектов и запуска таймеров необходимо вынести в слот, которому передаётся сигнал от кнопки. Также возникает необходимость реализовать функцию паузы в игре, по которой все игровые таймеры останавливаются и объекты не могут передвигаться или производить иных действий. А в слоте, который отвечает за Game Over необходимо правильно обработать удаление всех объектов с игровой сцены.
- #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();
- }
- }
- }
Итог
По результатам проведенной работы игра перестанет быть бесконечной и ценность набираемых очков возрастёт в разы.
Также в видеоуроке по данной статье даны дополнительные комментарии и продемонстрирована работа игры.
Полный список статей данного цикла:
- Урок 1. Как написать игру на Qt. Управление объектом
- Урок 2. Как написать игру на Qt. Анимация героя игры (2D)
- Урок 3. Как написать игру на Qt. Взаимодействие с другими объектами
- Урок 4. Как написать игру на Qt. Враг - смысл в выживании
- Урок 5. Как написать игру на Qt. Добавляем звук с QMediaPlayer
Здравствуй у меня опять проблема как решить? 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!
П.С.: я не очень умею пока читать документацию( поэтому прошу помощи у вас, чтобы разобраться с этими параметрами