基于QT的C++的坦克大战游戏

近期培训期间做的基于C++的坦克小游戏,欢迎评论。

首先是主驱动部分:tankclient.h,和tankclient.cpp

tankclient.h部分

#ifndef TANKCLIENT_H

#define TANKCLIENT_H
#include <QtGui/QMainWindow>
class Tank;//前置申明
class Missile;
class explode;
class TankClient : public QMainWindow
{
    Q_OBJECT
public:
    TankClient(QWidget *parent = 0);
    ~TankClient();
    //画出图形的方法
    void paintEvent(QPaintEvent *);
    //定义坦克初始坐标
    //static const int才能初始化
    //int x,y;
    //定义定时器的方法
    void timerEvent(QTimerEvent *);
    //定义键盘事件(压下)方法
    void keyPressEvent(QKeyEvent *);
    //定义键盘事件(松开)方法
    void keyReleaseEvent(QKeyEvent *);
    //持有一枚主站坦克
    Tank* tank;
    //持有装在子弹的集合(模板)
    QList<Missile*> missiles;
    //持有10辆敌军坦克
    QList<Tank*> etanks;
    //持有爆炸的集合
    QList<explode*> explodes;
    //定义游戏的分辨率
    static const int GAME_W=500;
    static const int GAME_H=400;
};

#endif // TANKCLIENT_H

tankclient.cpp部分

#include "tankclient.h"
#include <QtGui>  //总的GUI函数的库文件
#include "tank.h"
#include "missile.h"
#include"explode.h"


TankClient::TankClient(QWidget *parent)
    : QMainWindow(parent)
{
    //创建窗体 ALT+/自动补全
    //默认快捷方式ctrl+space
    //设置标题
     setWindowTitle(tr("坦克大战"));
     //设置大小
     setFixedSize(GAME_W,GAME_H);
     //设置背景
     setStyleSheet("background-color:black");
     //初始化坐标
     //x=200;
     //y=200;
     //启动定时器
     startTimer(50);//参数:long(毫秒)
     //初始化主站坦克
     tank=new Tank(200,200,30,30,this,true);
     //初始化敌军坦克
          for(int i=0;i<10;++i){
               Tank* t=
                       new Tank(30+40*i,350,30,30,this,false);
               etanks.push_back(t);
          }
 }
//实现画图的方法
//当界面刷新的时候被系统自己调用
void TankClient::paintEvent(QPaintEvent *){
    //输出
    qDebug("paint...");
    //创建画布对象
    QPainter p(this);
    //显示子弹的个数
        p.setPen(Qt::white);
        p.drawText(0,15,tr("子弹的个数:")+QString::number(missiles.size()));
    //画出主站坦克
    tank->draw(p);


    //画出子弹
    for(int i=0;i<missiles.size();i++){
        //取出每一个子弹依次画出来
        Missile* m=missiles[i];
        m->draw(p);
        //调用hitTanks
        m->hitTanks(etanks);
        m->hitTank(tank);
    }
    //画出敌军坦克
    for(int i=0;i<etanks.size();i++){
        Tank* t = etanks[i];
        t->draw(p);
    }
    //画出爆炸效果
    for(int i=0;i<explodes.size();i++){
        explode* e = explodes[i];
        e->draw(p);
    }




    //假设界面刷新的时候向右移动
    //采用定时器或者多线程Thread
    //x+=1;
}


//定义定时器的方法
void TankClient::timerEvent(QTimerEvent *){
    //调用paintEvent方法
    repaint();//reset+paint 重绘
}


//定义键盘事件(压下)方法
void TankClient::keyPressEvent(QKeyEvent *e){
    //获取键盘的ASCII(中 日本 韩)码
    //合资项目(外包项目)
    //整理代码:ctrl+i
    int key=e->key();
    if(tank->live)
    tank->keyPress(key);
}
//定义键盘事件(松开)方法
void TankClient::keyReleaseEvent(QKeyEvent *e){
    int key=e->key();
    //调用tank里面抬起方法
    if(tank->live)
    tank->keyRePress(key);
}


