C++(qt)游戏实战项目:坦克大战(五)

发射子弹
单独的子弹类根据坦克属性生成相应的子弹对象。

//file bullet.h
#ifndef BULLET_H
#define BULLET_H

#include"wanwu.h"
#include"tank.h"
class Bullet : public Wanwu
{
public:
    Bullet(const Tank &tank);
    // 绘图
  void Display(QPainter &paint) ;

    // 移动
    void Move() ;
    //
    protected:
    void CalculateSphere();
private:
    int style;
    int group;//子弹所在组

};

#endif // BULLET_H
//file bullet.cpp
#include "bullet.h"
#include"status.h"
Bullet::Bullet(const Tank &tank)
{
    m_dir=tank.m_dir;
    m_pos=tank.m_pos;
    style=tank.style/2;
    m_step=tank.m_step+10;
    wuli=tank.wuli;
    fashu-tank.fashu;
    group=tank.group;
    m_bDisappear=false;
CalculateSphere();
}

void Bullet::Display(QPainter &paint){
   if(m_bDisappear==true)return;
    switch(m_dir){
        case UP:

           paint.drawImage(m_rectSphere,*glo.bulletimage,QRect(2*PICBULLETWIDTH,style*PICBULLETHEIGHT,PICBULLETWIDTH,PICBULLETHEIGHT));//身体
           //paint.drawImage(xm_rectSphere,*glo.bulletimage,QRect(2*PICBULLETWIDTH,(style*2+1)*PICBULLETHEIGHT,PICBULLETWIDTH,PICBULLETHEIGHT));//炮塔
            break;
        case DOWN:
            paint.drawImage(m_rectSphere,*glo.bulletimage,QRect(0*PICBULLETWIDTH,style*PICBULLETHEIGHT,PICBULLETWIDTH,PICBULLETHEIGHT));//身体
            //paint.drawImage(xm_rectSphere,*glo.bulletimage,QRect(0*PICBULLETWIDTH,(style*2+1)*PICBULLETHEIGHT,PICBULLETWIDTH,PICBULLETHEIGHT));//炮塔
            break;
        case LEFT:
            paint.drawImage(m_rectSphere,*glo.bulletimage,QRect(1*PICBULLETWIDTH,style*PICBULLETHEIGHT,PICBULLETWIDTH,PICBULLETHEIGHT));//身体
            //paint.drawImage(xm_rectSphere,*glo.bulletimage,QRect(1*PICBULLETWIDTH,(style*2+1)*PICBULLETHEIGHT,PICBULLETWIDTH,PICBULLETHEIGHT));//炮塔
            break;
        case RIGHT:
            paint.drawImage(m_rectSphere,*glo.bulletimage,QRect(3*PICBULLETWIDTH,style*PICBULLETHEIGHT,PICBULLETWIDTH,PICBULLETHEIGHT));//身体
            //paint.drawImage(xm_rectSphere,*glo.bulletimage,QRect(3*PICBULLETWIDTH,(style*2+1)*PICBULLETHEIGHT,PICBULLETWIDTH,PICBULLETHEIGHT));//炮塔
            break;
      }



}




void Bullet::Move(){


     switch(m_dir){
         case UP:
             m_pos.setY(m_pos.y()-m_step);
             break;
         case DOWN:
             m_pos.setY(m_pos.y()+m_step);
             break;
         case LEFT:
             m_pos.setX(m_pos.x()-m_step);
             break;
         case RIGHT:
             m_pos.setX(m_pos.x()+m_step);
             break;
       }
     CalculateSphere();

//子弹是否与地图块碰撞
     for(int i=0;i<INUM;i++)
         for(int j=0;j<JNUM;j++)
          if(glo.gamemap->getcell(i,j))
           if(!glo.gamemap->getcell(i,j)->ischuantou1())
          if(IsBoom(*glo.gamemap->getcell(i,j)))
          {glo.gamemap->getcell(i,j)->downlife(wuli,0);m_bDisappear=true;
          *glo.status=Status(*glo.gamemap->getcell(i,j));

          }

//子弹是否击中敌对坦克
     for(int i=0;i<glo.badtanks.count();i++)
     if(glo.badtanks.at(i)&&glo.badtanks.at(i)->group!=this->group&&IsBoom(*glo.badtanks.at(i)))
     {

        m_bDisappear=true;//子弹消失
        glo.badtanks.at(i)->downlife(wuli);
        *glo.status=Status(*glo.badtanks.at(i));//将打中的对象的血量显示出来

     }

     if(glo.player->group!=this->group&&IsBoom(*glo.player))
     {

         m_bDisappear=true;//子弹消失
         glo.player->downlife(wuli);
         *glo.status=Status(*glo.player);//将打中的对象的血量显示出来

     }


//子弹出界
     if(m_pos.x()<0||m_pos.x()>WIDTH||m_pos.y()>HEIGHT||m_pos.y()<0)
         m_bDisappear=true;//子弹消失


}




