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

From Qt Wiki
Jump to navigation Jump to search
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:
=Simple example of game scene with QGraphicsScene=
{{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] ''[youtube.com]''
[http://www.youtube.com/watch?v=cofUk8BK7nE View example on Youtube]


==Main.cpp==


The main() method creates a scene and a QTimer. <br /> The timer calls Scene::advance() every 0.01 sec.
== Main.cpp ==


==The Scene==
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
''' has a counter m_TicTacTimer
** every 20th ticTac, a new mobile unit is created with a random position, direction and speed.
'''''' every 20th ticTac, a new mobile unit is created with a random position, direction and speed.
** dead units are removed from the item list
'''''' 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'''


==Towers==
<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 is performed by squared distance comparison
** Search stops when a first item is found
'''''' 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.
'''''' 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 “reload time” of 100ms
* 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'''<br />'''simpletower.cpp'''
'''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-&gt;drawEllipse(…) with a growing radius
* The explosion is drawn by painter->drawEllipse(…) with a growing radius
 
'''mobileunit.h'''
<code>#ifndef MOBILEUNIT_H
#define MOBILEUNIT_H


'''mobileunit.h'''<br />
#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'''


===Categories:===


* [[:Category:Developing with Qt|Developing_with_Qt]]
<code>#include "mobileunit.h"
** [[:Category:Developing with Qt::Games|Games]]
#include <QPainter>
* [[:Category:Learning|Learning]]
#include <QGraphicsScene>
** [[:Category:Learning::Demos and Examples|Demos_and_Examples]]
#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

View example on Youtube


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;
 }
}