如何用C++编写程序输出以下图形一个基本的2D图形游戏,如小时候玩的坦克大战

& C++实战项目:坦克大战(二)
C++实战项目:坦克大战(二)
  这一篇中,我们继续继续进行我们的坦克大战。  位置信息数据结构  在游戏设计过程中,需要记录大量的位置信息,如果仅仅使用(x,y)坐标很容易出错。这一篇中,我们先定义两个简单的数据结构用来保存点和矩形的信息。  在项目中新建Model目录,创建下面四个文件:  代码如下:
#ifndef&__POINT_H__&&
#define&__POINT_H__&&
class&Point&&
&&&&Point(int&x&=&0,&int&y&=&0)&:&m_x(x),&m_y(y){};&&
&&&&~Point(){};&&
&&&&Point&&operator=(const&Point&&p)&&
&&&&&&&&m_x&=&p.m_x;&&
&&&&&&&&m_y&=&p.m_y;&&
&&&&&&&&return&*this;&&
&&&&void&Set(int&x,&int&y);&&
&&&&void&SetX(int&x);&&
&&&&void&SetY(int&y);&&
&&&&int&GetX();&&
&&&&int&GetY();&&
private:&&
&&&&int&m_x;&&
&&&&int&m_y;&&
#endif&&  这个头文件创建了一个Point类,有两个成员变量m_x,m_y用来记录一个点的横、纵坐标。一组public方法用来完成给对象赋值和读取坐标值的操作。  这里我们用到了的运算符重载功能,将&=&功能进行重载,方便我们用一个Point对象给另一个Point对象赋值,同时也能够使我们将Point作为参数进行传递。  Point.cpp
#include&&Point.h&&&
void&Point::Set(int&x,&int&y)&&
&&&&m_x&=&x;&&
&&&&m_y&=&y;&&
void&Point::SetX(int&x)&&
&&&&m_x&=&x;&&
void&Point::SetY(int&y)&&
&&&&m_y&=&y;&&
int&Point::GetX()&&
&&&&return&m_x;&&
int&Point::GetY()&&
&&&&return&m_y;&&
}&&  这个文件中是对Point类的实现,大家一看就明白。  这里需要强调的是,在类的封装过程中有一个非常重要的原则是不允许将成员变量用public的方法暴露在外。如果类的外部代码能够直接对类成员变量进行修改的话,程序将很不安全。正确的方法是像我们这样实现一组Get和Set方法进行管理。这样虽然代码量多了一些,但对后期维护带来的帮助是不可估量的。  Rect.h
#ifndef&__RECTANGLE_H__&&
#define&__RECTANGLE_H__&&
#include&&Point.h&&&
class&Rect&&
&&&&Rect(int&x1&=&0,&int&y1&=&0,&int&x2&=&0,&int&y2&=&0)&:&m_startPoint(x1,&y1),&m_endPoint(x2,&y2){};&&
&&&&Rect(const&Point&p1,&const&Point&p2)&:&m_startPoint(p1),&m_endPoint(p2){};&&
&&&&~Rect(){};&&
&&&&Rect&&operator=(const&Rect&&rect)&&
&&&&&&&&m_startPoint&=&rect.GetStartPoint();&&
&&&&&&&&m_endPoint&=&rect.GetEndPoint();&&
&&&&&&&&return&*this;&&
&&&&void&Set(const&Point&pStart,&const&Point&pEnd);&&
&&&&void&Set(int&x1,&int&y1,&int&x2,&int&y2);&&
&&&&void&SetStartPoint(const&Point&p);&&
&&&&void&SetEndPoint(const&Point&p);&&
&&&&Point&GetStartPoint()&const;&&
&&&&Point&GetEndPoint()&const;&&
&&&&int&GetWidth();&&
&&&&int&GetHeight();&&
private:&&
&&&&void&Check();&&
&&&&Point&m_startP&&
&&&&Point&m_endP&&
#endif&&  Rect类是用来定义矩形的,它的成员变量是两个Point对象,分别表示矩形的左上角和右下角。这里我们强行规定m_startPoint表示左上角,m_endPoint表示右下角。如果创建对象时两个点顺序反了,Check()函数会自动把它们调整过来。  这里需要注意,GetStartPoint()和GetEndPoint()两个函数都通过const修饰,表示返回值不能被修改。为什么要这么实现呢,因为这个函数的结果将会传进EasyX接口中,而这些接口大部分都要求参数是const的,如果这里不做修饰,在传参时会报错。  Rect.cpp
#include&&Rect.h&&&
void&Rect::Set(Point&pStart,&Point&pEnd)&&
&&&&m_startPoint&=&pS&&
&&&&m_endPoint&=&pE&&
void&Rect::Set(int&x1,&int&y1,&int&x2,&int&y2)&&
&&&&m_startPoint.Set(x1,&y1);&&
&&&&m_endPoint.Set(x2,&y2);&&
void&Rect::SetStartPoint(Point&p)&&
&&&&m_startPoint&=&p;&&
void&Rect::SetEndPoint(Point&p)&&
&&&&m_endPoint&=&p;&&
Point&Rect::GetStartPoint()&const&&
&&&&return&m_startP&&
Point&Rect::GetEndPoint()&const&&
&&&&return&m_endP&&
int&Rect::GetWidth()&&
&&&&return&m_endPoint.GetX()&-&m_startPoint.GetX();&&
int&Rect::GetHeight()&&
&&&&return&m_endPoint.GetY()&-&m_startPoint.GetY();&&
void&Rect::Check()&&
&&&&if&(m_startPoint.GetX()&&&m_endPoint.GetX()&||&m_startPoint.GetY()&&&m_endPoint.GetY())&&
&&&&&&&&Point&p&=&m_startP&&
&&&&&&&&m_startPoint&=&m_endP&&
&&&&&&&&m_endPoint&=&m_startP&&
}&&  这个文件中实现了Rect类的成员函数。  主战坦克升级  Tank.h  首先,我们对Tank类进行修改,新增一部分功能,代码如下:
#ifndef&__TANK_H__&&
#define&__TANK_H__&&
#include&&Graphic.h&&&
enum&Dir&{&UP,&DOWN,&LEFT,&RIGHT&};&&
class&Tank&&
&&&&virtual&void&Display()&=&0;&&
&&&&virtual&void&Move()&=&0;&&
protected:&&
&&&&virtual&void&CalculateSphere()&=&0;&&
&&&&Point&m_&&
&&&&Rect&m_rectS&&&
&&&&COLORREF&m_&&
&&&&Dir&m_&&
&&&&int&m_&&
#endif&&  我们把坐标用Point对象m_pos表示,又添加了一个新属性m_rectSphere,它是一个Rect对象,用来记录坦克的形状范围。之前我们的坦克总是用一组坐标来表示,这个坐标是坦克的中心点,所有跟坦克相关的行为都通过这个点来计算位置,实现起来有些复杂,有了这个Rect对象,相当于我们记录了这个坦克所在的矩形的位置,这样在绘制坦克时更容易计算坐标。  MainTank.h
#ifndef&__MAIN_TANK__&&
#define&__MAIN_TANK__&&
#include&&Tank.h&&&
class&MainTank&:&public&Tank&&
&&&&MainTank()&&
&&&&&&&&m_pos.Set(300,&300);&&
&&&&&&&&this-&CalculateSphere();&&
&&&&&&&&m_color&=&YELLOW;&&
&&&&&&&&m_dir&=&Dir::UP;&&
&&&&&&&&m_step&=&2;&&
&&&&~MainTank(){}&&
&&&&void&SetDir(Dir&dir);&&
&&&&void&Display();&&
&&&&void&Move();&&
protected:&&
&&&&void&CalculateSphere();&&
&&&&void&DrawTankBody();&&
#endif&&  这个文件中没有太大的修改,只是在成员变量初始化时做了一些调整。主战坦克的颜色改成了黄色,初始化后调用CalculateSphere()函数计算出矩形位置。  MainTank.cpp
#include&&MainTank.h&&&
void&MainTank::SetDir(Dir&dir)&&
&&&&m_dir&=&&&
void&MainTank::DrawTankBody()&&
&&&&fillrectangle(m_pos.GetX()&-&6,&m_pos.GetY()&-&6,&m_pos.GetX()&+&6,&m_pos.GetY()&+&6);&&
&&&&switch&(m_dir)&&
&&&&case&UP:&&
&&&&case&DOWN:&&
&&&&&&&&fillrectangle(m_rectSphere.GetStartPoint().GetX(),&m_rectSphere.GetStartPoint().GetY(),&&
&&&&&&&&&&&&m_rectSphere.GetStartPoint().GetX()&+&4,&m_rectSphere.GetEndPoint().GetY());&&
&&&&&&&&fillrectangle(m_rectSphere.GetEndPoint().GetX()&-&4,&m_rectSphere.GetStartPoint().GetY(),&&
&&&&&&&&&&&&m_rectSphere.GetEndPoint().GetX(),&m_rectSphere.GetEndPoint().GetY());&&
&&&&&&&&break;&&
&&&&case&LEFT:&&
&&&&case&RIGHT:&&
&&&&&&&&fillrectangle(m_rectSphere.GetStartPoint().GetX(),&m_rectSphere.GetStartPoint().GetY(),&&
&&&&&&&&&&&&m_rectSphere.GetEndPoint().GetX(),&m_rectSphere.GetStartPoint().GetY()&+&4);&&
&&&&&&&&fillrectangle(m_rectSphere.GetStartPoint().GetX(),&m_rectSphere.GetEndPoint().GetY()&-&4,&&
&&&&&&&&&&&&m_rectSphere.GetEndPoint().GetX(),&m_rectSphere.GetEndPoint().GetY());&&
&&&&&&&&break;&&
&&&&default:&&
&&&&&&&&break;&&
void&MainTank::Display()&&
&&&&COLORREF&fill_color_save&=&getfillcolor();&&
&&&&COLORREF&color_save&=&getcolor();&&
&&&&setfillcolor(m_color);&&
&&&&setcolor(m_color);&&
&&&&DrawTankBody();&&
&&&&switch&(m_dir)&&
&&&&case&UP:&&
&&&&&&&&line(m_pos.GetX(),&m_pos.GetY(),&m_pos.GetX(),&m_pos.GetY()&-&15);&&
&&&&&&&&break;&&
&&&&case&DOWN:&&
&&&&&&&&line(m_pos.GetX(),&m_pos.GetY(),&m_pos.GetX(),&m_pos.GetY()&+&15);&&
&&&&&&&&break;&&
&&&&case&LEFT:&&
&&&&&&&&line(m_pos.GetX(),&m_pos.GetY(),&m_pos.GetX()&-&15,&m_pos.GetY());&&
&&&&&&&&break;&&
&&&&case&RIGHT:&&
&&&&&&&&line(m_pos.GetX(),&m_pos.GetY(),&m_pos.GetX()&+&15,&m_pos.GetY());&&
&&&&&&&&break;&&
&&&&default:&&
&&&&&&&&break;&&
&&&&setcolor(color_save);&&
&&&&setfillcolor(fill_color_save);&&
void&MainTank::Move()&&
&&&&switch&(m_dir)&&
&&&&case&UP:&&
&&&&&&&&m_pos.SetY(m_pos.GetY()&-&m_step);&&
&&&&&&&&if&(m_pos.GetY()&&&Graphic::GetBattleGround().GetStartPoint().GetY())&&
&&&&&&&&&&&&m_pos.SetY(Graphic::GetBattleGround().GetEndPoint().GetY()&-&1);&&
&&&&&&&&break;&&
&&&&case&DOWN:&&
&&&&&&&&m_pos.SetY(m_pos.GetY()&+&m_step);&&
&&&&&&&&if&(m_pos.GetY()&&&Graphic::GetBattleGround().GetEndPoint().GetY())&&
&&&&&&&&&&&&m_pos.SetY(Graphic::GetBattleGround().GetStartPoint().GetY()&+&1);&&
&&&&&&&&break;&&
&&&&case&LEFT:&&
&&&&&&&&m_pos.SetX(m_pos.GetX()&-&m_step);&&
&&&&&&&&if&(m_pos.GetX()&&&Graphic::GetBattleGround().GetStartPoint().GetX())&&
&&&&&&&&&&&&m_pos.SetX(Graphic::GetBattleGround().GetEndPoint().GetX()&-&1);&&
&&&&&&&&break;&&
&&&&case&RIGHT:&&
&&&&&&&&m_pos.SetX(m_pos.GetX()&+&m_step);&&
&&&&&&&&if&(m_pos.GetX()&&&Graphic::GetBattleGround().GetEndPoint().GetX())&&
&&&&&&&&&&&&m_pos.SetX(Graphic::GetBattleGround().GetStartPoint().GetX()&+&1);&&
&&&&&&&&break;&&
&&&&default:&&
&&&&&&&&break;&&
&&&&CalculateSphere();&&
void&MainTank::CalculateSphere()&&
&&&&switch&(m_dir)&&
&&&&case&UP:&&
&&&&case&DOWN:&&
&&&&&&&&m_rectSphere.Set(m_pos.GetX()&-&13,&m_pos.GetY()&-&10,&m_pos.GetX()&+&13,&m_pos.GetY()&+&10);&&
&&&&&&&&break;&&
&&&&case&LEFT:&&
&&&&case&RIGHT:&&
&&&&&&&&m_rectSphere.Set(m_pos.GetX()&-&10,&m_pos.GetY()&-&13,&m_pos.GetX()&+&10,&m_pos.GetY()&+&13);&&
&&&&&&&&break;&&
&&&&default:&&
&&&&&&&&break;&&
}&&  这个文件修改较多,是不是有些眼花缭乱了。  & DrawTankBody()  这个函数的参数被拿掉了,在这里我们通过坦克当前方向来判断它的形状。  在绘制履带时,我们利用了m_rectSphere的位置坐标,虽然看起来代码变多了,但只有一个数字4是无意义的,它代表履带的宽度。如果这个宽度需要经常调整的话,我们还可以考虑把它用一个成员变量管理起来。  在判断坦克形状时,我们利用了switch的一个特性,通过故意少写break关键字,让两个判断结果公用一段代码,这个早已经讲过,这里不多说了。  & Display()  之前我们用setfillcolor设置了填充颜色,这里我们加入了setcolor,这样画出来的坦克边框也是我们设置的颜色。  & Move()  这个函数中,比较奇怪的是出现了一个没见过的函数Graphic::GetBattleGround()。我们今天要给坦克划定一个运行区域,不能让它满屏幕行驶了,这个后面再说。  这里要注意,每移动一次都需要调用CalculateSphere()方法重新计算坦克区域。  & CalculateSphere()  这个很简单,计算出左上角和右下角的Point位置即可。  更新画布  之前的画布颜色太深,我们要做修改。另外,我们后面需要在窗口上显示游戏信息,因此,要在右边留出一部分空间。我们给坦克划定一个新的区域,让它们在里面行驶。  Graphic.h
#ifndef&__GRAPHIC_H__&&
#define&__GRAPHIC_H__&&
#include&&graphics.h&&&
#include&&model/Rect.h&&&
#define&SCREEN_WIDTH&&&&1024&&
#define&SCREEN_HEIGHT&&&&768&&
#define&BATTLE_GROUND_X1&5&&
#define&BATTLE_GROUND_Y1&5&&
#define&BATTLE_GROUND_X2&800&&
#define&BATTLE_GROUND_Y2&(SCREEN_HEIGHT&-&BATTLE_GROUND_Y1)&&
class&Graphic&&
&&&&static&void&Create();&&
&&&&static&void&Destroy();&&
&&&&static&void&DrawBattleGround();&&
&&&&static&int&GetScreenWidth();&&
&&&&static&int&GetScreenHeight();&&
&&&&static&Rect&GetBattleGround();&&
private:&&
&&&&static&Rect&m_rectS&&
&&&&static&Rect&m_rectBattleG&&
#endif&&  文件中通过一组宏来定义战场区域的位置。另外通过m_rectBattleGround这个Rect对象来保存。  细心的读者应该发现了,我们在引用Rect类时用了下面这句话:
#include&&model/Rect.h&&&  Rect.h文件的路径需要加上model目录,否则找不到。需要说明的是这个目录指的是项目文件夹下真实存在的model目录。如果你用的是VS,&Solution Explorer&中新建的文件夹是逻辑目录,不需要加载include路径中。  简单说,include后面写的路径是给编译器看的,它只认Windows资源管理器中看到的路径,与IDE中的逻辑路径无关。  Graphic.cpp
#include&&Graphic.h&&&
Rect&Graphic::m_rectS&&&
Rect&Graphic::m_rectBattleG&&
void&Graphic::Create()&&
&&&&m_rectScreen.Set(0,&0,&SCREEN_WIDTH,&SCREEN_HEIGHT);&&
&&&&initgraph(SCREEN_WIDTH,&SCREEN_WIDTH);&&
&&&&setbkcolor(DARKGRAY);&&
&&&&m_rectBattleGround.Set(BATTLE_GROUND_X1,&BATTLE_GROUND_Y1,&BATTLE_GROUND_X2,&BATTLE_GROUND_Y2);&&
void&Graphic::Destroy()&&
&&&&closegraph();&&
void&Graphic::DrawBattleGround()&&
&&&&rectangle(m_rectBattleGround.GetStartPoint().GetX(),&m_rectBattleGround.GetStartPoint().GetY(),&&
&&&&&&&&m_rectBattleGround.GetEndPoint().GetX(),&m_rectBattleGround.GetEndPoint().GetY());&&
int&Graphic::GetScreenWidth()&&
&&&&return&SCREEN_WIDTH;&&
int&Graphic::GetScreenHeight()&&
&&&&return&SCREEN_HEIGHT;&&
Rect&Graphic::GetBattleGround()&&
&&&&return&m_rectBattleG&&
}&&  代码在创建画布是,重新指定了背景颜色。DrawBattleGround()函数在屏幕上画出了战场的范围。  main.cpp  主函数中,我们只需要再循环中添加一个DrawBattleGround函数的调用即可。
if&(!skip)&&
&&&&cleardevice();&&
&&&&Graphic::DrawBattleGround();&&
&&&&mainTank.Move();&&
&&&&mainTank.Display();&&
}&&  好了,运行一下程序,看看效果吧。  敌人坦克  屏幕上只有一个自己的坦克看着有些孤单,我们再添加上些敌人的坦克。  新建文件EnemyTank.h和EnemyTank.cpp。实现一个敌人坦克类。  EnemyTank.h
#ifndef&__ENEMY_TANK__&&
#define&__ENEMY_TANK__&&
#include&&Tank.h&&&
class&EnemyTank&:&public&Tank&&
&&&&EnemyTank()&&
&&&&&&&&RandomTank();&&
&&&&~EnemyTank(){}&&
&&&&void&Display();&&
&&&&void&Move();&&
protected:&&
&&&&void&CalculateSphere();&&
&&&&void&RandomTank();&&
#endif&&  有了Tank这个抽象类,所有的坦克都从它继承就好了。除了抽象类中继承的函数之外,我们加了一个RandomTank()用来随机地在战场区域生成一个坦克。  EnemyTank.cpp
#include&&EnemyTank.h&&&
void&EnemyTank::RandomTank()&&
&&&&m_pos.SetX(rand()&%&Graphic::GetBattleGround().GetWidth());&&
&&&&m_pos.SetY(rand()&%&Graphic::GetBattleGround().GetHeight());&&
&&&&m_color&=&WHITE;&&
&&&&m_dir&=&(Dir)(Dir::UP&+&(rand()&%&4));&&
&&&&m_step&=&2;&&
void&EnemyTank::Display()&&
&&&&COLORREF&fill_color_save&=&getfillcolor();&&
&&&&COLORREF&color_save&=&getcolor();&&
&&&&setfillcolor(m_color);&&
&&&&setcolor(m_color);&&
&&&&fillrectangle(m_pos.GetX()&-&6,&m_pos.GetY()&-&6,&m_pos.GetX()&+&6,&m_pos.GetY()&+&6);&&
&&&&fillrectangle(m_rectSphere.GetStartPoint().GetX(),&m_rectSphere.GetStartPoint().GetY(),&&
&&&&&&&&m_rectSphere.GetStartPoint().GetX()&+&4,&m_rectSphere.GetStartPoint().GetY()&+&4);&&
&&&&fillrectangle(m_rectSphere.GetEndPoint().GetX()&-&4,&m_rectSphere.GetStartPoint().GetY(),&&
&&&&&&&&m_rectSphere.GetEndPoint().GetX(),&m_rectSphere.GetStartPoint().GetY()&+&4);&&
&&&&fillrectangle(m_rectSphere.GetStartPoint().GetX(),&m_rectSphere.GetEndPoint().GetY()&-&4,&&
&&&&&&&&m_rectSphere.GetStartPoint().GetX()&+&4,&m_rectSphere.GetEndPoint().GetY());&&
&&&&fillrectangle(m_rectSphere.GetEndPoint().GetX()&-&4,&m_rectSphere.GetEndPoint().GetY()&-&4,&&
&&&&&&&&m_rectSphere.GetEndPoint().GetX(),&m_rectSphere.GetEndPoint().GetY());&&
&&&&switch&(m_dir)&&
&&&&case&UP:&&
&&&&&&&&line(m_pos.GetX(),&m_pos.GetY(),&m_pos.GetX(),&m_pos.GetY()&-&15);&&
&&&&&&&&break;&&
&&&&case&DOWN:&&
&&&&&&&&line(m_pos.GetX(),&m_pos.GetY(),&m_pos.GetX(),&m_pos.GetY()&+&15);&&
&&&&&&&&break;&&
&&&&case&LEFT:&&
&&&&&&&&line(m_pos.GetX(),&m_pos.GetY(),&m_pos.GetX()&-&15,&m_pos.GetY());&&
&&&&&&&&break;&&
&&&&case&RIGHT:&&
&&&&&&&&line(m_pos.GetX(),&m_pos.GetY(),&m_pos.GetX()&+&15,&m_pos.GetY());&&
&&&&&&&&break;&&
&&&&default:&&
&&&&&&&&break;&&
&&&&setcolor(color_save);&&
&&&&setfillcolor(fill_color_save);&&
void&EnemyTank::Move()&&
&&&&switch&(m_dir)&&
&&&&case&UP:&&
&&&&&&&&m_pos.SetY(m_pos.GetY()&-&m_step);&&
&&&&&&&&if&(m_pos.GetY()&&&Graphic::GetBattleGround().GetStartPoint().GetY())&&
&&&&&&&&&&&&m_pos.SetY(Graphic::GetBattleGround().GetEndPoint().GetY()&-&1);&&
&&&&&&&&break;&&
&&&&case&DOWN:&&
&&&&&&&&m_pos.SetY(m_pos.GetY()&+&m_step);&&
&&&&&&&&if&(m_pos.GetY()&&&Graphic::GetBattleGround().GetEndPoint().GetY())&&
&&&&&&&&&&&&m_pos.SetY(Graphic::GetBattleGround().GetStartPoint().GetY()&+&1);&&
&&&&&&&&break;&&
&&&&case&LEFT:&&
&&&&&&&&m_pos.SetX(m_pos.GetX()&-&m_step);&&
&&&&&&&&if&(m_pos.GetX()&&&Graphic::GetBattleGround().GetStartPoint().GetX())&&
&&&&&&&&&&&&m_pos.SetX(Graphic::GetBattleGround().GetEndPoint().GetX()&-&1);&&
&&&&&&&&break;&&
&&&&case&RIGHT:&&
&&&&&&&&m_pos.SetX(m_pos.GetX()&+&m_step);&&
&&&&&&&&if&(m_pos.GetX()&&&Graphic::GetBattleGround().GetEndPoint().GetX())&&
&&&&&&&&&&&&m_pos.SetX(Graphic::GetBattleGround().GetStartPoint().GetX()&+&1);&&
&&&&&&&&break;&&
&&&&default:&&
&&&&&&&&break;&&
&&&&CalculateSphere();&&
void&EnemyTank::CalculateSphere()&&
&&&&switch&(m_dir)&&
&&&&case&UP:&&
&&&&case&DOWN:&&
&&&&&&&&m_rectSphere.Set(m_pos.GetX()&-&13,&m_pos.GetY()&-&10,&m_pos.GetX()&+&13,&m_pos.GetY()&+&10);&&
&&&&&&&&break;&&
&&&&case&LEFT:&&
&&&&case&RIGHT:&&
&&&&&&&&m_rectSphere.Set(m_pos.GetX()&-&10,&m_pos.GetY()&-&13,&m_pos.GetX()&+&10,&m_pos.GetY()&+&13);&&
&&&&&&&&break;&&
&&&&default:&&
&&&&&&&&break;&&
}&&  这个文件实在没什么可讲的,基本都用的之前提到的方法。随机生成坦克用到了星空中随机产生星星的方法,相信大家都能看懂。  main.cpp  最后是main函数,代码如下:
#define&MAX_TANKS&10&&
void&main()&&
&&&&srand((unsigned)time(NULL));&&
&&&&Graphic::Create();&&
&&&&MainTank&mainT&&
&&&&Tank*&pTank[MAX_TANKS];&&
&&&&for&(int&i&=&0;&i&&&MAX_TANKS;&i++)&&
&&&&&&&&pTank[i]&=&new&EnemyTank();&&
&&&&bool&loop&=&true;&&
&&&&bool&skip&=&false;&&
&&&&while&(loop)&&
&&&&&&&&if&(kbhit())&&
&&&&&&&&{&&
&&&&&&&&&&&&int&key&=&getch();&&
&&&&&&&&&&&&switch&(key)&&
&&&&&&&&&&&&{&&
&&&&&&&&&&&&&&
&&&&&&&&&&&&case&72:&&
&&&&&&&&&&&&&&&&mainTank.SetDir(Dir::UP);&&
&&&&&&&&&&&&&&&&break;&&
&&&&&&&&&&&&&&
&&&&&&&&&&&&case&80:&&&
&&&&&&&&&&&&&&&&mainTank.SetDir(Dir::DOWN);&&
&&&&&&&&&&&&&&&&break;&&
&&&&&&&&&&&&&&
&&&&&&&&&&&&case&75:&&&
&&&&&&&&&&&&&&&&mainTank.SetDir(Dir::LEFT);&&
&&&&&&&&&&&&&&&&break;&&
&&&&&&&&&&&&&&
&&&&&&&&&&&&case&77:&&&
&&&&&&&&&&&&&&&&mainTank.SetDir(Dir::RIGHT);&&
&&&&&&&&&&&&&&&&break;&&
&&&&&&&&&&&&case&224:&&&
&&&&&&&&&&&&&&&&break;&&
&&&&&&&&&&&&&&
&&&&&&&&&&&&case&27:&&
&&&&&&&&&&&&&&&&loop&=&false;&&
&&&&&&&&&&&&&&&&break;&&
&&&&&&&&&&&&&&
&&&&&&&&&&&&case&32:&&
&&&&&&&&&&&&&&&&break;&&
&&&&&&&&&&&&&&
&&&&&&&&&&&&case&13:&&
&&&&&&&&&&&&&&&&if&(skip)&&
&&&&&&&&&&&&&&&&&&&&skip&=&false;&&
&&&&&&&&&&&&&&&&else&&
&&&&&&&&&&&&&&&&&&&&skip&=&true;&&
&&&&&&&&&&&&&&&&break;&&
&&&&&&&&&&&&default:&&&
&&&&&&&&&&&&&&&&break;&&
&&&&&&&&&&&&}&&
&&&&&&&&}&&
&&&&&&&&if&(!skip)&&
&&&&&&&&{&&
&&&&&&&&&&&&cleardevice();&&
&&&&&&&&&&&&Graphic::DrawBattleGround();&&
&&&&&&&&&&&&mainTank.Move();&&
&&&&&&&&&&&&mainTank.Display();&&
&&&&&&&&&&&&for&(int&i&=&0;&i&&&MAX_TANKS;&i++)&&
&&&&&&&&&&&&{&&
&&&&&&&&&&&&&&&&pTank[i]-&Move();&&
&&&&&&&&&&&&&&&&pTank[i]-&Display();&&
&&&&&&&&&&&&}&&
&&&&&&&&}&&
&&&&&&&&Sleep(200);&&
&&&&for&(int&i&=&0;&i&&&MAX_TANKS;&i++)&&
&&&&&&&&delete&pTank[i];&&
&&&&Graphic::Destroy();&&
}&&  与之前相比,添加了下面这几个内容:  & 新建了一个宏MAX_TANKS用来设置坦克的数量  &&用一个指针数组保存每个坦克的指针  &&循环创建坦克,这里用了new的方法把坦克对象创建在堆空间中  &&每次擦屏之后,遍历指针数组,绘制出每个坦克。调用的是Move()和Display()方法。  &&退出程序前,释放每一个坦克所占的堆空间。  注意:C++中依然是new和delete成对出现,有申请就要有释放。否则会出现内存泄露。  下面运行一下代码,看看我们今天的成果。  是不是一下热闹了很多呢?  这一篇就到这里,源码请到上下载。
除非特别注明,文章均为原创
转载请标明本文地址:
作者:鸡啄米
&&( 9:34:32)&&( 9:27:7)&&( 9:27:20)&&( 10:6:19)&&( 10:17:42)&&( 10:16:33)&&( 9:36:50)&&( 8:51:34)&&( 10:34:22)&&( 9:59:44)
这个游戏属于非常简单的游戏,用c++做起来的话还是很简单的
为什么那么多函数里头的形参表中用 const,具体有什么讲究呢?
Rect中的 Check()函数中,调换两个点是不是应该用:Point p = m_startPm_startPoint = m_endPm_endPoint =
完全随机文章坦克大战下载_游戏编程类源码_VC/C++
当前位置 &
运行环境:Windows/Linux
软件大小:479KB
发布日期:.6319
人气浏览:13764
上海网通FTP下载
上海电信HTTP下载
下载此源码的会员还关注过:
在vc集成环境下,编译,连接成可执行文件,在源码所在目录下,拷贝6个文本文件(名字为1.txt,2.txt,3.txt,4.txt,5.txt,6.txt,文本文件的内容是英文),运行即可进行练习。..查看文件可被那些用户使用..考勤管理系统..机器人足球比赛原代码..create/display message boxes..
站长工具:
实用工具:
Copyright &
all rights reserved 上传我的文档
 下载
 收藏