void Bullet::CalculateSphere(){


this->m_rectSphere.setRect(m_pos.x()-BULLETWIDTH/2,m_pos.y()-BULLETHEIGHT/2,BULLETWIDTH,BULLETHEIGHT);

}

坦克拥有子弹,我们可以用包含关系来管理子弹,坦克发射子弹就是新建一个子弹对象插入到子弹链表中
坦克类更改如下

#ifndef TANK_H
#define TANK_H
#include"wanwu.h"
#include"main.h"
#include"gamemap.h"
#include"bullet.h"
class Tank : public Wanwu
{
protected:
    QList<Bullet*> bullets;
     static int steps[8];
     static float lifes[8];
     static float wulis[8];
     static float fashus[8];
     static float hujias[8];
     static float mokangs[8];
     static int gongjijianges[8];
   int  group;//坦克所在组
   // 计算势力范围
   virtual void CalculateSphere();
public:
   friend class Bullet;
    Tank();
    Tank(int iIndex,int jIndex,Dir dir=UP,int style=0,int group=1);


    // 绘图
    void Display(QPainter &paint);

    // 移动
    void Move();
    //
    void Move1();//fangzhi si xun huan
    //设置移动状态为开
    void startmove(){ismove=true;}
    //设置移动状态为关
    void stopmove(){ismove=false;}
    //
    void fire();
    void startfire();
    void stopfire();
    //设置方向
    void setdir(Dir dir){m_dir=dir;}
    //坦克下一步 是否和地图块碰撞
   bool nextsiboom();


private:
    int style;
    bool ismove;
    bool isfire;
    int gongjijiange;

};

#endif // TANK_H

#include "tank.h"
int Tank::steps[8]={4,8,8,16,16,32,32,64};
float Tank::lifes[8]={200,400,600,800,900,1100,1300,1500};
float Tank::wulis[8]={20,40,80,160,160,320,320,640};
float Tank::fashus[8]={20,40,80,160,160,320,320,640};
float Tank::hujias[8]={50,70,90,110,130,150,170,190};
float Tank::mokangs[8]={50,70,90,110,130,150,170,190};
int Tank::gongjijianges[8]={8,7,6,5,4,3,2,2};
Tank::Tank()
{
    this->m_pos.setX(10*CELLWIDTH+CELLWIDTH/2);
    this->m_pos.setY(8*CELLHEIGHT+CELLHEIGHT/2);
    this->wuli=200;
    this->group=0;//0玩家组,1敌人组
    m_step=16;
    gongjijiange=3;
    this->style=0;
    ismove=false;
    m_dir=UP;
    isfire=false;
    m_bDisappear=false;
    life=1000;
    CalculateSphere();
}


Tank::Tank(int iIndex,int jIndex,Dir dir,int style,int group){
    this->m_pos.setX(jIndex*CELLWIDTH+CELLWIDTH/2);
    this->m_pos.setY(iIndex*CELLHEIGHT+CELLHEIGHT/2);
    this->m_dir=dir;
    this->style=style;
    this->group=group;
    isfire=false;
    wuli=wulis[style];
    fashu=fashus[style];
    hujia=hujias[style];
    mokang=mokangs[style];
    m_step=steps[style];
    gongjijiange=gongjijianges[style];
    m_bDisappear=false;
    life=lifes[style];
    CalculateSphere();
}