TankClient::~TankClient()
{


}


然后是Tank部分

tank.h部分

#ifndef TANK_H
#define TANK_H
#include <QtGui>
#include "pub.h"//usr/bin/include


class TankClient;


class Tank
{
public:
    Tank(int x,int y,
         int w,int h,TankClient *tc,bool good);
    //属性
    //朝某一个方向随机走的步数
    int step;
    //方向
    Dir dir;
    //炮筒的方向
    Dir ptDir;
    //四个按键
    bool bu,bd,bl,br;
    //坐标
    int x,y;
    //宽高(半径)
    int w,h;


    //颜色
    bool good;


    //存活
    bool live;


    //方法
    //画
    void draw(QPainter&p);
    //键盘压下
    void keyPress(int key);
    //键盘松开
    void keyRePress(int key);
    //通过键盘的2个事件
    //确定四个按钮的状态方法
    void confimDir();
    //移动
    void move();
    //开火
    void fire(Dir ptDir);
    void firePlus();
    //持有TankClient
    TankClient* tc;
    //求出当前的外切四边形
    QRect getRect();


};


#endif // TANK_H


tank.cpp部分

#include "tank.h"
#include"tankclient.h"


Tank::Tank(int x, int y,
           int w, int h,TankClient* tc,bool good)
{
        this->x=x;
        this->y=y;
        this->w=w;
        this->h=h;
        this->tc=tc;
        this->good = good;
        //初始方向默认为朝下
        dir=STOP;
        //初始化四个按键默认值
        bu=bd=bl=br=false;
        //炮筒的默认方向
        ptDir=U;
        live = true;
        step = qrand()%15+3;//(3,17)
}
//画(成员方法 this:当前对象)
void Tank::draw(QPainter&q){
    if(!live){
        tc->etanks.removeOne(this);
        return;
    }
    if(good){
        //设置颜色
        q.setPen(Qt::red);
        //设置填充的颜色
        q.setBrush(Qt::red);
    }else{
        //设置颜色
        q.setPen(Qt::blue);
        //设置填充的颜色
        q.setBrush(Qt::blue);
    }
    //画出实心坦克 oval Iamge Rect
    q.drawEllipse(x,y,w,h);


    //坦克的方向发生改变,就移动dir
    move();


    //画出炮筒
    if(dir!=STOP){
        ptDir=dir;
    }
    //根据炮筒方向画出直线
    q.setPen(Qt::white);
    switch(ptDir){
        case U:q.drawLine(x+w/2,y+h/2,x+w/2,y);break;
        case D:q.drawLine(x+w/2,y+h/2,x+w/2,y+h);break;
        case L:q.drawLine(x+w/2,y+h/2,x,y+h/2);break;
        case R:q.drawLine(x+w/2,y+h/2,x+w,y+h/2);break;
        case LU:q.drawLine(x+w/2,y+h/2,x,y);break;
        case LD:q.drawLine(x+w/2,y+h/2,x,y+h);break;
        case RU:q.drawLine(x+w/2,y+h/2,x+w,y);break;
        case RD:q.drawLine(x+w/2,y+h/2,x+w,y+h);break;
    default:break;
        }


}
//键盘压下
void Tank::keyPress(int key){
    switch(key){
        case Qt::Key_Up:bu=true;break;
        case Qt::Key_Down:bd=true;break;
        case Qt::Key_Left:bl=true;break;
        case Qt::Key_Right:br=true;break;
        case Qt::Key_F:fire(ptDir);break;//开火
    case Qt::Key_A:firePlus();break;
    default:break;
    }
    confimDir();
}


void Tank::firePlus(){
    for(int i=0;i<8;i++){
        fire(Dir(i));
    }
}


