Проблемы с коллизией

Qt, С++, Игры

У меня есть три основным класса land из него состоит поле 30 на 30 это картинка, класс blockland это тоже картинка которую я добавляю при нажатии на правую кнопку мыши на поле и есть класс actor это герой он по клеткам идет туда куда я кликнул. Мне нужно сделать проверку коллизии, чтобы при встрече на сцене blockland он его обходил. Пытаюсь сделать так:

  1. blockland *test;
  2. case ActorAction::Down: m_moveAnimation->setPosAt(1.0, pos()+QPointF(0, SpeedPx));
  3. QList<QGraphicsItem*>items = scene()->items(QPolygonF()<<mapToScene(0,0)<<mapToScene(20,20)<<mapToScene(-20,-20));
  4. foreach (QGraphicsItem *item,items)
  5. {
  6. if(item==this)
  7. {
  8. continue;
  9. }
  10. if(item==test)
  11. {
  12. m_moveAnimation->setPosAt(1.0, pos()+QPointF(0, -SpeedPx));
  13. }
  14. }
В итоге он разворачивает совершенно в рандомный момент когда я устанавливаю blockland на сцене. Пытался сделать через if(!scene()->collidingItems(this).isEmpty()) тоже не получилось ни как обозначить класс blockland. Пытался написать через формирование абстрактоного пула для объектов но после установление этого пула как одного из родителей класс выдавал ошибки типа : invalid new-expression of abstract class type. Уже всю голову сломал как еще можно это сделать.
2

Вам это нравится? Поделитесь в социальных сетях!

20

Еще попробовал таким образом

QList<QGraphicsItem*>item = this->collidingItems(m_actor);
        if(!item.isEmpty())
        {
            for (auto items : item)
            {
                if(testl)
                {
                    m_actor->processMouse(ActorAction::Left);
                }
            }
        }
