本来想让子弹和目标相撞后,目标消失,出现新的目标,运行后,目标不消失,求高手指导,代码如下:
头文件:#ifndef CANNONFIELD_H
#define CANNONFIELD_H
#include <QtGui/QWidget>
#include <QLayout>
#include <QPaintEvent>
#include <QTimer>
using namespace std;
class CannonField :public QWidget
{
Q_OBJECT
public:
CannonField(QWidget *parent = 0 );
int angle()const;//定义一个角度值
int force()const;//定义一个力量值
public slots:
void setAngle(int angle);
void setForce(int force);
void shoot();//射击
void newTarget();//这个槽在新的位置生成一个新的目标
signals:
void angleChanged(int newAngle);
void forceChanged(int newForce);
void hit();//hit()信号是当炮弹击中目标的时候被发射的
void miss();//missed()信号是当炮弹移动超出了窗口部件的右面或者下面的边界时被发射的
private slots:
void moveShot();
protected:
void paintEvent(QPaintEvent *);
private:
void paintShot(QPainter *);
void paintCannon( QPainter * );
void paintTarget( QPainter * );//这个私有函数绘制目标
QRect barrelRect() const;
QRect targetRect() const;//这个私有函数返回一个封装了目标的矩形
QRect shotRect() const;
QRect cannonRect() const;
int currentAngle;
int currentForce;
int timerCount;//保留了射击进行后的时间
QTimer * autoshoottimer;
float shoot_currentAngle;//加农炮射击时的角度
float shoot_currentForce;//射击时加农炮的力量
QPoint target;//这个私有变量包含目标的中心点
};
#endif // CANNONFIELD_H
构造函数:
#include "cannonfield.h"
#include <QtGui/QApplication>
#include<QPainter>
#include <QBrush>
#include <QPen>
#include <QRect>
#include <QPixmap>
#include <math.h>
#include <QRegion>
#include <QPaintEvent>
#include <QPoint>
#include <QDateTime>
#include "stdlib.h"
#include "time.h"
CannonField::CannonField(QWidget *parent)
:QWidget(parent)
{
currentAngle = 45;
currentForce = 0;
timerCount = 0;
autoshoottimer = new QTimer(this);
connect(autoshoottimer,SIGNAL(timeout()),this,SLOT(moveShot()));//我们新的私有变量并且把QTimer::timeout()信号和我们的moveShot()槽相连。我们会在定时器超时的时候移动射击
setPalette(QPalette(QColor(250,250,100)));//自定义窗口颜色
setAutoFillBackground(true);//为填充
newTarget();//它为目标创建一个“随机的”位置
}
void CannonField::setAngle(int angle)
{
if(angle<5)
angle=5;
if(angle>70)
angle=70;
if (currentAngle == angle)
return;
currentAngle = angle;
update( cannonRect());//绘画事件发送到窗口部件之前指定的矩形将不会被擦去。这将会使绘画过程加速和平滑。
emit angleChanged(currentAngle);
}
void CannonField::setForce(int force)
{
if (force<0)
force = 0;
if (currentForce==force)
return;
currentForce=force;
emit forceChanged(force);
}//实现力量值,但不显示
QRect CannonField::cannonRect() const
{
QRect r(0,0,50,50);
r.moveBottomLeft(rect().bottomLeft());
return r;
}
void CannonField::shoot()
{
if(autoshoottimer->isActive())//子弹bu在空中
return;
timerCount = 0;//射击进行后的时间
shoot_currentAngle = currentAngle;
shoot_currentForce = currentForce;
autoshoottimer->start(40);
}
//只要炮弹不在空中,这个函数就会进行一次射击。timerCount 被重新设置为零。
//shoot_currentAngle 和shoot_currentForce 设置为当前加农炮的角度和力量。
void CannonField::moveShot()
{
QRegion r(shotRect());//首先我们使用QRegion 来保留旧的shotRect()
timerCount++;//用它来实现炮弹在它的轨迹中移动的每一步
QRect shotR = shotRect();
if(shotR.intersects(targetRect()))
{
autoshoottimer->stop();
emit hit();
}
//if 语句检查炮弹矩形和目标矩形是否相交。如果是的,炮弹击中了目标。我们停止射击定时器并且发射hit()信号来告诉外界目标已经被破坏,并返回
else if(shotR.x()>width()||shotR.y()>height())
{ autoshoottimer->stop();//如果炮弹已经移动到窗口部件的右面或者下面的边界,我们停止定时器或者添加新的shotRect()到QRegion。
emit miss();
}
else
{
r = r.unite(QRegion(shotR));
}
repaint(r);
}//moveShot()是一个移动射击的槽,当QTimer 开始的时候,每50 毫秒被调用一次。
void CannonField::paintCannon(QPainter *p)
{
QRect cr=cannonRect();
QPixmap pix(cr.size());
pix.fill(this,cr.topLeft());
QPainter painter(&pix);
//painter.begin(&pix);
//防闪屏
painter.setRenderHint(QPainter::Antialiasing,true);
painter.setPen(QPen(Qt::blue));
painter.setBrush(QBrush(QBrush(Qt::blue)));
painter.translate(0,pix.height()-1);
painter.drawPie(QRect(-35,-35,70,70),0,90*16);
painter.rotate(-currentAngle);
painter.drawRect(33,-4,15,8);
painter.end();
//painter.begin(this);
p->drawPixmap(cr.topLeft(),pix);
}
void CannonField::paintShot(QPainter *p)
{
p->setBrush(QBrush(Qt::black));
p->setPen(QPen(Qt::black));
p->drawRect(shotRect());
}//这个私有函数画一个黑色填充的矩形作为炮弹
void CannonField::paintEvent( QPaintEvent *e )
{ QRect updateR = e->rect();
QPainter p( this );
if ( updateR.intersects( cannonRect() ) )
paintCannon( &p );
if ( autoshoottimer->isActive() && updateR.intersects( shotRect() ) )
paintShot( &p );
//现在我们得到的新的矩形区域需要 绘画,检查加农炮和/或炮弹是否相交,并且如果需要的话,调用paintCannon()和/或paintShot()
//if( !e->rect().intersects(cannonRect()))
if (updateR.intersects(targetRect()))
paintTarget(&p);
// return;
}//判断各种相交情况
QRect CannonField::barrelRect() const
{
return QRect( 45, height() - 100, 15, 100 );
}
void CannonField::newTarget()
{
static bool first_time = TRUE;
if(first_time)
{
first_time = FALSE;//因为只有当这个函数第一次被调用的时候,我们在if 块中把first_time 设置为FALSE
QTime midnight (0,0,0);//然后我们创建一个QTime 对象midnight,它将会提供时间00:00:00
srand(midnight.secsTo(QTime::currentTime()));
}
QRegion r(targetRect());
target = QPoint(100+rand()%190,10+rand()%255);//使用rand()函数来获得随机整数
//我们把它放在一个矩形中(x=200,y=35,width=190,height=255),(例如,可能的x 和y 值是x=200~389 和y=35~289)
//在一个我们把窗口边界的下边界作为y 的零点,
//并且y 向上增加,X 轴向通常一样,左边界为零点,并且x 向右增加的坐标系统中
repaint(r.unite(targetRect()));
}
void CannonField::paintTarget(QPainter *p)
{
p->setBrush(QBrush(Qt::red));
p->setPen(QPen(Qt::black));
p->drawRect(targetRect());
}//这个私有函数绘制目标,一个由红色填充,有黑色边框的矩形
QRect CannonField::shotRect()const
{
const double gravity = 4;
double time = timerCount / 4.0;
double velocity = shoot_currentForce;
double radians = shoot_currentAngle*3.14159265/180;
double velx = velocity*cos( radians );
double vely = velocity*sin( radians );
double x0 = ( barrelRect().right() + 5 )*cos(radians);//运算公式使用的是有重力的环境下光滑运动的经典牛顿公式
double y0 = ( barrelRect().right() + 5 )*sin(radians);//运算公式使用的是有重力的环境下光滑运动的经典牛顿公式
double x = x0 + velx*time;
double y = y0 + vely*time - 0.5*gravity*time*time;//运算公式使用的是有重力的环境下光滑运动的经典牛顿公式
QRect r = QRect( 0, 0, 6, 6 );
r.moveCenter( QPoint(qRound(x), height() - 1 - qRound(y) ) );
return r;
}//这个私有函数计算炮弹的中心点并且返回封装炮弹的矩形。它除了使用自动增加所过去的时间的timerCount 之外,还使用初始时的加农炮的力量和角度
QRect CannonField::targetRect()const
{
QRect r(0,0,20,10);
r.moveCenter(QPoint(target.x(),height()-1-target.y()));
return r;
//这个私有函数返回封装目标的矩形。从newTarget()中所得的target 点使用0 点在窗口部件的下边界的y
}
补充:移动开发 , Qt