void Tank::Display(QPainter &paint){
    for(int i=0;i<bullets.count();i++)
        if(bullets.at(i)&&!bullets.at(i)->IsDisappear())
    bullets.at(i)->Display(paint);
        else if(bullets.at(i)){
            delete bullets.at(i);//回收new出来的对象空间
            bullets.removeAt(i);//将对象指针从链表删除
            i--;
        }

    QRect xm_rectSphere=m_rectSphere;
    if(m_bDisappear)return;
    switch(m_dir){
        case UP:

           paint.drawImage(m_rectSphere,*glo.tankimage,QRect(2*PICTANKWIDTH,style*2*PICTANKHEIGHT,PICTANKWIDTH,PICTANKHEIGHT));//身体
           paint.drawImage(xm_rectSphere,*glo.tankimage,QRect(2*PICTANKWIDTH,(style*2+1)*PICTANKHEIGHT,PICTANKWIDTH,PICTANKHEIGHT));//炮塔
            break;
        case DOWN:
            paint.drawImage(m_rectSphere,*glo.tankimage,QRect(0*PICTANKWIDTH,style*2*PICTANKHEIGHT,PICTANKWIDTH,PICTANKHEIGHT));//身体
            paint.drawImage(xm_rectSphere,*glo.tankimage,QRect(0*PICTANKWIDTH,(style*2+1)*PICTANKHEIGHT,PICTANKWIDTH,PICTANKHEIGHT));//炮塔
            break;
        case LEFT:
            paint.drawImage(m_rectSphere,*glo.tankimage,QRect(1*PICTANKWIDTH,style*2*PICTANKHEIGHT,PICTANKWIDTH,PICTANKHEIGHT));//身体
            paint.drawImage(xm_rectSphere,*glo.tankimage,QRect(1*PICTANKWIDTH,(style*2+1)*PICTANKHEIGHT,PICTANKWIDTH,PICTANKHEIGHT));//炮塔
            break;
        case RIGHT:
            paint.drawImage(m_rectSphere,*glo.tankimage,QRect(3*PICTANKWIDTH,style*2*PICTANKHEIGHT,PICTANKWIDTH,PICTANKHEIGHT));//身体
            paint.drawImage(xm_rectSphere,*glo.tankimage,QRect(3*PICTANKWIDTH,(style*2+1)*PICTANKHEIGHT,PICTANKWIDTH,PICTANKHEIGHT));//炮塔
            break;
      }

}
void Tank::Move()
{
    for(int i=0;i<bullets.count();i++)
    bullets.at(i)->Move();
   if(m_bDisappear)return ;
   if(nextsiboom())return;
   if(ismove==true){
    switch(m_dir){
        case UP:
            m_pos.setY(m_pos.y()-m_step);
            break;
        case DOWN:
            m_pos.setY(m_pos.y()+m_step);
            break;
        case LEFT:
            m_pos.setX(m_pos.x()-m_step);
            break;
        case RIGHT:
            m_pos.setX(m_pos.x()+m_step);
            break;
      }
    CalculateSphere();
    qDebug("move on");
 }
qDebug("move off");
}

void Tank::Move1()//和move一样,为了避免死循环
{
   if(ismove==true){
    switch(m_dir){
        case UP:
            m_pos.setY(m_pos.y()-m_step);
            break;
        case DOWN:
            m_pos.setY(m_pos.y()+m_step);
            break;
        case LEFT:
            m_pos.setX(m_pos.x()-m_step);
            break;
        case RIGHT:
            m_pos.setX(m_pos.x()+m_step);
            break;
      }
    CalculateSphere();
    qDebug("yuce ");
 }
qDebug("move off");
}


bool Tank::nextsiboom(){
 Tank tmp=*this;
 tmp.Move1();
 //qDebug("%d",tmp.m_rectSphere.right());
 //qDebug("%d",glo.gamemap->getcell(1,4)->m_rectSphere.left());
 //是否与地图块碰撞
 for(int i=0;i<INUM;i++)
     for(int j=0;j<JNUM;j++)
         if(glo.gamemap->getcell(i,j)&&!glo.gamemap->getcell(i,j)->ischuantou()&&tmp.IsBoom(*glo.gamemap->getcell(i,j))){
            qDebug("-----------boom-------"); return true;
         }
 qDebug("---------------");
 //是否与地图边界碰撞
 if(tmp.m_rectSphere.left()<0||tmp.m_rectSphere.right()>WIDTH||tmp.m_rectSphere.bottom()>HEIGHT||tmp.m_rectSphere.top()<0)
 return true;//

 return false;
}


