// 窗口
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace 坦克大战
{
public partial class Form1 : Form
{
private Thread t; // 可以被FormClosed引用
// private Graphics g;
private static Graphics windowG; // 定义图
private static Bitmap tempBmp; // 临时画布
public Form1()
{
InitializeComponent(); // 调用方法,初始化组件
this.StartPosition = FormStartPosition.CenterScreen; // 定义窗口开始位置
windowG = this.CreateGraphics(); // 声明图
// GameFramework.g = g;
// 解决画布闪烁问题
tempBmp = new Bitmap(450,450); // 定义临时画布大小
Graphics bmpG = Graphics.FromImage(tempBmp); // 将临时画布的图像绘制到图bmpG
GameFramework.g = bmpG; // 将图bmpG传递给GameFramework的静态图g
// 阻塞现象的解决方法:线程
//Thread t = new Thread(new ThreadStart(GameMainThread));
t = new Thread(new ThreadStart(GameMainThread)); // 声明调用一个线程t
t.Start(); // 线程开始运行
}
private static void GameMainThread()
{
// GameFramework
GameFramework.Start(); // 调用GameFramework中的Start()方法
int sleepTime = 1000 / 60; // 1000ms/60 = 1s/60 定义帧数
while (true)
{
GameFramework.g.Clear(Color.Black); // 将图的背景色涂黑
GameFramework.Update(); // 60帧
windowG.DrawImage(tempBmp, 0, 0); //从(0,0)坐标开始用临时图绘制画布
Thread.Sleep(sleepTime); // 将当前线程挂起,并指定的毫秒数。
}
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
t.Abort(); // 线程t终止
}
// 事件 消息 事件消息
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
// if(e.KeyCode == Keys.W) // Keys.W,枚举类型,确定W键被按下
GameObjectManager.KeyDown(e);
}
private void Form1_KeyUp(object sender, KeyEventArgs e)
{
GameObjectManager.KeyUp(e);
}
}
}
// 框架
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace 坦克大战
{
enum GameState // 游戏状态
{
Running,
GameOver
}
class GameFramework
{
public static Graphics g; // 定义静态图g
private static GameState gameState = GameState.Running; // 定义游戏状态为运行中
public static void Start() // 游戏开始
{
SoundManager.InitSound(); // 创建声音
GameObjectManager.Start(); // 创建敌人
GameObjectManager.CreateMap(); // 创建地图
GameObjectManager.CreateMyTank(); // 创建我的坦克
SoundManager.PlayStart(); // 播放声音
}
public static void Update() // 刷新地图
{
//GameObjectManager.DrawMap();
//GameObjectManager.DrawMyTank();
if (gameState == GameState.Running) // 游戏进行时
{
GameObjectManager.Update();
}
else if(gameState == GameState.GameOver) // 游戏结束
{
GameOverUpdate();
}
}
private static void GameOverUpdate() // 游戏结束刷新方式
{
Bitmap bmp = Properties.Resources.GameOver; // 调用源文件图片GameOver给图bmp
bmp.MakeTransparent(Color.Black); // 使透明化为黑色
int x = 450 / 2 - Properties.Resources.GameOver.Width / 2; // 图片中心位于画布x轴中点位置
int y = 450 / 2 - Properties.Resources.GameOver.Height / 2; // 图片中心位于画布y轴中点位置
//g.DrawImage(Properties.Resources.GameOver, x, y);
g.DrawImage(bmp, x, y); // 将图bmp放置(x,y)位置
}
public static void ChangeToGameOver() // 变为游戏结束状态
{
gameState = GameState.GameOver;
}
}
}
// 游戏对象的相关管理
// 管理者类
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using 坦克大战.Properties;
namespace 坦克大战
{
class GameObjectManager
{
private static List<NotMovething> wallList = new List<NotMovething>(); // 定义一个红墙列表
private static List<NotMovething> steelList = new List<NotMovething>(); // 定义一个铁墙列表
private static NotMovething boss; // 定义一个boss
private static MyTank myTank; // 定义我的坦克
private static List<EnemyTank> tankList = new List<EnemyTank>(); // 定义一个敌人坦克列表
private static List<Bullet> bulletList = new List<Bullet>(); // 定义一个子弹列表
// private static Object _bulletLock = new Object();
private static List<Explosion> expList = new List<Explosion>(); // 定义一个爆炸列表
private static int enemyBornSpeed = 60; // 敌人产生的速度60帧(1s1个)
private static int enemyBornCount = 60; // 计数器,敌人生成个数1个
private static Point[] points = new Point[3]; // 定义一个二维数组(x,y),用于存放敌人生成位置
public static void Start() // 敌人出现位置
{
points[0].X = 0; points[0].Y = 0; // (0,0)
points[1].X = 7 * 30; points[1].Y = 0; // (210,0)
points[2].X = 14 * 30; points[2].Y = 0; // (420,0)
}
public static void Update() // 刷新图片
{
foreach (NotMovething nm in wallList) // 刷新红墙
{
nm.Update();
}
foreach (NotMovething nm in steelList) // 刷新铁墙
{
nm.Update();
}
foreach(EnemyTank tank in tankList) // 刷新敌人坦克
{
tank.Update();
}
CheckAndDestroyBullet(); // 检查和销毁子弹
//lock (bulletList) // 子弹撞击边界报错 内部用for循环,foreach遍历不允许修改
//{
foreach (Bullet bullet in bulletList) // 刷新子弹
{
bullet.Update();
}
//}
foreach (Explosion exp in expList) // 爆炸效果刷新
{
exp.Update();
}
CheckAndDestroyExplosion(); // 检查并销毁爆炸效果
boss.Update(); // boss刷新
myTank.Update(); // 我的坦克刷新
EnemyBorn(); // 生成敌人
}
public static void CreateBullet(int x, int y, Tag tag, Direction dir) // 创建子弹
{
Bullet bullet = new Bullet(x, y, 5, dir, tag); // 子弹射出位置(x,y),速度为5,方向为dir,标志为tag
bulletList.Add(bullet); // 在子弹列表中添加子弹
}
public static void DestroyWall(NotMovething wall) // 销毁红墙
{
wallList.Remove(wall); // 从红墙列表中移除红墙
}
public static void DestroyTank(EnemyTank tank) //销毁敌人
{
tankList.Remove(tank);
}
private static void CheckAndDestroyBullet() // 检查并销毁子弹的方法
{
List<Bullet> needToDestroy = new List<Bullet>(); // 需要销毁的子弹集合
foreach (Bullet bullet in bulletList) // 遍历子弹列表
{
if (bullet.IsDestroy == true) // 找到需要销毁的子弹
{
needToDestroy.Add(bullet); // 将其加入需要销毁的子弹集合
}
}
foreach (Bullet bullet in needToDestroy) // 遍历需要销毁的子弹列表
{
bulletList.Remove(bullet); // 移除子弹
}
}
public static void CreateExplosion(int x, int y) // 创建爆炸效果
{
Explosion exp = new Explosion(x, y); // 创建一个爆炸效果,赋予位置
expList.Add(exp); // 添加到列表
}
private static void CheckAndDestroyExplosion() // 检查并销毁爆炸效果,同子弹销毁
{
List <Explosion> needToDestroy = new List<Explosion>();
foreach (Explosion exp in expList)
{
if (exp.IsNeedDestroy == true)
{
needToDestroy.Add(exp);
}
}
foreach (Explosion exp in needToDestroy)
{
expList.Remove(exp);
}
}
//public static void DestroyBullet(Bullet bullet)
//{
// bulletList.Remove(bullet);
//}
private static void EnemyBorn() // 敌人生成方法
{
enemyBornCount++; // 计数器加1
if (enemyBornCount < enemyBornSpeed) return; // 计数数小于生成速度,没有到达生成时间
SoundManager.PlayAdd(); // 敌人生成时的音效
// 0-2
Random rd = new Random(); // 生成随机数
int index = rd.Next(0, 3); // 返回在指定范围内的任意整数到索引
Point position = points[index]; // 将敌人生成坐标传递给position
int enemyType = rd.Next(1, 5); //返回在指定范围内的任意整数到索引
switch (enemyType) // 生成敌人类型
{
case 1:
CreateEnemyTank1(position.X, position.Y); // 创建敌人坦克1在该坐标
break;
case 2:
CreateEnemyTank2(position.X, position.Y); // 创建敌人坦克2在该坐标
break;
case 3:
CreateEnemyTank3(position.X, position.Y); // 创建敌人坦克3在该坐标
break;
case 4:
CreateEnemyTank4(position.X, position.Y); // 创建敌人坦克4在该坐标
break;
}
enemyBornCount = 0; // 计数器归零
}
private static void CreateEnemyTank1(int x, int y) // 创建敌人坦克1
{
EnemyTank tank = new EnemyTank(x, y, 2, Resources.GrayDown, Resources.GrayUp, Resources.GrayRight, Resources.GrayLeft);
// 在(x,y)轴生成,速度为2,四个方向状态的图片
tankList.Add(tank); // 列表加1
}
private static void CreateEnemyTank2(int x, int y) // 创建敌人坦克2
{
EnemyTank tank = new EnemyTank(x, y, 4, Resources.QuickDown, Resources.QuickUp, Resources.QuickRight, Resources.QuickLeft);
tankList.Add(tank);
}
private static void CreateEnemyTank3(int x, int y) // 创建敌人坦克3
{
EnemyTank tank = new EnemyTank(x, y, 2, Resources.GreenDown, Resources.GreenUp, Resources.GreenRight, Resources.GreenLeft);
tankList.Add(tank);
}
private static void CreateEnemyTank4(int x, int y) // 创建敌人坦克422
{
EnemyTank tank = new EnemyTank(x, y, 1, Resources.SlowDown, Resources.SlowUp, Resources.SlowRight, Resources.SlowLeft);
tankList.Add(tank);
}
public static NotMovething IsCollidedWall(Rectangle rt) // 检查是否和红墙发生碰撞
{
foreach(NotMovething wall in wallList)
{
if (wall.GetRectangle().IntersectsWith(rt)) // 判断是否相交
{
return wall;
}
}
return null;
}
public static NotMovething IsCollidedSteel(Rectangle rt) // 检查是否和铁墙发生碰撞
{
foreach(NotMovething wall in steelList)
{
if (wall.GetRectangle().IntersectsWith(rt)) // 判断是否相交
{
return wall;
}
}
return null;
}
public static bool IsCollidedBoss(Rectangle rt) // 检查是否和Boss发生碰撞,Boss只有一个
{
return boss.GetRectangle().IntersectsWith(rt);
}
public static MyTank IsCollidedMyTank(Rectangle rt) // 检查是否和我的坦克发生碰撞
{
if (myTank.GetRectangle().IntersectsWith(rt)) return myTank;
else return null;
}
public static EnemyTank IsCollidedEnemyTank(Rectangle rt) // 检查是否和敌人坦克发生碰撞
{
foreach(EnemyTank tank in tankList)
{
if (tank.GetRectangle().IntersectsWith(rt))
{
return tank;
}
}
return null;
}
//public static void DrawMap()
//{
// foreach (NotMovething nm in wallList)
// {
// nm.DrawSelf();
// }
// foreach (NotMovething nm in steelList)
// {
// nm.DrawSelf();
// }
// boss.DrawSelf();
//}
//public static void DrawMyTank()
//{
// myTank.DrawSelf();
//}
public static void CreateMyTank() // 创建我的坦克
{
int x = 5 * 30;
int y = 14 * 30;
// MyTank myTank = new MyTank(x, y, 2);
myTank = new MyTank(x, y, 2); // 位置(x,y),速度为2
}
public static void CreateMap() // 创建地图
{
// 打印红墙
CreatWall(1, 1, 5, Resources.wall, wallList); // 从坐标(x,y)开始,向下打印5个红墙,并计入红墙列表
CreatWall(3, 1, 5, Resources.wall, wallList);
CreatWall(5, 1, 4, Resources.wall, wallList);
CreatWall(7, 1, 3, Resources.wall, wallList);
CreatWall(9, 1, 4, Resources.wall, wallList);
CreatWall(11, 1, 4, Resources.wall, wallList);
CreatWall(13, 1, 4, Resources.wall, wallList);
CreatWall(7, 5, 1, Resources.steel, steelList);
CreatWall(0, 7, 1, Resources.steel, steelList);
CreatWall(2, 7, 1, Resources.wall, wallList);
CreatWall(3, 7, 1, Resources.wall, wallList);
CreatWall(4, 7, 1, Resources.wall, wallList);
CreatWall(6, 7, 1, Resources.wall, wallList);
CreatWall(7, 6, 2, Resources.wall, wallList);
CreatWall(8, 7, 1, Resources.wall, wallList);
CreatWall(10, 7, 1, Resources.wall, wallList);
CreatWall(11, 7, 1, Resources.wall, wallList);
CreatWall(12, 7, 1, Resources.wall, wallList);
CreatWall(14, 7, 1, Resources.steel, steelList);
CreatWall(1, 9, 5, Resources.wall, wallList);
CreatWall(3, 9, 5, Resources.wall, wallList);
CreatWall(5, 9, 3, Resources.wall, wallList);
CreatWall(6, 10, 1, Resources.wall, wallList);
CreatWall(7, 10, 2, Resources.wall, wallList);
CreatWall(8, 10, 1, Resources.wall, wallList);
CreatWall(9, 9, 3, Resources.wall, wallList);
CreatWall(11, 9, 5, Resources.wall, wallList);
CreatWall(13, 9, 5, Resources.wall, wallList);
CreatWall(6, 13, 2, Resources.wall, wallList);
CreatWall(7, 13, 1, Resources.wall, wallList);
CreatWall(8, 13, 2, Resources.wall, wallList);
CreatWall(7, 14, 2, Resources.wall, wallList);
CreatBoss(7, 14, Resources.Boss);
}
private static void CreatBoss(int x, int y, Image img) // 创建boss
{
int xPosition = x * 30; // x轴位置
int yPosition = y * 30; // y轴位置
boss = new NotMovething(xPosition, yPosition, img); // (x,y)坐标打印图像img
}
private static void CreatWall(int x,int y, int count,Image img, List<NotMovething> wallList) // 创建墙
{
int xPosition = x * 30;
int yPosition = y * 30;
for(int i = yPosition; i< yPosition + count * 30; i += 15) // 将4块(15*15)小墙连接成一块(30*30)大墙
{
NotMovething wall1 = new NotMovething(xPosition, i, img); // (x,y)坐标建立
NotMovething wall2 = new NotMovething(xPosition+15, i, img); // (x+15,y)坐标建立
wallList.Add(wall1);
wallList.Add(wall2);
}
}
public static void KeyDown(KeyEventArgs args) // 按键控制我的坦克运动
{
myTank.KeyDown(args);
}
public static void KeyUp(KeyEventArgs args) // 松键,停止控制操作
{
myTank.KeyUp(args);
}
}
}
// 音效管理
// 类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Media;
using System.Text;
using System.Threading.Tasks;
using 坦克大战.Properties;
namespace 坦克大战
{
class SoundManager // 音效管理
{
private static SoundPlayer startPlayer = new SoundPlayer(); // 定义开始音效
private static SoundPlayer addPlayer = new SoundPlayer(); // 定义增加敌人音效
private static SoundPlayer blastPlayer = new SoundPlayer(); // 定义爆炸音效
private static SoundPlayer firePlayer = new SoundPlayer(); // 定义发射子弹音效
private static SoundPlayer hitPlayer = new SoundPlayer(); // 定义击败坦克音效
public static void InitSound() // 初始化声音
{
startPlayer.Stream = Resources.start; // 开始音效
addPlayer.Stream = Resources.add; // 增加敌人音效
blastPlayer.Stream = Resources.blast; // 爆炸音效
firePlayer.Stream = Resources.fire; // 发射子弹音效
hitPlayer.Stream = Resources.hit; // 击败坦克音效
}
public static void PlayStart() // 开始音效方法
{
startPlayer.Play(); // 播放音效
}
public static void PlayAdd() // 增加敌人音效方法
{
addPlayer.Play();
}
public static void PlayBlast() // 爆炸音效方法
{
blastPlayer.Play();
}
public static void PlayFire() // 发射子弹音效方法
{
firePlayer.Play();
}
public static void PlayHit() // 击败坦克音效方法
{
hitPlayer.Play();
}
}
}
// 游戏对象
// 类
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 坦克大战
{
abstract class GameObject
{
//private int x;
//public int X { get { return x; } set { value = x; } }
// 简写
protected int X { get; set; } // 访问X轴位置
protected int Y { get; set; } // 访问Y轴位置
public int Width { get; set; } // 访问Width
public int Height { get; set; } // 访问Height
protected abstract Image GetImage(); // 需要在子类重写
public virtual void DrawSelf() // 绘制自身
{
Graphics g = GameFramework.g;
g.DrawImage(GetImage(), X, Y);
}
public virtual void Update()
{
DrawSelf(); // 重新绘制自己
}
public Rectangle GetRectangle() // 取得矩形
{
Rectangle rectangle = new Rectangle(X, Y, Width, Height);
return rectangle;
}
}
}
// 不可移动物体
// 类
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 坦克大战
{
class NotMovething: GameObject // 不可移动的物体
{
// public Image Img { get; set; }
private Image img; // 定义图片img
public Image Img { get { return img; } // 构造img的属性
set {
img = value;
// 确定高度和宽度
Width = img.Width;
Height = img.Height;
}
}
protected override Image GetImage() // 重载得到图片
{
return Img;
}
public NotMovething(int x,int y, Image img) // 创建不可移动物体的图片位置的方法
{
this.X = x;
this.Y = y;
this.Img = img;
}
}
}
// 可移动物体
//类
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 坦克大战
{
enum Direction // 枚举方向
{
Up = 0,
Down = 1,
Left = 2,
Right = 3
}
class Movething : GameObject // 可移动物体
{
private Object _lock = new object(); // 定义一把锁
public Bitmap BitmapUp { get; set; } // 访问向上图片,并取得
public Bitmap BitmapDown { get; set; } // 访问向下图片,并取得
public Bitmap BitmapLeft { get; set; } // 访问向左图片,并取得
public Bitmap BitmapRight { get; set; } // 访问向右图片,并取得
public int Speed { get; set; } // 访问速度,并取得
//public Direction Dir { get; set; }
private Direction dir; // 定义方向
public Direction Dir { get { return dir; } // 访问方向并取得
set {
dir = value;
Bitmap bmp = null;
switch (dir)
{
case Direction.Up: // 向上取得图片BitmapUp
bmp = BitmapUp;
break;
case Direction.Down: // 向下取得图片BitmapDown
bmp = BitmapDown;
break;
case Direction.Left: // 向左取得图片BitmapLeft
bmp = BitmapLeft;
break;
case Direction.Right: // 向右取得图片BitmapRight
bmp = BitmapRight;
break;
}
lock (_lock) // 获取锁,防止线程冲突
{
Width = bmp.Width;
Height = bmp.Height;
}
}
}
protected override Image GetImage() // 重载得到图像
{
Bitmap bitmap = null; // 定义bitmap图像
#region 方案一
//switch (Dir)
//{
// case Direction.Up:
// return BitmapUp;
// case Direction.Down:
// return BitmapDown;
// case Direction.Left:
// return BitmapLeft;
// case Direction.Right:
// return BitmapRight;
//}
#endregion
switch (Dir) // 判断方向
{
case Direction.Up:
bitmap = BitmapUp;
break;
case Direction.Down:
bitmap = BitmapDown;
break;
case Direction.Left:
bitmap = BitmapLeft;
break;
case Direction.Right:
bitmap = BitmapRight;
break;
}
bitmap.MakeTransparent(Color.Black); // 设置黑色为透明度
// return BitmapUp; //默认返回值,无法转向
return bitmap;
}
public override void DrawSelf() // 重载绘制自身
{
lock (_lock)
{
base.DrawSelf();
}
}
}
}
// 我的坦克
// 类
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using 坦克大战.Properties;
namespace 坦克大战
{
class MyTank : Movething
{
public bool IsMoving { get; set; } // 得到IsMoving属性
public int HP { get; set; } // 得到HP属性
private int originalX; // 用于存放最初的X轴位置
private int originalY; // 用于存放最初的Y轴位置
public MyTank(int x, int y, int speed) // 定义我的坦克的基本属性
{
IsMoving = false; // 默认不移动
this.X = x;
this.Y = y;
originalX = x;
originalY = y;
this.Speed = speed;
BitmapDown = Resources.MyTankDown;
BitmapUp = Resources.MyTankUp;
BitmapRight = Resources.MyTankRight;
BitmapLeft = Resources.MyTankLeft;
this.Dir = Direction.Up; // 默认方向
HP = 4;
}
public override void Update()
{
MoveCheck(); // 移动检查
Move();
base.Update();
}
private void MoveCheck()
{
#region 检查我的坦克有没有超出窗体边界
if (Dir == Direction.Up)
{
if (Y - Speed < 0) // Y-Speed 将要移动到的位置
{
IsMoving = false; return;
}
}
else if (Dir == Direction.Down)
{
if (Y + Speed + Height > 450)
{
IsMoving = false; return;
}
}
else if (Dir == Direction.Left)
{
if (X - Speed < 0)
{
IsMoving = false; return;
}
}
else if (Dir == Direction.Right)
{
if (X + Speed + Width > 450)
{
IsMoving = false; return;
}
}
#endregion
// 检查有没有其他元素发生碰撞
Rectangle rect = GetRectangle();
// rect表示将要走的位置
switch (Dir)
{
case Direction.Up:
rect.Y -= Speed;
break;
case Direction.Down:
rect.Y += Speed;
break;
case Direction.Left:
rect.X -= Speed;
break;
case Direction.Right:
rect.X += Speed;
break;
}
// if (GameObjectManager.IsCollidedWall(GetRectangle()) != null) 卡墙现象
if (GameObjectManager.IsCollidedWall(rect) != null) // 是否撞Wall
{
IsMoving = false; return;
}
if (GameObjectManager.IsCollidedSteel(rect) != null) // Steel
{
IsMoving = false; return;
}
if (GameObjectManager.IsCollidedBoss(rect)) // Boss
{
IsMoving = false; return;
}
}
private void Move() // 移动
{
if (IsMoving == false) return;
switch (Dir)
{
case Direction.Up:
Y -= Speed;
break;
case Direction.Down:
Y += Speed;
break;
case Direction.Left:
X -= Speed;
break;
case Direction.Right:
X += Speed;
break;
}
}
// GameMainThread 和 KeyDown 冲突
// 线程一和线程二 上锁
public void KeyDown(KeyEventArgs args)
{
switch (args.KeyCode) //获取的键盘
{
case Keys.W: // 按下W键
//if (Dir != Direction.Up) // 方案一,减少调用次数(权宜之计)
//{
// Dir = Direction.Up;
//}
Dir = Direction.Up;
IsMoving = true;
// Y -= Speed;
break;
case Keys.S:
Dir = Direction.Down;
IsMoving = true;
break;
case Keys.A:
Dir = Direction.Left;
IsMoving = true;
break;
case Keys.D:
Dir = Direction.Right;
IsMoving = true;
break;
case Keys.Space:
Attack(); // 发射子弹
break;
}
}
public void Attack() // 攻击
{
SoundManager.PlayFire(); // 调用音效
// 发射子弹
int x = this.X;
int y = this.Y;
switch (Dir)
{
case Direction.Up:
x = x + Width / 2;
break;
case Direction.Down:
x = x + Width / 2;
y = y + Height;
break;
case Direction.Left:
y = y + Height / 2;
break;
case Direction.Right:
x = x + Width;
y = y + Height / 2;
break;
}
GameObjectManager.CreateBullet(x, y, Tag.MyTank, Dir); // 创建子弹
}
public void KeyUp(KeyEventArgs args) // 松开键盘
{
switch (args.KeyCode)
{
case Keys.W:
IsMoving = false;
break;
case Keys.S:
IsMoving = false;
break;
case Keys.A:
IsMoving = false;
break;
case Keys.D:
IsMoving = false;
break;
}
}
public void TakeDamage() // 承受伤害
{
HP--;
if (HP <= 0)
{
X = originalX;
Y = originalY;
HP = 4;
}
}
}
}
// 敌人坦克
// 类
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 坦克大战
{
class EnemyTank:Movething
{
public int ChangeDirSpeed { get; set; } // 改变移动方向
public int changeDirCount = 0; // 改变移动方向计数器
public int AttackSpeed { get; set; } // 攻击速度
private int attackCount = 0; // 攻击速度计数器
private Random r = new Random(); // 调用同一个种子,保证随机
public EnemyTank(int x, int y, int speed, Bitmap bmpDown, Bitmap bmpUp, Bitmap bmpRight, Bitmap bmpLeft) // 敌方坦克基本属性
{
this.X = x;
this.Y = y;
this.Speed = speed;
BitmapDown = bmpDown;
BitmapUp = bmpUp;
BitmapRight = bmpRight;
BitmapLeft = bmpLeft;
this.Dir = Direction.Up;
AttackSpeed = 60; // 攻击频率
ChangeDirSpeed = 80; // 改变方向频率
}
public override void Update() // 重载更新
{
MoveCheck(); // 移动检查
Move(); // 移动
AttackCheck(); // 攻击检查
AutoChangeDirection(); // 自动转向
base.Update(); // 调用DrawSelf(); // 重新绘制自己
}
private void ChangeDirection() // 自动转向方法
{
// 4个朝向
// private Random r = new Random(); 种子,算法,伪随机数,不同种子可能生成同种算法
while (true)
{
Direction dir = (Direction)r.Next(0, 4); // 随机生成(0,4)
if (dir == Dir)
{
continue;
}
else
{
Dir = dir; break;
}
}
MoveCheck();
}
private void MoveCheck() // 移动检查方法
{
#region 检查敌人坦克有没有超出窗体边界
if (Dir == Direction.Up)
{
if (Y - Speed < 0) // Y-Speed 将要移动到的位置
{
ChangeDirection(); return;
}
}
else if (Dir == Direction.Down)
{
if (Y + Speed + Height > 450)
{
ChangeDirection(); return;
}
}
else if (Dir == Direction.Left)
{
if (X - Speed < 0)
{
ChangeDirection(); return;
}
}
else if (Dir == Direction.Right)
{
if (X + Speed + Width > 450)
{
ChangeDirection(); return;
}
}
#endregion
// 检查有没有其他元素发生碰撞
Rectangle rect = GetRectangle();
// rect表示将要走的位置
switch (Dir)
{
case Direction.Up:
rect.Y -= Speed;
break;
case Direction.Down:
rect.Y += Speed;
break;
case Direction.Left:
rect.X -= Speed;
break;
case Direction.Right:
rect.X += Speed;
break;
}
// if (GameObjectManager.IsCollidedWall(GetRectangle()) != null) 卡墙现象
if (GameObjectManager.IsCollidedWall(rect) != null) // 是否撞Wall
{
ChangeDirection(); return;
}
if (GameObjectManager.IsCollidedSteel(rect) != null) // Steel
{
ChangeDirection(); return;
}
if (GameObjectManager.IsCollidedBoss(rect)) // Boss
{
ChangeDirection(); return;
}
}
private void AutoChangeDirection() // 自动转向功能
{
changeDirCount++; // 计数器加1
if (changeDirCount < ChangeDirSpeed) return; // 计数器小于生成速度,返回
ChangeDirection(); // 改变方向
changeDirCount = 0; // 计数器归零
}
private void Move() // 移动方法
{
switch (Dir)
{
case Direction.Up:
Y -= Speed;
break;
case Direction.Down:
Y += Speed;
break;
case Direction.Left:
X -= Speed;
break;
case Direction.Right:
X += Speed;
break;
}
}
private void AttackCheck() // 攻击检查,原理同上
{
attackCount++; // 计数器加1
if (attackCount < AttackSpeed) return;
Attack();
attackCount = 0;
}
public void Attack() // 攻击方法
{
// 发射子弹
int x = this.X;
int y = this.Y;
switch (Dir)
{
case Direction.Up:
x = x + Width / 2;
break;
case Direction.Down:
x = x + Width / 2;
y = y + Height;
break;
case Direction.Left:
y = y + Height / 2;
break;
case Direction.Right:
x = x + Width;
y = y + Height / 2;
break;
}
GameObjectManager.CreateBullet(x, y, Tag.EnemyTank, Dir);
}
}
}
// 子弹
// 子弹类
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using 坦克大战.Properties;
namespace 坦克大战
{
enum Tag
{
MyTank,
EnemyTank
}
class Bullet : Movething
{
public Tag Tag { set; get; } // 访问并获取Tag
public bool IsDestroy { get; set; } // 建立IsDetroy属性
public Bullet(int x, int y, int speed, Direction dir, Tag tag) // 子弹的基本属性
{
IsDestroy = false; // 不销毁
this.X = x;
this.Y = y;
this.Speed = speed;
BitmapDown = Resources.BulletDown;
BitmapUp = Resources.BulletUp;
BitmapRight = Resources.BulletRight;
BitmapLeft = Resources.BulletLeft;
this.Dir = dir;
this.Tag = tag;
this.X -= Width / 2;
this.Y -= Height / 2;
}
// 子弹绘制图片过大,需要重新绘制
public override void DrawSelf()
{
base.DrawSelf();
}
public override void Update()
{
MoveCheck(); // 移动检查
Move();
base.Update();
}
private void MoveCheck()
{
#region 检查子弹有没有超出窗体边界
if (Dir == Direction.Up)
{
if (Y + Height/2+3 < 0) // Y-Speed 将要移动到的位置
{
IsDestroy = true; return;
}
}
else if (Dir == Direction.Down)
{
if (Y + Height / 2 - 3 > 450)
{
IsDestroy = true; return;
}
}
else if (Dir == Direction.Left)
{
if (X +Width/2-3 < 0)
{
IsDestroy = true; return;
}
}
else if (Dir == Direction.Right)
{
if (X + Width/2+3 > 450)
{
IsDestroy = true; return;
}
}
#endregion
Rectangle rect = GetRectangle(); // 取得矩形位置
rect.X = X + Width / 2 - 3;
rect.Y = Y + Width / 2 - 3;
rect.Width = 3;
rect.Height = 3;
// 1、墙;2、钢墙;3、坦克
int xExplosion = this.X + Width / 2;
int yExplosion = this.Y + Height / 2;
NotMovething wall = null;
if ((wall = GameObjectManager.IsCollidedWall(rect)) != null) // 是否撞Wall
{
IsDestroy = true; // 销毁
GameObjectManager.DestroyWall(wall); // 调用销毁方法
GameObjectManager.CreateExplosion(xExplosion, yExplosion); // 创建爆炸效果
SoundManager.PlayBlast(); // 创建音效
return;
}
if (GameObjectManager.IsCollidedSteel(rect) != null) // Steel
{
IsDestroy = true;
GameObjectManager.CreateExplosion(xExplosion, yExplosion);
return;
}
if (GameObjectManager.IsCollidedBoss(rect))
{
GameFramework.ChangeToGameOver(); // 游戏结束
SoundManager.PlayBlast(); // 结束音效
return;
}
//if (GameObjectManager.IsCollidedBoss(rect)) // Boss
//{
// ChangeDirection(); return;
//}
if (Tag == Tag.MyTank)
{
EnemyTank tank = null;
if( (tank = GameObjectManager.IsCollidedEnemyTank(rect)) != null)
{
IsDestroy = true;
GameObjectManager.DestroyTank(tank); // 销毁坦克
GameObjectManager.CreateExplosion(xExplosion, yExplosion); // 创建爆炸效果
SoundManager.PlayHit(); // 爆炸音效
return;
}
}
else if(Tag== Tag.EnemyTank)
{
MyTank mytank = null;
if((mytank = GameObjectManager.IsCollidedMyTank(rect)) != null)
{
IsDestroy = true;
GameObjectManager.CreateExplosion(xExplosion, yExplosion);
SoundManager.PlayBlast();
mytank.TakeDamage();
return;
}
}
}
private void Move() // 子弹移动方法
{
switch (Dir)
{
case Direction.Up:
Y -= Speed;
break;
case Direction.Down:
Y += Speed;
break;
case Direction.Left:
X -= Speed;
break;
case Direction.Right:
X += Speed;
break;
}
}
}
}
// 爆炸效果
// 爆炸效果类
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using 坦克大战.Properties;
namespace 坦克大战
{
class Explosion : GameObject
{
public bool IsNeedDestroy { get; set; } // 定义IsNeedDestroy属性
//private int playSpeed = 2;
//private int playCount = -1;
private int playSpeed = 1; // 生成速度
private int playCount = 0; // 生成速度计数器
// private int index = -1;
private int index = 0; // 为了能保证取到图片
private Bitmap[] bmpArray = new Bitmap[] // 图片数组
{
Resources.EXP1, // 爆炸效果图1
Resources.EXP2,
Resources.EXP3,
Resources.EXP4,
Resources.EXP5
};
public Explosion(int x, int y) // 爆炸位置及效果遍历
{
foreach (Bitmap bmp in bmpArray)
{
bmp.MakeTransparent(Color.Black); // 透明度为黑色
}
this.X = x - bmpArray[0].Width / 2;
this.Y = y - bmpArray[0].Height / 2;
IsNeedDestroy = false;
}
protected override Image GetImage() // 重写GetImage方法
{
if (index > 4) return bmpArray[4];
return bmpArray[index];
}
public override void Update() // 重写更新数据方法
{
playCount++; // 计数器+1
index = (playCount - 1) / playSpeed; //2帧一图
if (index > 4)
{
IsNeedDestroy = true;
}
base.Update();
}
}
}
// 主函数
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace 坦克大战
{
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles(); // 启用应用程序的可视样式
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
// 问题回顾
//