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);
}Thanks!!!
-
Hi,
don't know what's going wrong, just notice one thing: Instead of inheriting from QObject and QGraphicsItem you can inherit from QGraphicsObject. -
Now all my classes use QGraphicsObject but I still get the same problem.
There is at most 8 QGraphicsObject in the whole scene. That's very strange.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);
} -
Ok fixed.