Qt wiki will be updated on October 12th 2023 starting at 11:30 AM (EEST) and the maintenance will last around 2-3 hours. During the maintenance the site will be unavailable.
Towers lasers and spacecrafts example: Difference between revisions
No edit summary |
(Removed from almost empty category Category:Developing with Qt::Games) |
||
(8 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
= | {{Cleanup | reason=Auto-imported from ExpressionEngine.}} | ||
= Simple example of game scene with QGraphicsScene = | |||
This simple example mostly shows how to deal with | This simple example mostly shows how to deal with | ||
Line 7: | Line 8: | ||
* QGraphicsItem::paint(…) | * QGraphicsItem::paint(…) | ||
==Overview== | == Overview == | ||
The example contains three classes with following responsabilities | The example contains three classes with following responsabilities | ||
* The scene is a QGraphicsScene | * The scene is a QGraphicsScene | ||
** Creates and deletes new items (towers and mobile units) | ** Creates and deletes new items (towers and mobile units) | ||
* Towers | * Towers | ||
Line 20: | Line 21: | ||
** Explode and die | ** Explode and die | ||
[http://www.youtube.com/watch?v=cofUk8BK7nE View example on Youtube] | [http://www.youtube.com/watch?v=cofUk8BK7nE View example on Youtube] | ||
== Main.cpp == | |||
The main() method creates a scene and a QTimer. | |||
The timer calls Scene::advance() every 0.01 sec. | |||
<code> | |||
#include <QtGui> | |||
#include "scene.h" | |||
#include "simpletower.h" | |||
int main(int argc, char '''argv) | |||
{ | |||
QApplication app(argc, argv); | |||
Scene scene; | |||
scene.setSceneRect(0,0,640,360); | |||
QGraphicsView view(&scene); | |||
QTimer timer; | |||
QObject::connect(&timer, SIGNAL (timeout()), &scene, SLOT (advance())); | |||
view.show(); | |||
timer.start(10); | |||
return app.exec(); | |||
} | |||
</code> | |||
== The Scene == | |||
* The scene constructor creates several towers | * The scene constructor creates several towers | ||
* Scene::advance() : | * Scene::advance() : | ||
''' has a counter m_TicTacTimer | |||
'''''' every 20th ticTac, a new mobile unit is created with a random position, direction and speed. | |||
'''''' dead units are removed from the item list | |||
'''scene.h''' | '''scene.h''' | ||
<code> | |||
#ifndef SCENE_H | |||
#define SCENE_H | |||
#include <QGraphicsScene> | |||
class Scene : public QGraphicsScene | |||
{ | |||
Q_OBJECT | |||
public: | |||
Scene(); | |||
public slots: | |||
void advance(); | |||
private: | |||
int m_TicTacTime; | |||
}; | |||
#endif // SCENE_H | |||
</code> | |||
'''scene.cpp''' | '''scene.cpp''' | ||
== | <code> | ||
#include "scene.h" | |||
#include "mobileunit.h" | |||
#include "simpletower.h" | |||
#include<QDebug> | |||
Scene::Scene() | |||
: QGraphicsScene() | |||
, m_TicTacTime(0) | |||
{ | |||
SimpleTower * simpleTower = new SimpleTower(); | |||
simpleTower->setPos(200.0, 100.0); | |||
addItem(simpleTower); | |||
simpleTower = new SimpleTower(); | |||
simpleTower->setPos(200.0, 180.0); | |||
addItem(simpleTower); | |||
simpleTower = new SimpleTower(); | |||
simpleTower->setPos(200.0, 260.0); | |||
addItem(simpleTower); | |||
simpleTower = new SimpleTower(); | |||
simpleTower->setPos(250.0, 050.0); | |||
addItem(simpleTower); | |||
simpleTower = new SimpleTower(); | |||
simpleTower->setPos(250.0, 310.0); | |||
addItem(simpleTower); | |||
simpleTower = new SimpleTower(); | |||
simpleTower->setPos(300.0, 110.0); | |||
addItem(simpleTower); | |||
simpleTower = new SimpleTower(); | |||
simpleTower->setPos(300.0, 250.0); | |||
addItem(simpleTower); | |||
simpleTower = new SimpleTower(); | |||
simpleTower->setPos(350.0, 180.0); | |||
addItem(simpleTower); | |||
} | |||
void Scene::advance() | |||
{ | |||
m_TicTacTime+''; | |||
// delete killed objects | |||
QGraphicsItem '''item=NULL; | |||
MobileUnit''' unit=NULL; | |||
int i=0; | |||
while (i<items().count()) | |||
{ | |||
item=items().at(i); | |||
unit=dynamic_cast<MobileUnit* > (item); | |||
if ( ( unit!=NULL) && (unit->isFinished()==true)) | |||
{ | |||
removeItem(item); | |||
delete unit; | |||
} | |||
elsei; | |||
} | |||
// Add new units every 20 tictacs | |||
if(m_TicTacTime % 20==0) | |||
{ | |||
// qDebug() << "add unit"; | |||
MobileUnit * mobileUnit= new MobileUnit(); | |||
qreal h=static_cast<qreal>( qrand() % static_cast<int>(height()) ); | |||
mobileUnit->setPos(width(), h); | |||
addItem(mobileUnit); | |||
} | |||
QGraphicsScene::advance(); | |||
update(); | |||
} | |||
</code> | |||
== Towers == | |||
* Towers search for nearby units | * Towers search for nearby units | ||
'''''' Search is performed by squared distance comparison | |||
'''''' Search stops when a first item is found | |||
'''''' Warning: n against n = O (n2) algorithm… Poor performances on large amount of items… but sufficient here. | |||
* Towers shoot the located item if any | * Towers shoot the located item if any | ||
* after shooting, a tower must wait until its weapon is reloaded : it requires a | * after shooting, a tower must wait until its weapon is reloaded : it requires a "reload time" of 100ms | ||
* The laser beam is drawn with lines of different thicknesses and colors | * The laser beam is drawn with lines of different thicknesses and colors | ||
'''simpletower.h'''< | '''simpletower.h''' | ||
<code> | |||
#ifndef SIMPLETOWER_H | |||
#define SIMPLETOWER_H | |||
#include <QtCore> | |||
#include <QGraphicsRectItem> | |||
class MobileUnit; | |||
class SimpleTower : public QGraphicsRectItem | |||
{ | |||
public: | |||
SimpleTower(); | |||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget '''widget); | |||
void advance(int phase); | |||
private: | |||
void searchTarget(); | |||
void shoot(); | |||
private: | |||
qreal m_DetectionDistance; | |||
QTime m_Time; | |||
int m_ReloadTime; | |||
bool m_ShootIsActive; | |||
MobileUnit''' m_Target; | |||
QImage m_TowerImage; | |||
}; | |||
#endif // SIMPLETOWER_H | |||
</code> | |||
'''simpletower.cpp''' | |||
<code> | |||
#include <QPainter> | |||
#include <QGraphicsScene> | |||
#include "simpletower.h" | |||
#include "mobileunit.h" | |||
SimpleTower::SimpleTower() | |||
: QGraphicsRectItem() | |||
, m_DetectionDistance(100.0) | |||
, m_Time(0, 0) | |||
, m_ReloadTime(100) | |||
, m_ShootIsActive(false) | |||
, m_Target(NULL) | |||
, m_TowerImage(QImage(":/lightTower")) | |||
{ | |||
setRect(–15.0, -15.0, 30.0, 30.0); | |||
m_Time.start(); | |||
} | |||
void SimpleTower::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget '''widget) | |||
{ | |||
painter->drawImage(–15,-15,m_TowerImage); | |||
if ( (m_Target!=NULL) && (m_ShootIsActive) ) | |||
{ // laser beam | |||
QPointF towerPoint = mapFromScene(pos()); | |||
QPointF target = mapFromScene(m_Target->pos()); | |||
painter->setPen(QPen(Qt::yellow,8.0,Qt::SolidLine)); | |||
painter->drawLine(towerPoint.x(), towerPoint.y(), target.x(), target.y()); | |||
painter->setPen(QPen(Qt::red,5.0,Qt::SolidLine)); | |||
painter->drawLine(towerPoint.x(), towerPoint.y(), target.x(), target.y()); | |||
painter->setPen(QPen(Qt::white,2.0,Qt::SolidLine)); | |||
painter->drawLine(towerPoint.x(), towerPoint.y(), target.x(), target.y()); | |||
m_ShootIsActive=false; | |||
} | |||
} | |||
void SimpleTower::advance(int phase) | |||
{ | |||
if (phase==0) | |||
{ | |||
searchTarget(); | |||
if ( (m_Target!=NULL) && (m_Time.elapsed()> m_ReloadTime) ) | |||
shoot(); | |||
} | |||
} | |||
void SimpleTower::searchTarget() | |||
{ | |||
m_Target=NULL; | |||
QList<QGraphicsItem''' > itemList = scene()->items(); | |||
int i = itemList.count()-1; | |||
qreal dx, dy, sqrDist; | |||
qreal sqrDetectionDist = m_DetectionDistance * m_DetectionDistance; | |||
MobileUnit * unit=NULL; | |||
while( (i>=0) && (NULL==m_Target) ) | |||
{ | |||
QGraphicsItem * item = itemList.at(i); | |||
unit = dynamic_cast<MobileUnit * >(item); | |||
if ( (unit!=NULL) && ( unit->lifePoints()>0 ) ) | |||
{ | |||
dx = unit->x()-x(); | |||
dy = unit->y()-y(); | |||
sqrDist = dx*dx+dy*dy; | |||
if (sqrDist < sqrDetectionDist) | |||
m_Target=unit; | |||
} | |||
—i; | |||
} | |||
} | |||
void SimpleTower::shoot() | |||
{ | |||
m_ShootIsActive=true; | |||
m_Target->touched(3); | |||
m_Time.restart(); | |||
} | |||
</code> | |||
==Mobile units== | == Mobile units == | ||
Life Cycle of a mobile unit : | Life Cycle of a mobile unit : | ||
Line 60: | Line 288: | ||
* The unit explodes when lifepoints are exhausted | * The unit explodes when lifepoints are exhausted | ||
* The explosion has a duration. | * The explosion has a duration. | ||
* The explosion is drawn by painter- | * The explosion is drawn by painter->drawEllipse(…) with a growing radius | ||
'''mobileunit.h''' | |||
<code>#ifndef MOBILEUNIT_H | |||
#define MOBILEUNIT_H | |||
#include <QtCore> | |||
#include <QGraphicsRectItem> | |||
#include <QRadialGradient> | |||
class MobileUnit : public QGraphicsRectItem | |||
{ | |||
public: | |||
MobileUnit(); | |||
inline int lifePoints() { return m_LifePoints; } | |||
inline bool isFinished() const { return m_IsFinished; } | |||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); | |||
void advance(int phase); | |||
void touched (int hurtPoints); | |||
private: | |||
int m_LifePoints; | |||
qreal m_Alpha; | |||
qreal m_DirX; | |||
qreal m_DirY; | |||
qreal m_Speed; | |||
bool m_IsFinished; | |||
bool m_IsExploding; | |||
int m_ExplosionDuration; | |||
QRadialGradient m_RedExplosion; | |||
QTime m_Time; | |||
QImage m_SpacecraftImage; | |||
}; | |||
#endif // MOBILEUNIT_H | |||
</code> | |||
'''mobileunit.cpp''' | '''mobileunit.cpp''' | ||
<code>#include "mobileunit.h" | |||
** | #include <QPainter> | ||
* | #include <QGraphicsScene> | ||
** [[ | #include <math.h> | ||
MobileUnit::MobileUnit() | |||
: QGraphicsRectItem() | |||
, m_LifePoints(10) | |||
, m_Alpha(0) | |||
, m_DirX(1.0) | |||
, m_DirY(0.0) | |||
, m_Speed(1.0) | |||
, m_IsFinished(false) | |||
, m_IsExploding(false) | |||
, m_ExplosionDuration(500) | |||
, m_RedExplosion(0.0, 0.0, 20.0, 0.0, 0.0) | |||
, m_Time(0, 0) | |||
, m_SpacecraftImage(QImage(":/spacecraft00") ) | |||
{ | |||
m_Alpha= static_cast<qreal> (qrand()%90+60); | |||
qreal speed= static_cast<qreal> (qrand()%10-5); | |||
m_DirY=cos(m_Alpha/180.0*M_PI ); | |||
m_DirX=sin(m_Alpha/180.0*M_PI); | |||
m_Alpha= -m_Alpha'' 180.0 ; | |||
m_Speed=1.0+speed*0.1; | |||
setRect(–10.0, -10.0, 20.0, 20.0); | |||
m_Time.start(); | |||
m_RedExplosion.setColorAt(0.0, Qt::white); | |||
m_RedExplosion.setColorAt(0.2, QColor(255, 255, 100, 255)); | |||
m_RedExplosion.setColorAt(0.4, QColor(255, 80, 0, 200)); | |||
m_RedExplosion.setColorAt(1.0, QColor(255, 255, 255, 0)); | |||
} | |||
void MobileUnit::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) | |||
{ | |||
painter->setPen(Qt::NoPen); | |||
if (!m_IsExploding) | |||
{ | |||
painter->rotate(m_Alpha); | |||
painter->drawImage(–15,-14, m_SpacecraftImage); | |||
} | |||
else | |||
{ | |||
painter->setBrush(QBrush(m_RedExplosion)); | |||
qreal explosionRadius= 8.0 + m_Time.elapsed() / 50; | |||
painter->drawEllipse(-explosionRadius, -explosionRadius, 2.0*explosionRadius, 2.0*explosionRadius); | |||
} | |||
} | |||
void MobileUnit::advance(int phase) | |||
{ | |||
if (phase==0) | |||
{ | |||
qreal xx=x(); qreal yy=y(); | |||
if ( (xx<0.0) || (xx > scene()->width() ) ) | |||
{ // rebond | |||
m_DirX=-m_DirX; | |||
m_Alpha=-m_Alpha; | |||
} | |||
if ( (yy<0.0) || (yy > scene()->height())) | |||
{ // rebond | |||
m_DirY=-m_DirY; | |||
m_Alpha=180-m_Alpha; | |||
} | |||
if (m_IsExploding) | |||
{ | |||
m_Speed*=0.98; // decrease speed | |||
if (m_Time.elapsed() > m_ExplosionDuration) | |||
m_IsFinished=true; // is dead | |||
} | |||
setPos(x()+m_DirX*m_Speed, y()+m_DirY*m_Speed); | |||
} | |||
} | |||
void MobileUnit::touched (int hurtPoints) | |||
{ | |||
m_LifePoints-=hurtPoints; // decrease life | |||
if (m_LifePoints<0) m_LifePoints=0; | |||
if (m_LifePoints==0) | |||
{ | |||
m_Time.start(); | |||
m_IsExploding=true; | |||
} | |||
} | |||
</code> | |||
[[Category:Learning::Demos_and_Examples]] |
Latest revision as of 12:34, 24 May 2015
This article may require cleanup to meet the Qt Wiki's quality standards. Reason: Auto-imported from ExpressionEngine. Please improve this article if you can. Remove the {{cleanup}} tag and add this page to Updated pages list after it's clean. |
Simple example of game scene with QGraphicsScene
This simple example mostly shows how to deal with
- QGraphicsScene::advance()
- QGraphicsItem::advance()
- QGraphicsItem::paint(…)
Overview
The example contains three classes with following responsabilities
- The scene is a QGraphicsScene
- Creates and deletes new items (towers and mobile units)
- Towers
- search for nearby units
- shoot them if any
- Mobile units (fighters)
- Move
- Explode and die
Main.cpp
The main() method creates a scene and a QTimer. The timer calls Scene::advance() every 0.01 sec.
#include <QtGui>
#include "scene.h"
#include "simpletower.h"
int main(int argc, char '''argv)
{
QApplication app(argc, argv);
Scene scene;
scene.setSceneRect(0,0,640,360);
QGraphicsView view(&scene);
QTimer timer;
QObject::connect(&timer, SIGNAL (timeout()), &scene, SLOT (advance()));
view.show();
timer.start(10);
return app.exec();
}
The Scene
- The scene constructor creates several towers
- Scene::advance() :
has a counter m_TicTacTimer ' every 20th ticTac, a new mobile unit is created with a random position, direction and speed. ' dead units are removed from the item list
scene.h
#ifndef SCENE_H
#define SCENE_H
#include <QGraphicsScene>
class Scene : public QGraphicsScene
{
Q_OBJECT
public:
Scene();
public slots:
void advance();
private:
int m_TicTacTime;
};
#endif // SCENE_H
scene.cpp
#include "scene.h"
#include "mobileunit.h"
#include "simpletower.h"
#include<QDebug>
Scene::Scene()
: QGraphicsScene()
, m_TicTacTime(0)
{
SimpleTower * simpleTower = new SimpleTower();
simpleTower->setPos(200.0, 100.0);
addItem(simpleTower);
simpleTower = new SimpleTower();
simpleTower->setPos(200.0, 180.0);
addItem(simpleTower);
simpleTower = new SimpleTower();
simpleTower->setPos(200.0, 260.0);
addItem(simpleTower);
simpleTower = new SimpleTower();
simpleTower->setPos(250.0, 050.0);
addItem(simpleTower);
simpleTower = new SimpleTower();
simpleTower->setPos(250.0, 310.0);
addItem(simpleTower);
simpleTower = new SimpleTower();
simpleTower->setPos(300.0, 110.0);
addItem(simpleTower);
simpleTower = new SimpleTower();
simpleTower->setPos(300.0, 250.0);
addItem(simpleTower);
simpleTower = new SimpleTower();
simpleTower->setPos(350.0, 180.0);
addItem(simpleTower);
}
void Scene::advance()
{
m_TicTacTime+'';
// delete killed objects
QGraphicsItem '''item=NULL;
MobileUnit''' unit=NULL;
int i=0;
while (i<items().count())
{
item=items().at(i);
unit=dynamic_cast<MobileUnit* > (item);
if ( ( unit!=NULL) && (unit->isFinished()==true))
{
removeItem(item);
delete unit;
}
elsei;
}
// Add new units every 20 tictacs
if(m_TicTacTime % 20==0)
{
// qDebug() << "add unit";
MobileUnit * mobileUnit= new MobileUnit();
qreal h=static_cast<qreal>( qrand() % static_cast<int>(height()) );
mobileUnit->setPos(width(), h);
addItem(mobileUnit);
}
QGraphicsScene::advance();
update();
}
Towers
- Towers search for nearby units
' Search is performed by squared distance comparison ' Search stops when a first item is found ' Warning: n against n = O (n2) algorithm… Poor performances on large amount of items… but sufficient here.
- Towers shoot the located item if any
- after shooting, a tower must wait until its weapon is reloaded : it requires a "reload time" of 100ms
- The laser beam is drawn with lines of different thicknesses and colors
simpletower.h
#ifndef SIMPLETOWER_H
#define SIMPLETOWER_H
#include <QtCore>
#include <QGraphicsRectItem>
class MobileUnit;
class SimpleTower : public QGraphicsRectItem
{
public:
SimpleTower();
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget '''widget);
void advance(int phase);
private:
void searchTarget();
void shoot();
private:
qreal m_DetectionDistance;
QTime m_Time;
int m_ReloadTime;
bool m_ShootIsActive;
MobileUnit''' m_Target;
QImage m_TowerImage;
};
#endif // SIMPLETOWER_H
simpletower.cpp
#include <QPainter>
#include <QGraphicsScene>
#include "simpletower.h"
#include "mobileunit.h"
SimpleTower::SimpleTower()
: QGraphicsRectItem()
, m_DetectionDistance(100.0)
, m_Time(0, 0)
, m_ReloadTime(100)
, m_ShootIsActive(false)
, m_Target(NULL)
, m_TowerImage(QImage(":/lightTower"))
{
setRect(–15.0, -15.0, 30.0, 30.0);
m_Time.start();
}
void SimpleTower::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget '''widget)
{
painter->drawImage(–15,-15,m_TowerImage);
if ( (m_Target!=NULL) && (m_ShootIsActive) )
{ // laser beam
QPointF towerPoint = mapFromScene(pos());
QPointF target = mapFromScene(m_Target->pos());
painter->setPen(QPen(Qt::yellow,8.0,Qt::SolidLine));
painter->drawLine(towerPoint.x(), towerPoint.y(), target.x(), target.y());
painter->setPen(QPen(Qt::red,5.0,Qt::SolidLine));
painter->drawLine(towerPoint.x(), towerPoint.y(), target.x(), target.y());
painter->setPen(QPen(Qt::white,2.0,Qt::SolidLine));
painter->drawLine(towerPoint.x(), towerPoint.y(), target.x(), target.y());
m_ShootIsActive=false;
}
}
void SimpleTower::advance(int phase)
{
if (phase==0)
{
searchTarget();
if ( (m_Target!=NULL) && (m_Time.elapsed()> m_ReloadTime) )
shoot();
}
}
void SimpleTower::searchTarget()
{
m_Target=NULL;
QList<QGraphicsItem''' > itemList = scene()->items();
int i = itemList.count()-1;
qreal dx, dy, sqrDist;
qreal sqrDetectionDist = m_DetectionDistance * m_DetectionDistance;
MobileUnit * unit=NULL;
while( (i>=0) && (NULL==m_Target) )
{
QGraphicsItem * item = itemList.at(i);
unit = dynamic_cast<MobileUnit * >(item);
if ( (unit!=NULL) && ( unit->lifePoints()>0 ) )
{
dx = unit->x()-x();
dy = unit->y()-y();
sqrDist = dx*dx+dy*dy;
if (sqrDist < sqrDetectionDist)
m_Target=unit;
}
—i;
}
}
void SimpleTower::shoot()
{
m_ShootIsActive=true;
m_Target->touched(3);
m_Time.restart();
}
Mobile units
Life Cycle of a mobile unit :
- A mobile unit is created with 10 life points
- Position changes according to predefined direction and speed
- It loses life points if touched by a laser beam
- The unit explodes when lifepoints are exhausted
- The explosion has a duration.
- The explosion is drawn by painter->drawEllipse(…) with a growing radius
mobileunit.h
#ifndef MOBILEUNIT_H
#define MOBILEUNIT_H
#include <QtCore>
#include <QGraphicsRectItem>
#include <QRadialGradient>
class MobileUnit : public QGraphicsRectItem
{
public:
MobileUnit();
inline int lifePoints() { return m_LifePoints; }
inline bool isFinished() const { return m_IsFinished; }
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
void advance(int phase);
void touched (int hurtPoints);
private:
int m_LifePoints;
qreal m_Alpha;
qreal m_DirX;
qreal m_DirY;
qreal m_Speed;
bool m_IsFinished;
bool m_IsExploding;
int m_ExplosionDuration;
QRadialGradient m_RedExplosion;
QTime m_Time;
QImage m_SpacecraftImage;
};
#endif // MOBILEUNIT_H
mobileunit.cpp
#include "mobileunit.h"
#include <QPainter>
#include <QGraphicsScene>
#include <math.h>
MobileUnit::MobileUnit()
: QGraphicsRectItem()
, m_LifePoints(10)
, m_Alpha(0)
, m_DirX(1.0)
, m_DirY(0.0)
, m_Speed(1.0)
, m_IsFinished(false)
, m_IsExploding(false)
, m_ExplosionDuration(500)
, m_RedExplosion(0.0, 0.0, 20.0, 0.0, 0.0)
, m_Time(0, 0)
, m_SpacecraftImage(QImage(":/spacecraft00") )
{
m_Alpha= static_cast<qreal> (qrand()%90+60);
qreal speed= static_cast<qreal> (qrand()%10-5);
m_DirY=cos(m_Alpha/180.0*M_PI );
m_DirX=sin(m_Alpha/180.0*M_PI);
m_Alpha= -m_Alpha'' 180.0 ;
m_Speed=1.0+speed*0.1;
setRect(–10.0, -10.0, 20.0, 20.0);
m_Time.start();
m_RedExplosion.setColorAt(0.0, Qt::white);
m_RedExplosion.setColorAt(0.2, QColor(255, 255, 100, 255));
m_RedExplosion.setColorAt(0.4, QColor(255, 80, 0, 200));
m_RedExplosion.setColorAt(1.0, QColor(255, 255, 255, 0));
}
void MobileUnit::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
painter->setPen(Qt::NoPen);
if (!m_IsExploding)
{
painter->rotate(m_Alpha);
painter->drawImage(–15,-14, m_SpacecraftImage);
}
else
{
painter->setBrush(QBrush(m_RedExplosion));
qreal explosionRadius= 8.0 + m_Time.elapsed() / 50;
painter->drawEllipse(-explosionRadius, -explosionRadius, 2.0*explosionRadius, 2.0*explosionRadius);
}
}
void MobileUnit::advance(int phase)
{
if (phase==0)
{
qreal xx=x(); qreal yy=y();
if ( (xx<0.0) || (xx > scene()->width() ) )
{ // rebond
m_DirX=-m_DirX;
m_Alpha=-m_Alpha;
}
if ( (yy<0.0) || (yy > scene()->height()))
{ // rebond
m_DirY=-m_DirY;
m_Alpha=180-m_Alpha;
}
if (m_IsExploding)
{
m_Speed*=0.98; // decrease speed
if (m_Time.elapsed() > m_ExplosionDuration)
m_IsFinished=true; // is dead
}
setPos(x()+m_DirX*m_Speed, y()+m_DirY*m_Speed);
}
}
void MobileUnit::touched (int hurtPoints)
{
m_LifePoints-=hurtPoints; // decrease life
if (m_LifePoints<0) m_LifePoints=0;
if (m_LifePoints==0)
{
m_Time.start();
m_IsExploding=true;
}
}