© EVILEG 2015-2018
Рекомендует хостинг
TIMEWEB
29 мая 2018 г. 16:55

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

Qt, С++, Игры

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

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

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

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

вам нудно переопределить метод 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
{

}

 

ну и сцена где я все добавляю, там у меня много классов которые я пока еще ни от кого не наследую

Вот так должно выглядеть наследование для класса 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/ Используйте, пожалуйста, для вставки кода специальное диалоговое окно, это кнопочка на панели инструментов со значками <>

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

Ответы

Только авторизованные пользователи могут отвечать на форуме.
Пожалуйста, Авторизуйтесь или Зарегистрируйтесь
25 июня 2018 г. 11:55
lebendig

C++ - Тест 006. Перечисления

  • Результат 100 баллов
  • Очки рейтинга 10
25 июня 2018 г. 11:24
lebendig

C++ - Тест 005. Структуры и Классы

  • Результат 100 баллов
  • Очки рейтинга 10
25 июня 2018 г. 8:48
lebendig

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат 100 баллов
  • Очки рейтинга 10
Последние комментарии
25 июня 2018 г. 9:34
EVILEG

Как написать игру на Qt - Урок 4. Враг - смысл в выживании

Там неправильный подсчёт был по направлению и полный бардак был с поведением, эти 45 градусов исправляли ситуацию. Точную причину уже совсем не помню. А вообще все эти расчёты довольно...
25 июня 2018 г. 9:13
MarkSD

Как написать игру на Qt - Урок 4. Враг - смысл в выживании

Здравствуйте, Подскажите, пжлст, как работает этот код : QLineF lineToTarget(QPointF(0, 0), mapFromItem(target, 0, 0));  // Проводим линию от паука к мухе qreal angl...
25 июня 2018 г. 7:51
EVILEG

PyQt5 - Урок 003. QSystemTrayIcon - Как свернуть приложение в трей

Если не ошибаюсь, можно просто удалить вот эту строку central_widget.setLayout(grid_layout) Там указатель на парента передаётся в само размещение, что автоматически заменяет в размещен...
Сейчас обсуждают на форуме
25 июня 2018 г. 17:38
IscanderChe

Иконка исполняемого файла

Спасибо!
25 июня 2018 г. 13:12
Arrow

QComboBox и База данных

И если можно еще один вопрос. Таблицы во вложении. Если писать: mainModel = new QSqlRelationalTableModel(this);mainModel-&g...;
25 июня 2018 г. 7:49
EVILEG

На чём сделан этот сайт?

Добрый день! На сервере сайта установлена Ubuntu 16.04. В качестве сервера используется VDS. Хостинг-провайдер Timeweb . Сайт написан на Django/Python, для...
19 июня 2018 г. 7:56
EVILEG

как редактировать порядок обхода этементов по нажатию TAB в Qt5 qml

Что-то наподобие такого TextField { Keys.onReturnPressed: nextItemInFocusChain().forceActiveFocus()}

Рекомендуемые страницы