void Tank::fire(){
    if(m_bDisappear)return;
if(isfire==true&&glo.framei%gongjijiange==0){
Bullet *newbullet=new Bullet(*this);
bullets.append(newbullet);
}

}


void Tank::startfire(){

    isfire=true;

}

void Tank::stopfire(){



    isfire=false;
}



void Tank::CalculateSphere(){

this->m_rectSphere.setRect(m_pos.x()-TANKWIDTH/2,m_pos.y()-TANKHEIGHT/2,TANKWIDTH,TANKHEIGHT);

}

地图块类有些能被子弹穿透,有些能被坦克穿透,因此增加两个属性。外加其他方面更改

#ifndef MAPCELL_H
#define MAPCELL_H

#include"wanwu.h"
#include"main.h"
#include<fstream>
class Mapcell : public Wanwu
{
public:
        enum {BLOCKSNUM=13};
        static float lifes[BLOCKSNUM];
        static float hujias[BLOCKSNUM];
        static float mokangs[BLOCKSNUM];
        static bool chuantous[BLOCKSNUM];
        static bool chuantous1[BLOCKSNUM];
    Mapcell();
    Mapcell(int iIndex, int jIndex, int style=0);//护甲魔抗物理攻击魔法攻击攻击速度移动速度暂时用不到
    // 绘图
    void Display(QPainter &paint);

    // 移动
   void Move();
   //得到方块样式
   int getstyle(){return style;}
   //切换样式
   int switchstyle(){style++;style=style%BLOCKSNUM; this->life=lifes[this->style];
                     this->hujia=hujias[this->style];
                     this->mokang=mokangs[this->style];
                     this->chuantou=chuantous[this->style];
                     this->chuantou1=chuantous1[this->style];return style;}
   //设置样式
   void setstyle(int style){this->style=style%BLOCKSNUM; this->life=lifes[this->style];
                            this->hujia=hujias[this->style];
                            this->mokang=mokangs[this->style];
                            this->chuantou=chuantous[this->style];
                            this->chuantou1=chuantous1[this->style];}
   //
   bool ischuantou(){return chuantou;}
   //
   bool ischuantou1(){return chuantou1;}
private:
//static QImage blockimage;
   int style;//方块样式,从图片上依次编号0 ,1,2 ,3,4,5.。。。。
   //
   void cal(int style,int &i,int &j){//将一维编号变成一行有4列的二维编号i行j列
     i=style/4;
    j=style%4;
   }
void CalculateSphere(){
    this->m_rectSphere.setRect(m_pos.x()-CELLWIDTH/2,m_pos.y()-CELLHEIGHT/2,CELLWIDTH,CELLHEIGHT);

}

bool chuantou;//坦克能否穿透方块
bool chuantou1;//子弹能否穿透方块

};

#endif // MAPCELL_H
#include "mapcell.h"
//QImage Mapcell::blockimage=QImage(":/images/map_block.png"); linux
float Mapcell::lifes[BLOCKSNUM]={30000,3000,2000,1000,800,700,600,20000,0,0,0,0,0};
float Mapcell::hujias[BLOCKSNUM]={1000,500,400,300,200,100,50,800,0,0,0,0,0};
float Mapcell::mokangs[BLOCKSNUM]={1000,500,400,300,200,100,50,800,0,0,0,0,0};
bool Mapcell::chuantous[BLOCKSNUM]={false,false,false,false,false,false,false,false,true,true,true,true,true};
bool Mapcell::chuantous1[BLOCKSNUM]={false,false,false,false,false,false,false,false,true,true,true,true,true};
Mapcell::Mapcell()
{
    this->m_pos.setX(8*CELLWIDTH+CELLWIDTH/2);
    this->m_pos.setY(8*CELLHEIGHT+CELLHEIGHT/2);
    this->CalculateSphere();
    this->m_bDisappear=false;
    this->style=0;//map_block.png总共有28小块
    this->life=lifes[this->style];
    this->hujia=hujias[this->style];
    this->mokang=mokangs[this->style];
    this->chuantou=chuantous[this->style];
    this->chuantou1=chuantous1[this->style];

}

