QGraphicsItem::collidingItems([...]) and QGraphicsScene::collidingItems([...])



  • Copy of https://forum.qt.io/topic/53153/qgraphicsitem-collidingitems-and-qgraphicsscene-collidingitems-causes-runtime-error

    Hi,

    This is my first game (and program with Qt) and I got pretty far on my own but now I am stuck!

    When I run the following code I get a runtime error.

    void AnimationTir::advance(int phase)
    {
    if (phase == 1)
    {
    setPos(pos().rx() + vitX / 30, pos().ry() + VitY / 30);
    }

    if (!GameState::Instance().sceneRect().contains(pos()))
    {
    emit(obusDepasseScene());
    }

    QList<QGraphicsItem *> objetsEnCollision = collidingItems(); //cause crash
    if (!GameState::Instance().collidingItems(this).isEmpty()) //cause crash
    {
    emit(objetTouche(pos()));
    }
    }

    It crashes in qvector.h (Qt 5.4.1 win32 on windows7 x64) line 490
    template <typename T>
    void QVector<T>::reallocData(const int asize, const int aalloc, QArrayData::AllocationOptions options)
    {
    Q_ASSERT(asize >= 0 && asize <= aalloc); //crash right here!!!
    Data *x = d;
    [...]
    }

    This is the header of the class AnimationTir.
    This class inherits QGraphicsObject. I use slots and signals with
    my classes to keep track of what's going on in my game.

    #include <qgraphicsitem.h>
    #include <qpainter.h>
    #include <qpoint.h>

    class AnimationTir : public QGraphicsObject
    {
    Q_OBJECT
    public:
    AnimationTir(int puissance, int angle, QPointF posIni);
    void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0);
    void advance(int phase);
    QRectF boundingRect() const;
    signals:
    void objetTouche(QPointF positionCollision);
    void obusDepasseScene();
    private:
    double vitX;
    double VitY;
    int tailleRectangle;
    };

    This is my "custom QgraphicsScene class".

    #include <qgraphicsscene.h>
    #include <qlist.h>
    #include "Tank.h"
    #include "Map.h"
    #include "AnimationTir.h"

    class GameState : public QGraphicsScene
    {
    Q_OBJECT
    public:
    static GameState& Instance();
    void nouvellePartie(int nbrTank, int tailleExplosion, int nbrDegatsExplosion);
    public slots:
    void tirer();
    void changerPuissance();
    void canonAntihoraire();
    void canonHoraire();
    void avancerGauche();
    void avancerDroite();
    void tirDepasseScene();
    void traiterCollisionObus(QPointF positionCollision);
    void detruireTank(Tank* tankADetruire);
    protected:
    GameState();
    GameState& operator=(const GameState&) {}
    GameState(const GameState&) {}

    int nbrTank;
    int noTankActif;
    QList<Tank*> listeTank;
    QColor listeDesCouleurs[8];
    AnimationTir* animTir;
    bool tirEnCours;

    int tailleExplosion;
    int nbrDegatsExplosion;
    };

    It crashes when I shoot with GameState::tirer()
    GameState::tirer() create a new AnimationTir on the heap. AnimationTir inherits QGraphicsObject and it's position is just in front of the Tank muzzle.

    void GameState::tirer()
    {
    [...]
    //positionBoucheCanon return the scene position of the muzzle of the tank
    QPointF posIni = tankCourant->positionBoucheCanon();
    double puissance = tankCourant->GetPuissance();
    double angle = tankCourant->GetAngle();
    animTir = new AnimationTir(puissance, angle, posIni);
    addItem(animTir);
    connect(animTir, SIGNAL(objetTouche(QPointF)), this, SLOT(traiterCollisionObus(QPointF)));
    connect(animTir, SIGNAL(obusDepasseScene()), this, SLOT(tirDepasseScene()));
    }
    }

    In my game there are 3 type of QGraphicsObject: Tank, AnimationTir and Map
    These are the methods related to collision detection for these classes.

    QPainterPath Tank::shape() const
    {
    QPainterPath forme;
    QVector<QPointF>* pointsPolygone;
    //voir les points de la methode paint
    pointsPolygone->append(QPoint(0, 45));
    pointsPolygone->append(QPoint(20, 65));
    pointsPolygone->append(QPoint(80, 65));
    pointsPolygone->append(QPoint(100, 45));
    pointsPolygone->append(QPoint(40, 45));
    pointsPolygone->append(QPoint(45, 35));
    pointsPolygone->append(QPoint(55, 35));
    pointsPolygone->append(QPoint(60, 45));
    forme.addPolygon(QPolygonF(*pointsPolygone));
    return forme;
    }

    QRectF Tank::boundingRect() const
    {
    return QRect(0, 0, 100, 65);
    }

    bool Map::collidesWithItem(const QGraphicsItem * other, Qt::ItemSelectionMode mode) const
    {
    QRectF rectangleForme = other->mapRectToScene((other->boundingRect()));
    QPointF pointSupGauche = rectangleForme.topLeft();
    QPointF pointSupDroit = rectangleForme.topRight();
    QPointF pointInfGauche = rectangleForme.bottomLeft();
    QPointF pointInfDroit = rectangleForme.bottomRight();
    QPointF pointMillieu = rectangleForme.center();
    QPointF* pointEnCoursTraitement;

    for (int i = 0; i < 5; i++)
    {
    if (i == 0)
    {
    pointEnCoursTraitement = &pointSupGauche;
    }
    else if (i == 1)
    {
    pointEnCoursTraitement = &pointSupDroit;
    }
    else if (i == 2)
    {
    pointEnCoursTraitement = &pointInfGauche;
    }
    else if (i == 3)
    {
    pointEnCoursTraitement = &pointInfDroit;
    }
    else if (i == 4)
    {
    pointEnCoursTraitement = &pointMillieu;
    }

    int x = pointEnCoursTraitement->rx();
    int y = pointEnCoursTraitement->ry();
    if (x < 0 || x > largeur || y < 0 || y > hauteur)
    {
        continue;
    }
    else
    {
        vector<ligneVerticale*>* trancheVerticale = &(pointsMap->operator[](x));
        int taille = trancheVerticale->size();
        for (int i = 0; i < taille; i++)
        {
            ligneVerticale* sousLigne = trancheVerticale->operator[](i);
            if (y >= sousLigne->ymin && y <= sousLigne->ymax)
            {
                return true;
            }
        }
    }
    

    }
    return false;
    }

    QRectF Map::boundingRect() const
    {
    return QRect(0, 0, largeur, hauteur);
    }

    I also got the following problem: even though AnimationTir::paint([...]) get called I can't see anything on the scene (it should the pos() of a new AnimationTir is right in front of the muzzle of a tank and it move slowly from there).

    void AnimationTir::paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget)
    {
    painter->setBrush(Qt::gray);
    AnimationTir* f = this;
    QPointF posi = this->pos();
    painter->drawEllipse(pos().rx(), pos().ry(), 10, 10);
    //painter->drawRect(pos().rx(), pos().ry(), tailleRectangle, tailleRectangle);
    }

    Thanks!!!



  • Look at this:

    @nicolas565 said:

    QPainterPath Tank::shape() const
    {
    QPainterPath forme;
    QVector<QPointF>* pointsPolygone; // A pointer but no memory



  • Thanks. Fixed. How just got rid of that damn pointer.



Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.