но так как isEmpty срабатывает тогда когда объект сталкивается с каким либо объектом а все мое состоит из объектов то условие срабатывает всегда, не как не могу заставить персонажа отличать обычную ячейку от заблокированной
    Evgenii Legotckoi
    • 30 мая 2018 г. 13:05
    • (ред.)

    Добрый день!

    Вам нужно создать базовый класс, который наследован от QGraphicsItem, а все ваши игровые объекты уже наследовать от него.
    В этой базовом классе вам нужно добавить метод getType(), который будет возвращать либо тип int, либо enum.
    Также в базовом классе нужно будет перечислить все в enum все типы игровых объектов, а когда будетт брать объекты через collidingItems, то кастовать каждый объект к типу вашего нового базового класса и проверять через метод getType(), можно ли на этот объект реагировать или нет.
    В каждом наследованном классе нужно будет переопределить метод getType() так, чтобы он возвращал enum, который соответствует типу этого объекта.
    Подобный функционал был реализован вот в этой статье по полиморфизму

    Если не понятно, то вечером постараюсь накидать пример кода, сейчас немного некогда.

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

      новый класс gameobject:
      h файл
      #ifndef GAMEOBJECT_H
      #define GAMEOBJECT_H
      
       
      #include <QGraphicsItem>
      
       
      class gameobject : public QGraphicsItem
      {
          Q_OBJECT
      public:
          explicit gameobject(QGraphicsItem *parent =nullptr);
          enum Type
          {
              blockwall,
              bullet,
              mod,
          };
      
       
      };
      
       
      #endif // GAMEOBJECT_H
      срр файл
      #include "gameobject.h"
      
       
      gameobject::gameobject(QGraphicsItem *parent)
      {
      
       
      }

      Наследовал класс который хотел занести туда

      #include <gameobject.h>
      class TestLand :public gameobject
      определял слот возврата
      virtual int type() const override;
      это в h файле в срр так писал
       
      int TestLand::type()
      {
          return Type::blockwall;
      }
      в итоге этот класс при попытке обозначит его на сцене
       TestLand *mi = new TestLand (it->pos().x(),it->pos().y(),30,30);
      возвращал такую ошибку:  invalid new-expression of abstract class type
        Evgenii Legotckoi
        • 31 мая 2018 г. 13:21

        вам нудно переопределить метод boundingRect.

        Он объявлен в классе QGraphicsItem и не имеет реализации, поэтому его нужно также переопределить и дать своб реализацию.

          Попытался переопределить boundingRec() и процессе поиска информации понял что он вроде как применяется только для непосредственно нарисованных объектов а у меня все в картинка. После этого наследовал базовый класс от QGraphicsPixMapItem и теперь у меня ошибка при попытке вернуть тип в классе который я наследую от базового


          virtual int type() const override;
          вот в этой строке, следующая ошибка
          ошибка: prototype for 'int TestLand::type()' does not match any in class 'TestLand' int TestLand::type()

            написал так

            в H файле
            #ifndef GAMEOBJECT_H
            #define GAMEOBJECT_H
            
            #include <QGraphicsItem>
            #include <QObject>
            #include <QGraphicsPixmapItem>
            
            
            class gameobject: public QObject, public QGraphicsPixmapItem
            {
                Q_OBJECT
            public:
               explicit gameobject(qreal x, qreal y, qreal w, qreal h, QGraphicsItem *parent=0);
                enum Type
                {
                    blockland,
                    mob,
                    tower,
                    bullet,
                    hero,
                    land
                };
            public:
            
            
            };
            
            #endif // GAMEOBJECT_H
            и в срр
            #include "gameobject.h"
            
            gameobject::gameobject(qreal x, qreal y, qreal w, qreal h, QGraphicsItem *parent)
                :QObject()
            {
            
            }
            пока что по крайней мере нет ошибок

              Но теперь все классы которые я наследую от базового вызывают ошибку при попытке их добавить на сцену и установить их позицию методами addItem и setPos или при использовании setZValue

                А вы текст ошибки прилагать будете?
                Плюсом я вам указывал на статью, где есть пример с абстрактным методом getType() в базовом классе. Пробовали сделать, как в той статье?

                  Ошибки вот такого типа

                  При использовании setPose  и setZValue
                  ошибка: request for member 'setPos' is ambiguous
                  При использовании addItem
                  ошибка: 'QGraphicsItem' is an ambiguous base of 'hero_actor'
                  Да конечно пытался, я уже не один день пытаюсь сделать это и все найденные примеры перепробовал

                    тааак...

                    Есть одна мысль.
                    Реализация конструктора точно не правильно написана. У вас там множественное наследование.
                    gameobject::gameobject(qreal x, qreal y, qreal w, qreal h, QGraphicsItem *parent)
                        : QObject(), QGraphicsPixmapItem(parent)
                    {
                    }
                    Исправьте это, а там скажете, какие ещё ошибки посыпятся. Но так конструктор будет правильный.

                      TestLand *mi = new TestLand (it->pos().x(),it->pos().y(),30,30);
                                  addItem(mi);
                      вот тут ругается на добавление
                       
                      ошибка: 'QGraphicsItem' is an ambiguous base of 'TestLand' addItem(mi);
                      ^

                        Какая у вас иерархия наследования классов сейчас? Что-то совсем по ходу намудрили.

                          есть gameobject

                          h:
                          #ifndef GAMEOBJECT_H
                          #define GAMEOBJECT_H
                          
                          #include <QGraphicsItem>
                          #include <QObject>
                          #include <QGraphicsPixmapItem>
                          
                          
                          class gameobject: public QObject, public QGraphicsPixmapItem
                          {
                              Q_OBJECT
                          public:
                             explicit gameobject(qreal x, qreal y, qreal w, qreal h, QGraphicsItem *parent=0);
                              enum Type
                              {
                                  blockland,
                                  mob,
                                  tower,
                                  bullet,
                                  hero,
                                  land
                              };
                          public:
                          
                          
                          };
                          
                          #endif // GAMEOBJECT_H
                          cpp
                          #include "gameobject.h"
                          
                          gameobject::gameobject(qreal x, qreal y, qreal w, qreal h, QGraphicsItem *parent)
                              : QObject(), QGraphicsPixmapItem(parent)
                          {
                          
                          }
                          и есть testland
                          h
                          #ifndef TESTLAND_H
                          #define TESTLAND_H
                          
                          
                          #include <QtWidgets>
                          #include <QObject>
                          #include <gameobject.h>
                          
                          
                          
                          
                          class TestLand :public gameobject, public QGraphicsPixmapItem
                          {
                              Q_OBJECT
                          public:
                               TestLand(qreal x, qreal y, qreal w, qreal h, QGraphicsItem *parent=0);
                               virtual int type() const;
                          };
                          
                          #endif // TESTLAND_H
                          cpp
                          #include "testland.h"
                          #include <QGraphicsItem>
                          
                          
                          
                          TestLand::TestLand(qreal x, qreal y, qreal w, qreal h, QGraphicsItem *parent)
                              :gameobject(parent)
                          {
                              setPos(QPointF(x,y));
                              this->setPixmap(QPixmap("land_2.jpg"));
                          }
                          
                          int TestLand::type() const
                          {
                          
                          }

                           

                          ну и сцена где я все добавляю, там у меня много классов которые я пока еще ни от кого не наследую
                            Evgenii Legotckoi
                            • 2 июня 2018 г. 4:16

                            Вот так должно выглядеть наследование для класса TestLand


                            class TestLand :public gameobject
                            {
                                Q_OBJECT
                            public:
                                 TestLand(qreal x, qreal y, qreal w, qreal h, QGraphicsItem *parent=0);
                                 virtual int type() const;
                            };
                            У вас gameobject и так уже наследован от QGraphicsPixmapItem , поэтому добавлять это наследование в TestLand не нужно. Это неправильно.

                              Теперь снова ошибка

                              TestLand::TestLand(qreal x, qreal y, qreal w, qreal h, QGraphicsItem *parent)
                                  :gameobject(parent) // ругается на это
                              ошибка: no matching function for call to 'gameobject::gameobject(QGraphicsItem*&)'
                              :gameobject(parent)
                              ^

                                Эх... ну правильно, у вас же конструктора такого у gameobject нет.

                                TestLand::TestLand(qreal x, qreal y, qreal w, qreal h, QGraphicsItem *parent)
                                    : gameobject(x, y, w, h, parent)
                                {
                                    setPos(QPointF(x,y));
                                    this->setPixmap(QPixmap("land_2.jpg"));
                                }

                                  Спасибо огромное за помощь. Намучился ты со мною конечно, без тебя бы не зделал

                                    Еще один вопрос, можно ли использовать collidingitem перед объектом.

                                    Что нибудь наподобие такого
                                    1. QList<QGraphicsItem *> foundItems = scene()->items(QPolygonF()
                                    2. << mapToScene(0, 0)
                                    3. << mapToScene(-20, -20)
                                    4. << mapToScene(20, -20));
                                    Только для collidingitem?

                                      Вы можете использовать метод items() только передавать в него форму вашего объекта.

                                      Так
                                      QList<QGraphicsItem *> foundItems = scene()->items(myItem->boundingRect());
                                      Или так
                                      QList<QGraphicsItem *> foundItems = scene()->items(myItem->shape());

                                      P/S/ Используйте, пожалуйста, для вставки кода специальное диалоговое окно, это кнопочка на панели инструментов со значками <>

                                        Учту, еще раз спасибо большое за помощь

                                          Комментарии

                                          Только авторизованные пользователи могут публиковать комментарии.
                                          Пожалуйста, авторизуйтесь или зарегистрируйтесь