坦克大战(一)

26 篇文章 0 订阅
2 篇文章 0 订阅

网站:点击打开链接助 C++语言初学者上手图形编程的网站。

在VS2013中没有图形库

点击打开链接下载对应编辑器的EasyX库EasyX 是针对 C++ 的图形库,可以帮助 C++语言初学者快速上手图形和游戏编程。

安装EasyX 点击打开链接

从网站:点击打开链接可以学坦克大战的游戏设计。我主要加深对C++面向对象编程的理解。

面向对象的三大特性:封装、继承、多态。

设计步骤:

一、主坦克设计及在固定坐标界面中测试

1、画布类:实现创建和销毁画布的功能,还能够让其他代码随时通过这个类拿到画布的尺寸。

创建Graphic.h和Graphic.cpp文件。

Graphic.h文件中主要是对游戏界面设计的封装。

方法:界面的创建static void Create();、销毁static void Destroy();

          获得界面的高度static int GetScreenHeight();,宽度static int GetScreenWidth();

属性:界面的高度static int m_screen_height;和宽度static int m_screen_width;

Graphic.cpp文件中是对Graphic.h方法的实现和属性初始化。

其中类使用的是静态成员变量和静态成员函数,注意静态成员变量的初始化时在类外进行的


2、坦克抽象类:为后面多态的使用做准备。

新建文件Tank.h。

在文件中先枚举坦克移动的4个方向enum Dir { UP, DOWN, LEFT, RIGHT };

建立显示virtual void Display() = 0;和移动的虚函数virtual void Move() = 0;

建立受保护的属性(供继承中子类使用),颜色,移动坐标,步数,方向。


主战坦克设计:所谓主战坦克就是玩家控制的坦克,所有的坦克中,只有这个一个是可以控制的。

创建文件MainTank.h,MainTank类公有继承Tank,构造函数初始化Tank中所有成员变量。 style); 

设置行驶方向:void SetDir(Dir dir); ,重写显示和移动方法。

绘制坦克主体void DrawTankBody(int style); 

 

创建文件MainTank.cpp

MainTank类中方法实现。

SetDir()修改成员变量的值。通过这个函数能够改变坦克的行驶方向。

DrawTankBody(int style);style有1和0分别表示上下和左右情况,通过参数负责绘制不同的形状。

这个函数负责画坦克的主体部分,一个正方形的坦克身和两个矩形的履带。

m_x,m_y这个坐标是坦克的中心点

FillRectangle是填充一个Graphics,然后显示Rectangle指定的部分。

“FillRectangle就是用指定的图象填充坐标在(x, y)处,宽width,高height的矩形。

void fillrectangle (int left, int top, int right, int bottom);// 画填充矩形(有边框)

通过该函数可以确定中心点坐标((right+left)/2,(top+bottom)/2)。

以中心点向左移动left长度,向右移动right长度,向上移动top长度,向下移动bottom长度,形成一个矩形。

简单来说fillrectangle函数中前两个参数是要填充矩形的左上角点坐标,后两个参数是矩形的右下角点坐标


//中部正方形的坦克身(8x8)
fillrectangle(m_x - 4, m_y - 4, m_x + 4, m_y + 4);

//左边矩形履带(2x12)
fillrectangle(m_x - 8, m_y - 6, m_x - 6, m_y + 6);
//右边矩形履带(2x12)
fillrectangle(m_x +6, m_y - 6, m_x +8, m_y + 6);


判断坦克的行驶方向,之后调用DrawTankBody绘制出坦克身
根据行驶方向画上炮管

setfillcolor(m_color);给坦克身体填充颜色。

DrawTankBody(1);上下移动

炮管长度为10.

上部炮管line(m_x, m_y, m_x, m_y - 10);

下部炮管:line(m_x, m_y, m_x, m_y +10);

DrawTankBody(0);左右移动

左部炮管:line(m_x, m_y, m_x-10, m_y );

右部炮管:line(m_x, m_y, m_x+10, m_y);


Move()函数每执行一次,坦克向前移动m_step长度。当超出屏幕边沿时,从另一侧重新出现,行驶方向不变。

整个界面是坐标象限的第四象限,原点在左上角点。

上下左右出现越界。

1)、上部分越界即m_y < 0

   重新给纵坐标赋值m_y = Graphic::GetScreenHight() - 1;即从下端出来

2)、下部分越界即m_y >m_y >Graphic::GetScreenHight()(纵坐标长度)

   重新给纵坐标赋值m_y = 1;即从上端出来

3)、左部分越界即m_x < 0

   重新给纵坐标赋值m_x = Graphic::GetScreenWidth() - 1;即从右端出来

4)、右部分越界即m_x >GetScreenWidth()(横坐标长度)

   重新给纵坐标赋值m_x =  1;即从左端出来


3、主函数测试

通过kbhit()捕捉键盘动作

通过getch()得到按下键的码值

方向键

UP:      72 

DOWN:80

LEFT:  75

RIGHT:77

Esc,程序退出。

ESC :   27

Space: 32

Enter程序暂停,再按一下程序继续

