要求:按空格鍵,玩家發射子彈,子彈(長條形)從玩家(player,底邊上的大正方形)所在位置自行向上運動。而敵人(小正方形)在檢視窗體頂部的隨機位置出現,並且自動向下運動。如果子彈和敵人兩個物件發生碰撞那麼,子彈和敵人一塊報銷(delete);如果沒遇到敵人,子彈離開檢視窗體邊界時被delete以節省記憶體。
程式設計要點:
1. 一個類要用到connect函式,那麼這個類就需要做到三點:
(1)類的標頭檔案需要#include <QObject>
(2)除了繼承QGraphicsRectItem類,還必須繼承QObject類
(3)類的定義中,必須用到Q_OBJECT宏
2. 子彈圖項自動運動,透過定時器QTimer,connect槽函式move()實現。敵人圖項也是如此。
3. 設定圖項(玩家)的焦點特性,然後才可以接受鍵盤事件、滑鼠事件。按空格鍵發射子彈,建立子彈圖項後,用scene()方法返回場景的指標,從而將子彈新增到場景中去, scene( )->addItem(item).
4. 鍵盤事件程式的重寫,用游標鍵控制玩家的左右移動,用空格鍵發射子彈。
5. 為防止因為子彈和敵人運動導致場景不斷擴大,進而導致檢視窗體的捲軸不斷滾動,採取的辦法是設定檢視窗體為固定大小。
6. 子彈和敵人如果發生碰撞,場景首先remove它們,然後再delete它們。
7. 圖項(子彈、敵人)離開檢視窗體後,delete這些物件,以節省記憶體空間。
這裡給出子彈類的程式碼:
-----------------bullet.h------------------
#ifndef BULLET_H
#define BULLET_H
#include <QGraphicsRectItem>
#include <QObject>
class Bullet: public QObject,public QGraphicsRectItem
{
Q_OBJECT //因為bullet要用到connect()函式,要使用這個宏,同時類要繼承QObject類
public:
Bullet();
public slots:
void move(); //槽函式
};
#endif // BULLET_H
-----------------bullet.cpp------------------
#include "bullet.h"
#include "Enemy.h"
#include <QGraphicsRectItem>
#include <QTimer>
#include <QGraphicsItem>
#include <QObject>
#include <QGraphicsScene>
#include <QDebug>
#include <QList>
Bullet::Bullet()
{
setRect(0,0,10,50); //設定子彈的大小
QTimer *timer = new QTimer();
connect(timer,SIGNAL(timeout()),this,SLOT(move()));
timer->start(20); //每隔20ms, 定時器就會觸發,發出訊號,呼叫子彈運動的槽函式。
}
void Bullet::move() {
//獲取所有與子彈碰撞的物件的指標,並存儲在一個QList物件中
QList <QGraphicsItem*> colliding_items = collidingItems();
for(int i=0,n=colliding_items.size();i<n;i++)
{
/*if bullet collides with enemy,destroy them both
判斷這個物件的型別,是否Enemy */
if(typeid(*(colliding_items[i]))==typeid(Enemy))
{
//remove them both
scene()->removeItem(colliding_items[i]);
scene()->removeItem(this);
//delete them all
delete colliding_items[i]; //delete Enemy
delete this; //delete bullet
return;
}
}
//如果沒有發生碰撞,y座標減少10,即子彈向上運動10個畫素距離
setPos(x(),y()-10);
/*如果子彈沒發生碰撞,且離開檢視窗體範圍,場景就刪除子彈圖項,並delete子彈物件。
因為這裡場景、檢視的左上角都設為(0,0),檢視的頂端即子彈運動的邊界,其y座標為0,
小於0說明子彈已經出界了。
*/
if(this->pos().y()+this->rect().height()<0)
{
scene()->removeItem(this); //場景刪除子彈物件
delete this; //銷燬物件,釋放物件所佔用的記憶體空間。
qDebug()<<"bullet deleted";
}
}