//键盘松开
void Tank::keyRePress(int key){
    switch(key){
        case Qt::Key_Up:bu=false;break;
        case Qt::Key_Down:bd=false;break;
        case Qt::Key_Left:bl=false;break;
        case Qt::Key_Right:br=false;break;
    default:break;
    }
    confimDir();
}
//通过键盘的2个事件
//确定四个按钮的状态方法
void Tank::confimDir(){
    if(bu&&!bd&&!bl&&!br)dir=U;
    else if(!bu&&bd&&!bl&&!br)dir=D;
    else if(!bu&&!bd&&bl&&!br)dir=L;
    else if(!bu&&!bd&&!bl&&br)dir=R;
    else if(bu&&!bd&&bl&&!br)dir=LU;
    else if(!bu&&bd&&bl&&!br)dir=LD;
    else if(bu&&!bd&&!bl&&br)dir=RU;
    else if(!bu&&bd&&!bl&&br)dir=RD;
    else dir=STOP;
    //move(); 不科学
}
#include "tankclient.h"//不建议
//移动
void Tank::move(){
    switch(dir){
        case U:y-=5;break;
        case D:y+=5;break;
        case L:x-=5;break;
        case R:x+=5;break;
        case LU:x-=5;y-=5;break;
        case LD:x-=5;y+=5;break;
        case RU:x+=5;y-=5;break;
        case RD:x+=5;y+=5;break;
    default:break;
    }
    //处理坦克遇到边界的情况
    if(x<=0)x=0;//左
    if(y<=5)y=5;//上
    if(x>=TankClient::GAME_W-w)
        x=TankClient::GAME_W-w;//右
    if(y>=TankClient::GAME_H-h)
        y=TankClient::GAME_H-h;//下


    //让敌军坦克智能化
    if(!good){
        //随机开火
        if(qrand()%40>37)fire(ptDir);
        if(step ==0 ){
            //朝一个方向走的步数剩下为0
            dir = Dir(qrand()%9);
            step = qrand()%15+3;
        }
        step--;
    }


}
#include "missile.h"
//坦克开火
void  Tank::fire(Dir ptDir){
    //思路:F-->new Missile-->画出来(QPainter p)
    Missile* m=new Missile(x+w/2,y+h/2,w/5,h/5,ptDir,tc,good);
    //m应该注入到tankClient里面missiles集合
    tc->missiles.push_back(m);
}
//求出当前的外切四边形
QRect Tank::getRect(){
        return QRect(x,y,w,h);
    }


之后是炮弹部分missile

missile.h部分

#ifndef MISSILE_H
#define MISSILE_H
#include "pub.h"
#include <QtGui>


class TankClient;
class Tank;


class Missile
{
public:
    Missile(int x,int y,int w,int h,Dir dir,TankClient *tc,bool good);
    //坐标
    int x,y;
    //宽高
    int w,h;
    //方向
    Dir dir;
    //存活
    bool live;
    //好坏
    bool good;


    //画图
    void draw(QPainter&p);
    //移动
    void move();
    //求出当前的外切四边形
    QRect getRect();
    //一枚子弹打击一辆坦克
    bool hitTank(Tank *t);


    TankClient *tc;


    //所有的子弹去打击所有敌军坦克
    void hitTanks(QList<Tank*> etanks);




};


#endif // MISSILE_H

missile.cpp

部分

#include "missile.h"
#include"tankclient.h"
#include"explode.h"


Missile::Missile(int x, int y, int w, int h, Dir dir,TankClient *tc,bool good)
{
    //属性
    this->x=x;
    this->y=y;
    this->w=w;
    this->h=h;
    this->dir=dir;
    this->tc = tc;
    this->live= true;
    this->good = good;
}