Enter:  13

创建mainTank对象

调用mainTank.SetDir()。



二、位置信息数据结构设计

游戏设计过程中,需要记录大量的位置信息,如果仅仅使用(x,y)坐标很容易出错,先定义两个简单的数据结构用来保存点和矩形的信息。

1、点Point类

创建Point.h文件

Point类中私有属性为m_x,m_y用来记录一个点的横、纵坐标。

通过构造函数初始化。

将“=”功能进行重载,方便用一个Point对象给另一个Point对象赋值,同时也能够将Point作为参数进行传递。

属性为私有,用Set()方法设置坐标,SetX()与SetY()单独设置横纵坐标。

方法GetX()和GetY()分别获得点横纵坐标值。

创建Point.cpp文件对Point类中方法实现。


2、矩阵Rect

创建Rect.h文件,私有方法Check()创建对象时两个点顺序反了,Check()函数会自动把它们调整过来。

私有属性 有左上角点m_startPoint;和右下角点m_endPoint;。

建立两个构造函数,Rect(int x1 = 0, int y1 = 0, int x2 = 0, int y2 = 0)和Rect(const Point p1, const Point p2)

设置矩阵参数方法:Set(const Point pStart, const Point pEnd);和Set(int x1, int y1, int x2, int y2);。

设置左上右下角点方法:SetStartPoint(const Point p);,SetEndPoint(const Point p);

获得左上右下角点方法:GetStartPoint() constGetEndPoint() const;两个函数都通过const修饰,表示返回值不能被修改。

获得高度和宽度的方法:GetWidth(); GetHeight();

创建Rect.cpp文件对Rect类中方法实现。


3、主战坦克升级

对Tank类进行修改,新增一部分功能。

计算出矩形位置virtual void CalculateSphere() = 0; 

将原有的坐标点直接用Point类创建的对象m_pos(中心点)代替。

矩阵类创建对象m_rectSphere用来记录坦克的形状范围

MainTank.h

修改原来的绘制坦克主体 void DrawTankBody(); 

对坦克中心点设置。

MainTank.cpp中修改坐标及方法

坦克身:(12*12)

m.pos值是(300,298),StartPoint(287,288),EndPoint(313,308)

fillrectangle(m_pos.GetX() - 6, m_pos.GetY() - 6, m_pos.GetX() + 6, m_pos.GetY() + 6);

要填充的矩阵左上角点坐标是(294,292),右下角点坐标(306,304)

上下移动,左右两边履带

fillrectangle(m_rectSphere.GetStartPoint().GetX(), m_rectSphere.GetStartPoint().GetY(),  
            m_rectSphere.GetStartPoint().GetX() + 4, m_rectSphere.GetEndPoint().GetY());  
左:要填充的矩阵左上角点坐标是(287,288),右下角点坐标(291,308)

 fillrectangle(m_rectSphere.GetEndPoint().GetX() - 4, m_rectSphere.GetStartPoint().GetY(),  
            m_rectSphere.GetEndPoint().GetX(), m_rectSphere.GetEndPoint().GetY());  

右:要填充的矩阵左上角点坐标是(309,288),右下角点坐标(313,308)


左右移动,上下两边履带

由于程序首先执行上下运动,通过按下左右键,才能左右移动,此时的中心点的坐标已经改变。

选取左右位置的某一点

m.pos值是(298,288),StartPoint(288,275),EndPoint(308,301)


fillrectangle(m_rectSphere.GetStartPoint().GetX(), m_rectSphere.GetStartPoint().GetY(),
m_rectSphere.GetEndPoint().GetX(), m_rectSphere.GetStartPoint().GetY() + 4);
上:要填充的矩阵左上角点坐标是(288,275),右下角点坐标(308,379)

fillrectangle(m_rectSphere.GetStartPoint().GetX(), m_rectSphere.GetEndPoint().GetY() - 4,
m_rectSphere.GetEndPoint().GetX(), m_rectSphere.GetEndPoint().GetY());

下:要填充的矩阵左上角点坐标是(288,297),右下角点坐标(313,308)


颜色及炮管、边界都要相应的修改。

GetBattleGround()给坦克划定一个运行区域。

CalculateSphere()计算出左上角和右下角的Point位置。

每移动一次都需要调用CalculateSphere()方法重新计算坦克区域。

4、敌人坦克

新建文件EnemyTank.h和EnemyTank.cpp。

有了Tank这个抽象类,所有的坦克都从它继承。除了抽象类中继承的函数之外,加了一个RandomTank()用来随机地在战场区域生成一个坦克。

5、修改main()函数演示 

与之前相比:

新建了一个宏MAX_TANKS用来设置坦克的数量

用一个指针数组保存每个坦克的指针

循环创建坦克,这里用了new的方法把坦克对象创建在堆空间中

每次擦屏之后,遍历指针数组,绘制出每个坦克。调用的是Move()和Display()方法。

退出程序前,释放每一个坦克所占的堆空间。


源码:https://github.com/breakerthb/TankWar/tree/day2

 






  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HySmiley

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值