该文档贡献者很忙,什么也没留下。
 下载此文档
正在努力加载中...
C++课程设计坦克大战
下载积分:2000
内容提示:C++课程设计坦克大战
文档格式:DOC|
浏览次数:27|
上传日期: 17:46:12|
文档星级:
全文阅读已结束,如果下载本文需要使用
 2000 积分
下载此文档
该用户还上传了这些文档
C++课程设计坦克大战
官方公共微信& 经典坦克大战游戏源码,VC++编写
秒后自动跳转到登录页
快捷登录:
举报类型:
不规范:上传重复资源
不规范:标题与实际内容不符
不规范:资源无法下载或使用
其他不规范行为
违规:资源涉及侵权
违规:含有危害国家安全等内容
违规:含有反动/色情等内容
违规:广告内容
详细原因:
任何违反下载中心规定的资源,欢迎Down友监督举报,第一举报人可获5-10下载豆奖励。
视频课程推荐
经典坦克大战游戏源码,VC++编写
上传时间:
技术分类:
资源评价:
(3位用户参与评价)
已被下载&163&次
内容索引:VC/C++源码,游戏编程,坦克大战,VC游戏源码  经典的坦克大战游戏VC++的源代码,这熟悉的游戏界面是不是会勾起你对童年的回忆?记得小时候,打这款游戏上瘾,竟然不去上学,现在想想,那时候真的好执着。唉,如今学起来软件,用VC++重写一遍,当然有些代码是借鉴别人的,与小时候玩的游戏界面几乎是一样的,还带有音乐和多种地图,挺有意思。
51CTO下载中心常见问题:
1.如何获得下载豆?
1)上传资料
2)评论资料
3)每天在首页签到领取
4)购买VIP会员服务,无需下载豆下载资源
5)更多途径:点击此处
2.如何删除自己的资料?
下载资料意味着您已同意遵守以下协议:
1.资料的所有权益归上传用户所有
2.未经权益所有人同意,不得将资料中的内容挪作商业或盈利用途
3.51CTO下载中心仅提供资料交流平台,并不对任何资料负责
4.本站资料中如有侵权或不适当内容,请邮件与我们联系()
5.本站不保证资源的准确性、安全性和完整性, 同时也不承担用户因使用这些资料对自己和他人造成任何形式的伤害或损失
相关专题推荐
本专题收录Java经典编程的实例源码,
在国内的开发语言中,java凭借这简单
本套视频教程是韩顺平老师,循序渐进
北京圣思园张龙(风中叶)老师的Java
讲述Arm嵌入式Linux系统下的C语言编程
这段视频是从尚学堂科技的教学课堂上
本套视频共78集,是由郝斌老师根据多
本视频专题共180集涵盖了C语言概述中
本视频专题共107集涵盖了Java概述、数
由传智播客毕向东老师讲解的Java基础
本专题为spring视频教程,共31集。教
本专题为C语言黑客编程系列视频教程,
本专题为韩顺平讲解的Java从入门到精
本专题为Java Web项目开发案例精粹视
SSH为struts+spring+hibernate的一个
本专题为疯狂Java李刚老师讲解的Stru
意见或建议:
联系方式:
您已提交成功!感谢您的宝贵意见,我们会尽快处理

我要回帖

更多关于 编写程序打印下列图形 的文章

 

随机推荐