//画图
void Missile::draw(QPainter&p){
    if(!live){
            //死亡
            //删除集合中的子弹
            tc->missiles.removeOne(this);
            return;
        }
    if(good){
        //设置画笔
        p.setPen(Qt::red);
        //填充颜色
        p.setBrush(Qt::red);
    }else{
        //设置画笔
        p.setPen(Qt::blue);
        //填充颜色
        p.setBrush(Qt::blue);
    }


    //画出图形
    p.drawEllipse(x,y,w,h);


    move();
}
//移动
//ctrl+F/ctrl+R置换
void Missile::move(){
    switch(dir){
        case U:y-=20;break;
        case D:y+=20;break;
        case L:x-=20;break;
        case R:x+=20;break;
        case LU:x-=20;y-=20;break;
        case LD:x-=20;y+=20;break;
        case RU:x+=20;y-=20;break;
        case RD:x+=20;y+=20;break;
    default:break;
    }
    //处理子弹遇到边界
        if(x<=0 || y<=0
           || x>=TankClient::GAME_W-w
           || y>=TankClient::GAME_H-h)


           live=false;


}
//求出当前的外切四边形
QRect Missile::getRect(){
        return QRect(x,y,w,h);
    }
#include"tank.h"
//一枚子弹打击一辆坦克
bool Missile::hitTank(Tank *t){
    if(t->live&&this->good!=t->good&&this->getRect().intersects(t->getRect())){
        //子弹和坦克都死亡
        this->live = false;
        t->live = false;


        //创建一个爆炸效果
        explode* e = new explode(x,y,w,h,tc);
        //装到explodes
        tc->explodes.push_back(e);


        return true;
    }
    return false;
}


//所有的子弹去打击所有敌军坦克
void Missile::hitTanks(QList<Tank*> etanks){
    for(int i=0;i<etanks.size();i++){
        Tank *t = etanks[i];
        if(hitTank(t))
            return;
    }


}


之后是爆炸效果部分:

头文件:

#ifndef EXPLODE_H
#define EXPLODE_H
#include <QtGui>
class TankClient;
class explode
{
public:
    explode(int x,int y,int w,int h,TankClient* tc);
    //坐标,宽高
    int x,y,w,h;
    //画
    void draw(QPainter &p);
    //存活
    bool live;
    //半径的数组
    int ds[10];
    //索引(当下的数组)
    int index;


    TankClient* tc;
};


#endif // EXPLODE_H


cpp文件


#include "explode.h"
#include"tankclient.h"


explode::explode(int x,int y,int w,int h,TankClient* tc)
{
    this->x = x;
    this->y = y;
    this->w = w;
    this->h = h;
    this->tc = tc;
    live = true;
    index = 0;
    //初始化数组
    int ids[]={10,20,40,80,200,100,70,40,20,10};
    for(int i=0;i<10;i++){
        ds[i] = ids[i];
    }


}
void explode::draw(QPainter &p){
    //处理死亡
    if(!live){
        tc->explodes.removeOne(this);
        return;
    }
    //画出爆炸
    p.setPen(Qt::yellow);
    p.setBrush(Qt::yellow);
    p.drawEllipse(x,y,ds[index],ds[index]);
    index++;
    //判断极限
    if(index == 10){
        live = false;
    }
}

最后就是一些定义和主函数:

#ifndef PUB_H
#define PUB_H
//定义坦克的方向
typedef enum Dir{
    U,D,L,R,LU,LD,RU,RD,STOP
}Dir;


#endif // PUB_H


#include <QtGui/QApplication>
#include "tankclient.h"
#include <QTextCodec>


int main(int argc, char *argv[])
{
    //解决编码问题
    //QT本地的编码是 中文繁体 big5
    //GBK  GB2312 中文简体 oracle/mysql/sqlite/c++
    //ISO-8859-1  西欧 JAVAWEB
    //utf         国际编码 Android/h5
    QTextCodec::setCodecForTr(
            QTextCodec::codecForLocale()
            );
    QApplication a(argc, argv);
    TankClient w;
    w.show();


    return a.exec();

}


谢谢


























发布了1 篇原创文章 · 获赞 8 · 访问量 1696
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览