C#__分析使用Winform开发坦克大战

 // 窗口

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());
        }
    }
}

 // 问题回顾

//  

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值