Mapcell::Mapcell(int iIndex,int jIndex,int style){//护甲魔抗物理攻击魔法攻击攻击速度移动速度暂时用不到
    this->m_pos.setX(jIndex*CELLWIDTH+CELLWIDTH/2);
    this->m_pos.setY(iIndex*CELLHEIGHT+CELLHEIGHT/2);
    this->CalculateSphere();
    this->m_bDisappear=false;
    this->style=style%BLOCKSNUM;//map_block.png总共有28小块
    this->life=lifes[this->style];
    this->hujia=hujias[this->style];
    this->mokang=mokangs[this->style];
    this->chuantou=chuantous[this->style];
    this->chuantou1=chuantous1[this->style];
}


void Mapcell::Display(QPainter &paint){
int i,j;
cal(style,i,j);
if(!this->IsDisappear())
paint.drawImage(m_rectSphere,*glo.blockimage,QRect(j*PICWIDTH,i*PICHEIGHT,PICWIDTH,PICHEIGHT));//优化代码,速度飞一般
//paint.drawImage(m_rectSphere,QImage(":/images/map_block.png"),QRect(j*PICWIDTH,i*PICHEIGHT,PICWIDTH,PICHEIGHT));


}
void Mapcell::Move(){



}

增加一个状态类。为了实时记录被子弹打种物体的血量

#ifndef STATUS_H
#define STATUS_H

#include"wanwu.h"
class Status
{
public:
    float life;
    Status(){life=0;}
    Status(const Wanwu &wanwu);
    void Display(QPainter &paint);
};

#endif // STATUS_H
#include "status.h"
#include<QColor>
Status::Status(const Wanwu &wanwu)
{
life=wanwu.life;
}

void Status::Display(QPainter &paint){

    paint.drawText(500,180,QString("life:")+QString::number(life));

}

void MainWindow::keyPressEvent(QKeyEvent *event)函数中加入

else if(event->key()==Qt::Key_J){

                 glo.player->startfire();

          }

Glo结构体加入

Status *status;

MainWindow::MainWindow(QWidget *parent)里加入

glo.status=new Status();

MainWindow::paintEvent(QPaintEvent *event)函数加入

glo.status->Display(paint);

这样就完成了坦克发射子弹和血量的显示

本文章为作者原创
转载请标明本系列文章地址:http://blog.csdn.net/qq_26046771/article/details/72643740

  • 9
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
游戏分里外两个部分组成,里部分(用户不可见) 通过里部分执行判断,地图数组更改,和各种值的改变。更改完里部分再根据相应变化更改表部分。(用户可视部分)表部分的打印通过gotoxy去到相应坐标再printf打印出字符,通过文本函数改变文字字体颜色与文字背景颜色与字符组合实现图形界面。 程序通过 计数器+循环判断 的思想,类似单核cpu的多线程实现(单线程在不同程序/函数间来回执行)省去了多线程。(具体过程在功能设计与描述有详细描述) 另AI实现与加强依赖于rand随机函数的运用,进一步强化AI,增加游戏乐趣 功能方面,游戏参考于80年代任天堂红白机(FC/FamilyComputer)上的游戏坦克大战(Battle City),包括地图,游戏模式等等(当时的游戏直接烧在电路板上)。所以游戏平衡方面已经有了很好的参考,无需再花大量时间测试平衡性。 但诸如地图中的树林元素,随机道具等没有实现。但较之原版,该游戏由C/C++编写PC运行,由字符界面实现游戏画面。原版一辆坦克的子弹未消失之前不能发射第二颗。导致子弹打击远处CD长,近处CD短。该游戏每个子弹都有相同CD,子弹未消失只要CD达到即可发射第二颗,第三颗…增加了真实性,相较于原版是个改进。且考虑到PC性能不一内置了游戏速度调整。玩家可根据PC性能调整至合适的速度。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值