admin 管理员组文章数量: 1086019
2024年4月27日发(作者:selectedindex怎么设置)
坦克项目总结
一、需求分析:
要实现一个坦克大战游戏。游戏中包括我方坦克、对方坦克、障碍物(可摧
毁的墙、不可摧毁的墙、草地、水面)、我方的基地。双方坦克都不能穿越
除草地以外的障碍物;游戏的玩家通过键盘控制我方坦克的前进、后退、向
左、向右移动;对方坦克可以在窗体内自主移动,撞墙或边界后自动改变方
向;我方坦克与对方坦克都可以发射子弹,双方坦克被敌对方的子弹打中都
会有火花产生,被子弹打中后我方坦克生命值减1并且回到初始位置,对方
坦克被移除;双方子弹打到墙上都有火花产生,打中后子弹被移除,可摧毁
的墙被子弹打中后也会被移除;双方子弹移出窗体后被移除;当我方坦克生
命值减为0或我方基地被摧毁,玩家输,游戏结束;当对方坦克全部被子弹
打中,玩家赢,游戏结束。
二、游戏的设计图
游戏中的类及类的关系
三、游戏效果图 :
游戏主体图
游戏结束提示1 游戏结束提示2
游戏结束提示3
四、游戏设计中的问题:
1、我方坦克的绘制及移动问题
问题描述:
创建我方坦克,使其在主窗口中显示出来;按下不同的
键,画出不同方向的我方坦克,然后我方坦克向不同方
向移动。
解决方法:
我方坦克的属性继承于坦克,所以我们现在父类Tanke中
完成坦克的属性(高度,宽度,速度和位置);
在My Tanke类中添加一个构造函数,在构造函数中添加
我方坦克的位置;
public MyTanke()
{
_Location = new Point(300, 600);
}
在主程序中添加一个paint的刷新窗体的事件,在paint方
法中绘制我方坦克;
void GameManager_Paint(object sender, PaintEventArgs e)
{
_(cs);
}
在Tank抽象类中,定义Direction,然后在我方坦克的属性
中定义坦克的四个方位,当我们按下不同的键时,改变我
方坦克的方向;
在MyTanke的Draw方法中,根据传过来的方向,画出不
同方向的我方坦克;
同样,在MyTanke的Draw方法中,根据传过来的方向,
解决我方坦克的移动问题。
2、敌方坦克的绘制、自动移动及自动转向问题
问题描述:
创建对方坦克,使对方坦克自行移动,并能够自
行随机转换方向
解决方法:
在主线程中创建一个线程来创建对方坦克,X坐标取0—
950之间的随机数,Y坐标取0—60之间的随机数,然后
创建一个泛型集合,把创建的坦克加入其中;
在主程序的Draw方法中,绘制对方坦克,用for循环;
for (int i = 0; i < _; i++)
{
_ListOtherTanke[i].Draw(cs);
}
我们所创建的对方坦克只有一类,因为有不同方向需插入
不同图片,只需在对方坦克的Draw方法中,根据
Direction的不同Draw出不同图片;
创建一个线程来让对方坦克在移动过程中可以随机转换
方向;
Random random = new Random();
int tankeNum = (1, 5);
OtherTanke otherTanke = null;
int _direction = (1, 5);
对方坦克Move的方向各不相同,所以需要在它们各自的
Move方法中进行相应的设置;
在主线程中添加一个MoveTanke的线程。
void MoveOtherTanke()
{
while (1 == 1)
{
OtherTanke otherTanke = null;
for (int i = 0; i < _; i++)
{
otherTanke = _ListOtherTanke[i];
if (otherTanke != null)
{
();
}
}
(50);
h();
}
}
3、基地、障碍物的绘制问题
问题描述:
创建我方基地,并在窗体中绘制出来,根据基地位置,在
其周围绘制保护基地的障碍物(RuinedWall),设计不同障
碍物在窗体中的位置并绘制出来。
解决方法:
在Base类中定义基地的属性,并添加一个构造函数,在构
造函数中添加我方基地的位置;
public Base()
{
_width = 30;
_height = 30;
_Location = new Point(450, 620);
}
在主程序的Paint事件中绘制我方基地;
在父类Wall中定义障碍物的属性,在构造函数中定义障碍
物的长和宽,在Draw方法中绘制障碍物;
在Bankground类中定义障碍物的泛型集合,并在
Bankground的带参构造函数中,用多个for循环创建障碍
物,然后将其加入泛型集合中。
4、我方子弹的创建及移动问题
问题描述:
创建我方子弹,在按下F键的时候,根据我方坦克方向
的不同,我方坦克向不同方向发射子弹,子弹被发射后
能够自行移动。
解决方法:
在Bullet抽象类中创建子弹的属性(宽度,高度,位置,
速度,方向)及方法(绘制、移动);
在子弹的默认构造函数中定义它的宽度和高度;
public Bullet()
{
_height = 9;
_width = 9;
_speed = 15;
}
在带参(位置)的构造函数中定义它的位置,在绘制方
法中把子弹绘制出来;
在Move方法中(因为移动方法继承于抽象类所以void
前面需要加上override)定义在不同的方向上的不同的
x,y坐标变化。用一个switch语句;
public override void Move()
{
switch (_direction)
{
case 1:
_location.Y = _location.Y - _speed;
break;
case 2:
_location.Y = _location.Y + _speed;
break;
case 3:
_location.X = _location.X - _speed;
break;
case 4:
_location.X = _location.X + _speed;
break;
default:
break;
}
我方子弹由我方坦克发射,在我方坦克的Fire方法中定
义我方子弹的位置,并且返回值为子弹:public override
Bullet Fire().定义两个变量来表示子弹位置的x和y坐标,
用一个switch循环,当坦克位于不同的方向时,子弹总
是从中间的位置处出来;
public override Bullet Fire()
{
int x = 0;
int y = 0;
Bullet myBullet = null;
switch (_Direction)
{
case 1:
x = _Location.X + _width / 2;
y = _Location.Y;
break;
case 2:
x = _Location.X + _width / 2;
y = _Location.Y + _height ;
break;
case 3:
x = _Location.X - 10;
y = _Location.Y + _height / 2;
break;
case 4:
x = _Location.X + _width;
y = _Location.Y + _height / 2;
break;
default:
break;
}
Point myBulletLocation = new Point(x, y);
myBullet = new MyBullet(myBulletLocation, _Direction);
return myBullet;
}
在主程序中定义一个my bullet的泛型集合,在key down事件
中,添加一个当我们按下F键时,我方子弹发射;
if (e == Keys.F)
{
if (e == Keys.F)
{
MyBullet myBullet = new MyBullet();
myBullet = (MyBullet)_();
_(myBullet);
}
h();
}
添加一个Move Bullet 的线程,在线程中定义个死循环来不
停的使子弹移动;
void MoveBullet()
{
while (1 == 1)
{
Bullet bullet = null;
for (int i = 0; i < _; i++)
{
bullet = _listMyBullet[i];
if (bullet != null)
{
();
}
}
(100);
}
}
在主程序的Paint事件中绘制我方子弹;用for循环;
for (int i = 0; i < _; i++)
{
_listMyBullet[i].Draw(cs);
}
5、对方子弹的创建及移动问题
问题描述:
创建对方子弹,根据我方坦克方向的不同,对方坦克自动
向不同方向发射子弹, 子弹被发射后能够自行移动。
解决方法:
在Other Tank中,定义默认构造函数和带参(位置和方向)
构造函数,在Move方法一样根据方向的不同来设定子弹不
同的x,y坐标变换;
在Other Tank中的Fire方法中,创建对方子弹的位置;
public override Bullet Fire()
{
int x = 0;
int y = 0;
Bullet OtherBullet = null;
x = _Location.X + _width / 2;
y = _Location.Y + _height / 2;
Point OtherBulletLocation = new Point(x, y);
OtherBullet = new OtherBullet(OtherBulletLocation, _Direction);
return OtherBullet;
}
在主程序中创建一个创建子弹的线程,在这个线程中写创
建子弹的代码;
void CreateBullet()
{
while (1 == 1)
{
OtherBullet bullet = null;
for (int i = 0; i < _; i++)
{
bullet = (OtherBullet)_ListOtherTanke[i].Fire();
= ng();
_(bullet);
}
h();
(2000);
}
}
添加一个Move OtherBullet 的线程,在线程中定义个死循
环来不停的使子弹移动;
在主程序的Paint事件中绘制对方子弹;
6、撞击事件问题
问题描述:
我方坦克撞墙,我方坦克不能再移动,需改变方向才能够
再移动;对方坦克撞墙,自动改变方向;我方子弹打中对
方坦克,我方子弹及对方坦克被移除,有火花产生;对方
子弹打中我方坦克,对方子弹被移除,我方坦克生命值减
一,回到初始位置,有火花产生;双方子弹打中RuinedWall,
子弹及RuinedWall被移除,有火花产生;双方子弹打中
NotRuinedWall或Water,子弹被移除,有火花产生;
解决方法:
1)我方坦克与墙的撞击:当我方坦克与墙相撞时,我方坦
克停止移动,只有改变它的方向,它才会继续移动;
A)在坦克的抽象类中,定义一个方法:
public Rectangle GetRect()
{
return new Rectangle(_Location, new Size(_width, _height));
}
B)在我方坦克的Move方法中,由于Direction的不同,它
们所对应的Location也不同,当Direction向上时(即
Direction==1时):
Rectangle selfrec = GetRect();
if (_Direction == 1)
{
_Location.Y -= _speed;
for (int i = 0; i < nagerObj._; i++)
{
Rectangle ruinedwallrec = nagerObj._inedwall[i].GetRect();
if (ectsWith(ruinedwallrec))
{
_Location.Y = _Location.Y + _speed+10;
}
}
}
我方坦克撞NotRuinedWall及Water时方法类似;
Direction不同时,我方坦克的撞墙事件方法类似;
2)其他的碰撞事件与以上的碰撞事件都类似,只是具体细节略
有不同;
3)需要注意的是:对方子弹打到我方坦克时,我方坦克会在起
始位置重新绘制,我们需要在我方坦克的属性中添加一个生
命值,并对生命值赋予初值,当我方坦克被击中时,生命值
减1,当我方基地被击中时,生命值也会减1,当我方生命值
被减到0时,再次被击中就会导致游戏的结束;
void OtherBulletHitMyTanke(OtherBullet otherBullet)
{
_--;
if (_ == 0)
{
("Game Over,你输喽~ !");
rentProcess().Kill();
}
}
4)当我方坦克把对方的坦克全部消灭掉时,我们就赢得了这个
游戏;
if (_ == 0)
{
("哇塞!你赢喽!");
rentProcess().Kill();
}
五、 用到的知识点
委托:
在实现敌方子弹打中东西和我方子弹打中东西的处理中都用到了
委托,都在主窗体中分别定义相应的方法来等待被调用。
委托实质上是一个类,委托的实例化就是一个包装好的方法。
事件:
游戏中使用了KeyDown事件和Paint事件
void GameManager_KeyDown(object sender, KeyEventArgs e)
void GameManager_Paint(object sender, PaintEventArgs e)
事件是当有动作发生或状态改变时,类发出的信息或通知;
产生事件的类(发出通知的类)叫事件源sender,接受事件的类
叫做事件接收者receiver;
线程:
在敌方坦克的创建和移动、子弹的创建和移动、敌方坦克方向的
改变、窗体的刷新分别有一个线程来实现;
线程的创建:
Thread RefreshThread = new Thread(new ThreadStart(RefreshFrmMain));
();
线程的开启:
();
线程所要实现的方法:
RefreshFrmMain(){}
泛型集合:
我方子弹、地方子弹、敌方坦克、障碍物都分别装在不同的集合
中以方便调用;
泛型集合时创建一个集合,这个集合只能存储所规定的类型的数
据,在取值时不需要进行强制类型转换;
private List
版权声明:本文标题:坦克大战项目总结 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://roclinux.cn/p/1714229284a670739.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论