QGraphicsItem::collidingItems([...]) and QGraphicsScene::collidingItems([...])
-
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.