C#WinForm开发坦克大战

Posted ZERO_BEYOND

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#WinForm开发坦克大战相关的知识,希望对你有一定的参考价值。

 using System.Drawing;
 using System.Threading;
 using System.Windows.Forms;
 
 /// <summary>
 /// 窗体
 /// </summary>
 namespace _03_WinForm
 
     public partial class Form1 : Form
     
         //子线程
         private Thread t;
         //窗体画布
         private static Graphics windowG;
         //场景图片(临时画布)
         private static Bitmap tempBmp;
 
         public Form1()
         
             InitializeComponent();
             this.StartPosition = FormStartPosition.CenterScreen;
         
 
         private void Form1_Paint(object sender, PaintEventArgs e)
         
             windowG = CreateGraphics();
             //将场景绘制到临时画布上,再将临时画布绘制到窗体画布上,解决画面闪烁
             tempBmp = new Bitmap(450, 450);
             Graphics bmpG = Graphics.FromImage(tempBmp);
             GameFramework.graphics = bmpG;
             //创建子线程
             t = new Thread(new ThreadStart(GameMainThread));
             t.Start();
         
 
         //子线程
         public static void GameMainThread()
         
             //GameFramework
             GameFramework.Start();
             //更新时间
             int sleepTime = 1000 / 60;
             //每秒调用60次
             while (true)
             
                 //清空画布
                 GameFramework.graphics.Clear(Color.Black);
                 //重新刷新
                 GameFramework.Update();
                 //重新绘制
                 windowG.DrawImage(tempBmp, 0, 0);
                 //间隔
                 Thread.Sleep(sleepTime);
             
         
 
         //窗口关闭后终止线程
         private void Form1_FormClosed(object sender, FormClosedEventArgs e)
         
             t.Abort();
         
 
         //点击按键
         private void Form1_KeyDown(object sender, KeyEventArgs e)
         
             GameObjectManager.KeyDown(e);
         
 
         //抬起按键
         private void Form1_KeyUp(object sender, KeyEventArgs e)
         
             GameObjectManager.KeyUp(e);
         
     
 
 using _03_WinForm.Properties;
 using System.Drawing;
 
 /// <summary>
 /// 游戏框架
 /// </summary>
 namespace _03_WinForm
 
     enum GameState
      
         Running,
         GameOver
     
 
     class GameFramework
     
         private static GameState gameState = GameState.Running;
         public static Graphics graphics;
         public static void Start()
         
             //声音初始化
             SoundManager.SoundInit();
             //播放背景音乐
             SoundManager.PlayStart();
             //初始化敌人位置
             GameObjectManager.Start();
             //初始化创建地图
             GameObjectManager.CreateMap();
             //创建玩家坦克
             GameObjectManager.CreateMyTank();
         
 
         public static void Update()
         
             //实时刷新场景元素
             if (gameState == GameState.Running)
             
                 GameObjectManager.Update();
             
             else
             //游戏结束界面
                 graphics.DrawImage(Resources.GameOver, new Point(450 / 2 - Resources.GameOver.Width / 2, 450 / 2 - Resources.GameOver.Height / 2));
             
         
 
         public static void GameOver()
         
             gameState = GameState.GameOver;
         
     
 
 using _03_WinForm.Properties;
 using System.Media;
 
 /// <summary>
 /// 声音管理
 /// </summary>
 namespace _03_WinForm
 
     class SoundManager
     
         private static SoundPlayer start = new SoundPlayer();
         private static SoundPlayer add = new SoundPlayer();
         private static SoundPlayer hit = new SoundPlayer();
         private static SoundPlayer blast = new SoundPlayer();
         private static SoundPlayer fire = new SoundPlayer();
 
         public static void SoundInit()
         
             start.Stream = Resources.start;
             add.Stream = Resources.add;
             hit.Stream = Resources.hit;
             blast.Stream = Resources.blast;
             fire.Stream = Resources.fire;
         
 
         //播放背景音乐
         public static void PlayStart()
         
             start.PlayLooping();
         
 
         //添加玩家和敌人
         public static void Add()
         
             add.Play();
         
 
         //玩家受伤
         public static void Hit()
         
             hit.Play();
         
 
         //爆炸
         public static void Blast()
         
             blast.Play();
         
 
         //射击
         public static void Fire()
         
             fire.Play();
         
     
 
 using _03_WinForm.Properties;
 using System;
 using System.Collections.Generic;
 using System.Drawing;
 using System.Windows.Forms;
 
 /// <summary>
 /// 场景管理
 /// </summary>
 namespace _03_WinForm
 
     class GameObjectManager
     
         //场景元素集合
         private static List<GameObject> objList = new List<GameObject>();
         //墙集合
         private static List<NotMovething> wallList = new List<NotMovething>();
         //钢铁墙集合
         private static List<NotMovething> steelList = new List<NotMovething>();
         //boss
         private static NotMovething boss;
         //玩家
         private static MyTank myTank;
         //敌人生成速度
         private static int EnemyBornSpeed = 60;
         //计数器
         private static int EnemyBornCount = 60;
         //敌人位置数组
         private static Point[] points = new Point[3];
         //敌人集合
         private static List<EnemyTank> enemyList = new List<EnemyTank>();
         //子弹集合
         private static List<Bullet> bulletList = new List<Bullet>();
         //特效集合
         private static List<Explosion> explosionList = new List<Explosion>();
 
         public static void Start()
         
             points[0].X = 0;
             points[0].Y = 0;
             points[1].X = 7 * 30;
             points[1].Y = 0;
             points[2].X = 14 * 30;
             points[2].Y = 0;
         
 
         public static void Update()
         
             foreach (GameObject item in objList)
             
                 item.Update();
             
             foreach (GameObject item in bulletList)
             
                 item.Update();
             
             foreach (GameObject item in explosionList)
             
                 item.Update();
             
             EnemyBorn();
             CheckDestroyBullet();
             CheckDestroyExp();
         
 
         //检测是否销毁子弹
         private static void CheckDestroyBullet()
         
             List<Bullet> bullets = new List<Bullet>(); 
             foreach (Bullet item in bulletList)
             
                 if (item.bDestroy)
                     bullets.Add(item);
             
             foreach (Bullet item in bullets)
             
                 bulletList.Remove(item);
             
         
 
         //检测是否销毁特效
         public static void CheckDestroyExp()
         
             List<Explosion> explosions = new List<Explosion>();
             foreach (Explosion item in explosionList)
             
                 if (item.bDestroy)
                     explosions.Add(item);
             
             foreach (Explosion item in explosions)
             
                 explosionList.Remove(item);
             
         
 
         //销毁墙
         public static void DestroyWall(NotMovething wall)
         
             objList.Remove(wall);
             wallList.Remove(wall);
         
 
         //销毁敌人
         public static void DestroyEnemy(EnemyTank enemy)
         
             objList.Remove(enemy);
             enemyList.Remove(enemy);
         
 
         //销毁玩家
         public static void DestroyPlayer()
         
             objList.Remove(myTank);
         
 
         //销毁boss
         public static void DestroyBoss()
         
             objList.Remove(boss);
         
 
         //创建地图
         public static void CreateMap()
         
             CreateWall(1, 1, 4, Resources.wall);
             CreateWall(3, 1, 4, Resources.wall);
             CreateWall(5, 1, 4, Resources.wall);
             CreateWall(7, 1, 4, Resources.wall);
             CreateSteel(7, 7, 1, Resources.steel);
             CreateWall(9, 1, 4, Resources.wall);
             CreateWall(11, 1, 4, Resources.wall);
             CreateWall(13, 1, 4, Resources.wall);
 
             CreateSteel(2, 7, 1, Resources.steel);
             CreateWall(3, 7, 1, Resources.wall);
             CreateWall(6, 7, 1, Resources.wall);
             CreateWall(8, 7, 1, Resources.wall);
             CreateWall(11, 7, 1, Resources.wall);
             CreateSteel(12, 7, 1, Resources.steel);
 
             CreateWall(1, 10, 4, Resources.wall);
             CreateWall(3, 10, 4, Resources.wall);
             CreateWall(5, 10, 2, Resources.wall);
             CreateWall(6, 10, 1, Resources.wall);
             CreateWall(7, 10, 1, Resources.wall);
             CreateWall(8, 10, 1, Resources.wall);
             CreateWall(9, 10, 2, Resources.wall);
             CreateWall(11, 10, 4, Resources.wall);
             CreateWall(13, 10, 4, Resources.wall);
 
             CreateWall(6, 13, 2, Resources.wall);
             CreateWall(7, 13, 1, Resources.wall);
             CreateBoss(7, 14, Resources.Boss);
             CreateWall(8, 13, 2, Resources.wall);
         
 
         //创建墙
         public static void CreateWall(int x, int y, int count, Image img)
         
             int xPosition = x * 30;
             int yPosition = y * 30;
             for (int i = yPosition; i < yPosition + count * 30; i += 15)
             
                 NotMovething item1 = new NotMovething(xPosition, i, img);
                 NotMovething item2 = new NotMovething(xPosition + 15, i, img);
                 objList.Add(item1);
                 objList.Add(item2);
                 wallList.Add(item1);
                 wallList.Add(item2);
             
         
 
         //创建钢铁墙
         public static void CreateSteel(int x, int y, int count, Image img)
         
             int xPosition = x * 30;
             int yPosition = y * 30;
             for (int i = yPosition; i < yPosition + count * 30; i += 15)
             
                 NotMovething item1 = new NotMovething(xPosition, i, img);
                 NotMovething item2 = new NotMovething(xPosition + 15, i, img);
                 objList.Add(item1);
                 objList.Add(item2);
                 steelList.Add(item1);
                 steelList.Add(item2);
             
         
 
         //创建Boss
         public static void CreateBoss(int x, int y, Image img)
         
             int xPosition = x * 30;
             int yPosition = y * 30;
             boss = new NotMovething(xPosition, yPosition, img);
             objList.Add(boss);
         
 
 
         //创建玩家坦克
         public static void CreateMyTank()
         
             int xPosition = 5 * 30;
             int yPosition = 14 * 30;
             myTank = new MyTank(xPosition, yPosition, 5);
             objList.Add(myTank);
         
 
         //创建子弹
         public static void CreateBullet(int x, int y, Direction dir, Tag tag)
         
             SoundManager.Fire();
             Bullet bullet = new Bullet(x, y, 10, dir, tag);
             bulletList.Add(bullet);
         
 
         //创建爆炸特效
         public static void CreateExplosion(int x, int y)
         
             Explosion explosion = new Explosion(x, y);
             explosionList.Add(explosion);
         
 
         #region 创建敌人
         private static void EnemyBorn()
         
             EnemyBornCount++;
             if (EnemyBornCount < EnemyBornSpeed) return;
             Random rd = new Random();
             int index = rd.Next(0, 3);
             Point point = points[index];
             Random rd1 = new Random();
             int enemyType = rd1.Next(1, 5);
             switch (enemyType)
             
                 case 1:
                     CreateEnemyTank1(point.X,point.Y);
                     break;
                 case 2:
                     CreateEnemyTank2(point.X, point.Y);
                     break;
                 case 3:
                     CreateEnemyTank3(point.X, point.Y);
                     break;
                 case 4:
                     CreateEnemyTank4(point.X, point.Y);
                     break;
             
             EnemyBornCount = 0;
         
 
         private static void CreateEnemyTank1(int x, int y)
         
             EnemyTank enemy = new EnemyTank(x,y,5,Resources.YellowUp,Resources.YellowDown, Resources.YellowLeft, Resources.YellowRight);
             objList.Add(enemy);
             enemyList.Add(enemy);
         
 
         private static void CreateEnemyTank2(int x, int y)
         
             EnemyTank enemy = new EnemyTank(x, y, 4, Resources.GrayUp, Resources.GrayDown, Resources.GrayLeft, Resources.GrayRight);
             objList.Add(enemy);
             enemyList.Add(enemy);
         
 
         private static void CreateEnemyTank3(int x, int y)
         
             EnemyTank enemy = new EnemyTank(x, y, 3, Resources.GreenUp, Resources.GreenDown, Resources.GreenLeft, Resources.GreenRight);
             objList.Add(enemy);
             enemyList.Add(enemy);
         
 
         private static void CreateEnemyTank4(int x, int y)
         
             EnemyTank enemy = new EnemyTank(x, y, 2, Resources.QuickUp, Resources.QuickDown, Resources.QuickLeft, Resources.QuickRight);
             objList.Add(enemy);
             enemyList.Add(enemy);
         
         #endregion
 
         #region 碰撞检测
         //是否跟红墙发生碰撞
         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 steel in steelList)
             
                 if (steel.GetRectangle().IntersectsWith(rt))
                 
                     return steel;
                 
             
             return null;
         
 
         //是否跟玩家发生碰撞
         public static Movething IsCollidedPlayer(Rectangle rt)
         
             if (myTank.GetRectangle().IntersectsWith(rt))
             
                 return myTank;
             
             return null;
         
 
         //是否跟敌人发生碰撞
         public static Movething IsCollidedEnemy(Rectangle rt)
         
             foreach (Movething enemy in enemyList)
             
                 if (enemy.GetRectangle().IntersectsWith(rt))
                 
                     return enemy;
                 
             
             return null;
         
 
         //是否跟子弹发生碰撞
         public static Bullet IsCollidedBullet(Rectangle rt)
         
             foreach (Bullet bullet in bulletList)
             
                 if (bullet.GetRectangle().IntersectsWith(rt))
                 
                     return bullet;
                 
             
             return null;
         
 
         //是否跟Boss发生碰撞
         public static NotMovething IsCollidedBoss(Rectangle rt)
         
             if (boss.GetRectangle().IntersectsWith(rt))
             
                 return boss;
             
             return null;
         
         #endregion
 
         //点击触发
         public static void KeyDown(KeyEventArgs e)
         
             myTank.KeyDown(e);
         
 
         //抬起触发
         public static void KeyUp(KeyEventArgs e)
         
             myTank.KeyUp(e);
         
     
 
 using System.Drawing;
 
 /// <summary>
 /// 场景物体基类
 /// </summary>
 namespace _03_WinForm
 
     abstract class GameObject
     
         public int X  get; set; 
         public int Y  get; set; 
 
         public int width  get; set; 
         public int height  get; set; 
 
         protected abstract Image GetImage();
 
         public virtual void DrawSelf()
         
             Graphics graphics = GameFramework.graphics;
             graphics.DrawImage(GetImage(), X, Y);
         
 
         public virtual void Update()
         
             DrawSelf();
         
 
         public Rectangle GetRectangle()
         
             Rectangle rectangle = new Rectangle(X, Y, width, height);
             return rectangle;
         
     
 
 using System.Drawing;
 
 /// <summary>
 /// 可移动物体
 /// </summary>
 namespace _03_WinForm
 
     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; 
         private Direction dir  get; set; 
         public Direction Dir  
             get 
             
                 return dir; 
             
             set
              
                 dir = value;
                 Bitmap bmp = null;
                 switch (dir)
                 
                     case Direction.Up:
                         bmp = BitmapUp;
                         break;
                     case Direction.Down:
                         bmp = BitmapDown;
                         break;
                     case Direction.Left:
                         bmp = BitmapLeft;
                         break;
                     case Direction.Right:
                         bmp = BitmapRight;
                         break;
                 
                 lock (_lock)
                 //加锁解决资源冲突
                     width = bmp.Width;
                     height = bmp.Height;
                 
             
         
 
         public override void DrawSelf()
         
             lock (_lock)
             //加锁解决资源冲突
                 base.DrawSelf();
             
         
 
         protected override Image GetImage()
         
             Bitmap bitmap = null;
             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;
                 default:
                     bitmap = BitmapUp;
                     break;
             
             bitmap.MakeTransparent(Color.Black);
             return bitmap;
         
     
 
 using System.Drawing;
 
 /// <summary>
 /// 不可移动物体
 /// </summary>
 namespace _03_WinForm
 
     class NotMovething : GameObject
     
         private Image img  get; set; 
         public Image Img
         
             get 
              
                 return 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 _03_WinForm.Properties;
 using System.Drawing;
 using System.Windows.Forms;
 
 /// <summary>
 /// 玩家类
 /// </summary>
 namespace _03_WinForm
 
     class MyTank:Movething
     
         private bool bMove  get; set; 
         public int Hp  get; set; 
         public MyTank(int x, int y, int speed)
         
             this.bMove = false;
             this.Hp = 1;
             this.X = x;
             this.Y = y;
             this.Speed = speed;
             BitmapUp = Resources.MyTankUp;
             BitmapDown = Resources.MyTankDown;
             BitmapLeft = Resources.MyTankLeft;
             BitmapRight = Resources.MyTankRight;
             this.Dir = Direction.Up;
         
 
         public override void Update()
         
             base.Update();
             Check();
             Move();
         
 
         //检测是否可移动
         private void Check()
         
             #region 碰撞检测
             Rectangle rect = GetRectangle();
             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(rect) != null)
             
                 this.bMove = false; return;
             
             if (GameObjectManager.IsCollidedSteel(rect) != null)
             
                 this.bMove = false; return;
             
             if (GameObjectManager.IsCollidedBoss(rect) != null)
             
                 this.bMove = false; return;
             
             if (GameObjectManager.IsCollidedEnemy(rect) != null)
             
                 this.bMove = false; return;
             
             #endregion
 
             #region 检测是否超出窗体边界
             if (this.Dir == Direction.Left)
             
                 if (this.X - Speed < 0)
                     this.bMove = false; return;
             
             else if (this.Dir == Direction.Right)
             
                 if (this.X + Speed + width > 450)
                     this.bMove = false; return;
             
             else if (this.Dir == Direction.Up)
             
                 if (this.Y - Speed < 0)
                     this.bMove = false; return;
             
             else if (this.Dir == Direction.Down)
             
                 if (this.Y + Speed + height > 450)
                     this.bMove = false; return;
             
             #endregion
         
 
         //移动
         private void Move()
         
             if (bMove)
             
                 if (this.Dir == Direction.Left)
                 
                     this.X -= Speed;
                 
                 if (this.Dir == Direction.Right)
                 
                     this.X += Speed;
                 
                 if (this.Dir == Direction.Up)
                 
                     this.Y -= Speed;
                 
                 if (this.Dir == Direction.Down)
                 
                     this.Y += Speed;
                 
             
         
 
         //点击触发
         public void KeyDown(KeyEventArgs e)
         
             if (e.KeyCode == Keys.A)
             
                 bMove = true;
                 this.Dir = Direction.Left;
             
             if (e.KeyCode == Keys.D)
             
                 bMove = true;
                 this.Dir = Direction.Right;
             
             if (e.KeyCode == Keys.W)
             
                 bMove = true;
                 this.Dir = Direction.Up;
             
             if (e.KeyCode == Keys.S)
             
                 bMove = true;
                 this.Dir = Direction.Down;
             
             if (e.KeyCode == Keys.Space)
             //发射子弹
                 int x = this.X;
                 int y = this.Y;
                 switch (this.Dir)
                 
                     case Direction.Up:
                         x += width / 2;
                         break;
                     case Direction.Down:
                         x += width / 2;
                         y += height;
                         break;
                     case Direction.Left:
                         y += height / 2;
                         break;
                     case Direction.Right:
                         x += width;
                         y += height / 2;
                         break;
                     default:
                         break;
                 
                 GameObjectManager.CreateBullet(x, y, this.Dir, Tag.MyTank);
             
         
 
         //抬起触发
         public void KeyUp(KeyEventArgs e)
         
             bMove = false;
         
     
 
 using System;
 using System.Drawing;
 
 /// <summary>
 /// 敌人类
 /// </summary>
 namespace _03_WinForm
 
     class EnemyTank:Movething
     
         private Random rd = new Random();
 
         //攻击间隔
         public int attackSpeed  get; set; 
         private int attackCount = 0;
 
         //随机转向间隔
         public int turnSpeed  get; set; 
         private int turnCount = 0;
 
         public EnemyTank(int x, int y, int speed, Bitmap bitmapUp, Bitmap bitmapDown, Bitmap bitmapLeft, Bitmap bitmapRight)
         
             this.X = x;
             this.Y = y;
             this.Speed = speed;
             BitmapUp = bitmapUp;
             BitmapDown = bitmapDown;
             BitmapLeft = bitmapLeft;
             BitmapRight = bitmapRight;
             this.Dir = Direction.Down;
             attackSpeed = 60;
             turnSpeed = 60;
             SoundManager.Add();
         
 
         public override void Update()
         
             base.Update();
             Check();
             Move();
             AttackCheck();
             TurnCheck();
         
 
         //检测是否攻击
         private void AttackCheck()
         
             attackCount++;
             if (attackCount >= attackSpeed)
             
                 Attack();
                 attackCount = 0;
             
         
 
         //检测是否随机转向
         private void TurnCheck()
         
             turnCount++;
             if (turnCount >= turnSpeed)
             
                 ChangeDirection();
                 turnCount = 0;
             
         
 
         //检测是否可移动
         private void Check()
         
             #region 碰撞检测
             Rectangle rect = GetRectangle();
             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(rect) != null)
             
                 ChangeDirection(); return;
             
             if (GameObjectManager.IsCollidedSteel(rect) != null)
             
                 ChangeDirection(); return;
             
             if (GameObjectManager.IsCollidedBoss(rect) != null)
             
                 ChangeDirection(); return;
             
             if (GameObjectManager.IsCollidedPlayer(rect) != null)
             
                 ChangeDirection(); return;
             
             #endregion
 
             #region 检测是否超出窗体边界
             if (this.Dir == Direction.Left)
             
                 if (this.X - Speed < 0)
                 
                     ChangeDirection();return;
                 
             
             else if (this.Dir == Direction.Right)
             
                 if (this.X + Speed + width > 450)
                 
                     ChangeDirection(); return;
                 
             
             else if (this.Dir == Direction.Up)
             
                 if (this.Y - Speed < 0)
                 
                     ChangeDirection(); return;
                 
             
             else if (this.Dir == Direction.Down)
             
                 if (this.Y + Speed + height > 450)
                 
                     ChangeDirection(); return;
                 
             
             #endregion
         
 
         //改变朝向
         private void ChangeDirection()
         
             while (true)
             
                 Direction dir = (Direction)rd.Next(0, 4);
                 if (dir == Dir)
                 
                     continue;
                 
                 else
                 
                     Dir = dir;
                     break;
                 
             
             Check();
         
 
         //移动
         private void Move()
         
             if (this.Dir == Direction.Left)
             
                 this.X -= Speed;
             
             if (this.Dir == Direction.Right)
             
                 this.X += Speed;
             
             if (this.Dir == Direction.Up)
             
                 this.Y -= Speed;
             
             if (this.Dir == Direction.Down)
             
                 this.Y += Speed;
             
         
 
         //攻击
         private void Attack()
         
             int x = this.X;
             int y = this.Y;
             switch (this.Dir)
             
                 case Direction.Up:
                     x += width / 2;
                     break;
                 case Direction.Down:
                     x += width / 2;
                     y += height;
                     break;
                 case Direction.Left:
                     y += height / 2;
                     break;
                 case Direction.Right:
                     x += width;
                     y += height / 2;
                     break;
                 default:
                     break;
             
             GameObjectManager.CreateBullet(x, y, this.Dir, Tag.EnemyTank);
         
     
 
 using _03_WinForm.Properties;
 using System.Drawing;
 
 /// <summary>
 /// 子弹类
 /// </summary>
 namespace _03_WinForm
 
     enum Tag
     
         MyTank,
         EnemyTank
     
 
     class Bullet : Movething
     
         public Tag tag  get; set; 
         public bool bDestroy  get; set; 
 
         public Bullet(int x, int y, int speed, Direction dir,Tag tag)
         
             this.X = x;
             this.Y = y;
             this.Speed = speed;
             BitmapUp = Resources.BulletUp;
             BitmapDown = Resources.BulletDown;
             BitmapLeft = Resources.BulletLeft;
             BitmapRight = Resources.BulletRight;
             this.Dir = dir;
             this.tag = tag;
             //位置修正,减去图片大小一半
             this.X -= width / 2;
             this.Y -= height / 2;
             bDestroy = false;
         
 
         public override void Update()
         
             base.Update();
             Check();
             Move();
         
 
         //检测
         private void Check()
         
             #region 碰撞检测
             Rectangle rect = GetRectangle();
             rect.X += width / 2 - 3;
             rect.Y += height / 2 - 3;
             rect.Width = 3;
             rect.Height = 3;
             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;
             
             NotMovething wall = null;
             Movething enemy = null;
             Bullet bullet = null;
             Movething myTank = null;
             int _expX = this.X + width / 2;
             int _expY = this.Y + height / 2;
             if ((wall = GameObjectManager.IsCollidedWall(rect)) != null)
             
                 //音效
                 SoundManager.Blast();
                 //爆炸特效
                 GameObjectManager.CreateExplosion(_expX, _expY);
                 //移除红墙
                 GameObjectManager.DestroyWall(wall);
                 bDestroy = true; return;
             
             if (GameObjectManager.IsCollidedSteel(rect) != null)
             
                 //音效
                 SoundManager.Blast();
                 //爆炸特效
                 GameObjectManager.CreateExplosion(_expX, _expY);
                 bDestroy = true; return;
             
             if (GameObjectManager.IsCollidedBoss(rect) != null)
             
                 //音效
                 SoundManager.Blast();
                 //爆炸特效
                 GameObjectManager.CreateExplosion(_expX, _expY);
                 //移除boss
                 GameObjectManager.DestroyBoss();
                 //游戏结束
                 GameFramework.GameOver();
                 bDestroy = true; return;
             
             if ((enemy = GameObjectManager.IsCollidedEnemy(rect)) != null)
             
                 //音效
                 SoundManager.Blast();
                 //移除敌人
                 GameObjectManager.CreateExplosion(_expX, _expY);
                 //爆炸特效
                 GameObjectManager.DestroyEnemy((EnemyTank)enemy);
                 bDestroy = true; return;
             
             if ((myTank = GameObjectManager.IsCollidedPlayer(rect)) != null)
             
                 if (this.tag == Tag.EnemyTank)
                 
                     //爆炸特效
                     GameObjectManager.CreateExplosion(_expX, _expY);
                     //音效
                     SoundManager.Hit();
                     //扣血
                     MyTank my = (MyTank)myTank;
                     my.Hp--;
                     if (my.Hp <= 0)
                     
                         //移除玩家
                         GameObjectManager.DestroyPlayer();
                         //重生
                         GameObjectManager.CreateMyTank();
                     
                     bDestroy = true; return;
                 
             
             if ((bullet = GameObjectManager.IsCollidedBullet(rect)) != null && GameObjectManager.IsCollidedBullet(rect) != this)
             
                 //音效
                 SoundManager.Blast();
                 //爆炸特效
                 GameObjectManager.CreateExplosion(_expX, _expY);
                 //子弹相互抵消
                 bDestroy = true; bullet.bDestroy = true; return;
             
             #endregion
 
             #region 检测是否超出窗

学习 Python 之 Pygame 开发坦克大战

学习 Python 之 Pygame 开发坦克大战(四)

坦克大战添加音效

我的素材放到了百度网盘里,里面还有原版坦克大战素材,我都放在一起来,我的素材是从原版改的,各位小伙伴可以直接用或者自己改一下再用,做出适合自己的素材

素材链接:百度网盘
链接:https://pan.baidu.com/s/19sCyH7rp37f6DzRj0iXDCA?pwd=tkdz
提取码:tkdz

那我们就继续编写坦克大战吧

1. 初始化音效

现在已经完成了敌方坦克和我方坦克的对打了,我们把音效加入一下

创建音乐类

import pygame


class Sound:
    def __init__(self, filename):
        self.filename = filename
        pygame.mixer.init()
        self.sound = pygame.mixer.Sound(self.filename)

    def play(self, loops = 0):
        self.sound.play(loops)

    def stop(self):
        self.sound.stop()

    def setVolume(self):
        self.sound.set_volume(0.2)
        return self

这些代码在 学习 Python 之 Pygame 开发坦克大战(一)中已经提前见过了

2. 加入游戏开始音效和坦克移动音效

坦克的移动是有音效的,在主类加入类成员

playerTankMoveSound = Sound('../Sound/player.move.wav').setVolume()
startingSound = Sound('../Sound/intro.wav')
class MainGame:

    ...
    
    # 坦克移动音效
    playerTankMoveSound = Sound('../Sound/player.move.wav').setVolume()

	# 游戏开始音效
    startingSound = Sound('../Sound/intro.wav')
    
	...

在主函数中调用播放

def startGame(self):
    # 初始化展示模块
    pygame.display.init()
    # 设置窗口大小
    size = (SCREEN_WIDTH, SCREEN_HEIGHT)
    # 初始化窗口
    MainGame.window = pygame.display.set_mode(size)
    # 设置窗口标题
    pygame.display.set_caption('Tank Battle')

    # 初始化我方坦克
    MainGame.playerTank = PlayerTank(PLAYER_TANK_POSITION[0], PLAYER_TANK_POSITION[1], 1, 1)
    
    # 播放开始音乐
    MainGame.startingSound.play()

	...

修改getPlayingModeEvent()函数

def getPlayingModeEvent(self):
    # 获取所有事件
    eventList = pygame.event.get()
    for event in eventList:

        if event.type == pygame.QUIT:
            sys.exit()

        """
        stop属性用来控制坦克移动,当键盘按键按下时,坦克可以移动,一直按住一直移动,当按键抬起时,停止移动
        如果没有该属性,按一下按键移动一次,按一下移动一下,不能一直按住一直移动
        """
        if event.type == pygame.KEYDOWN:
            MainGame.playerTankMoveSound.play(-1)
            if event.key == pygame.K_w:
                MainGame.playerTank.direction = 'UP'
                MainGame.playerTank.stop = False
            elif event.key == pygame.K_s:
                MainGame.playerTank.direction = 'DOWN'
                MainGame.playerTank.stop = False
            elif event.key == pygame.K_a:
                MainGame.playerTank.direction = 'LEFT'
                MainGame.playerTank.stop = False
            elif event.key == pygame.K_d:
                MainGame.playerTank.direction = 'RIGHT'
                MainGame.playerTank.stop = False
            elif event.key == pygame.K_j:
                # 判断子弹数量是否超过指定的个数
                if len(MainGame.playerBulletList) < MainGame.playerBulletNumber:
                    bullet = MainGame.playerTank.shot()
                    MainGame.playerBulletList.append(bullet)

        if event.type == pygame.KEYUP:
            MainGame.playerTankMoveSound.stop()
            if event.key == pygame.K_w:
                MainGame.playerTank.stop = True
            elif event.key == pygame.K_s:
                MainGame.playerTank.stop = True
            elif event.key == pygame.K_a:
                MainGame.playerTank.stop = True
            elif event.key == pygame.K_d:
                MainGame.playerTank.stop = True

完整的主类代码

import pygame
import sys

from PlayerTank import PlayerTank
from EnemyTank import EnemyTank
from Sound import Sound

SCREEN_WIDTH = 1100
SCREEN_HEIGHT = 600
BACKGROUND_COLOR = pygame.Color(0, 0, 0)
FONT_COLOR = (255, 255, 255)
PLAYER_TANK_POSITION = (325, 550)

class MainGame:

    # 窗口Surface对象
    window = None

    # 玩家坦克
    playerTank = None

    # 玩家子弹
    playerBulletList = []
    playerBulletNumber = 3

    # 敌人坦克
    enemyTankList = []
    enemyTankTotalCount = 5
    # 用来给玩家展示坦克的数量
    enemyTankCurrentCount = 5

    # 敌人坦克子弹
    enemyTankBulletList = []

    # 爆炸列表
    explodeList = []

    # 坦克移动音效
    playerTankMoveSound = Sound('../Sound/player.move.wav').setVolume()

    # 游戏开始音效
    startingSound = Sound('../Sound/intro.wav')

    def __init__(self):
        pass

    def startGame(self):
        # 初始化展示模块
        pygame.display.init()
        # 设置窗口大小
        size = (SCREEN_WIDTH, SCREEN_HEIGHT)
        # 初始化窗口
        MainGame.window = pygame.display.set_mode(size)
        # 设置窗口标题
        pygame.display.set_caption('Tank Battle')

        # 初始化我方坦克
        MainGame.playerTank = PlayerTank(PLAYER_TANK_POSITION[0], PLAYER_TANK_POSITION[1], 1, 1)

        # 播放开始音乐
        MainGame.startingSound.play()

        while 1:
            # 设置背景颜色
            MainGame.window.fill(BACKGROUND_COLOR)

            # 获取窗口事件
            self.getPlayingModeEvent()

            # 展示敌方坦克
            self.drawEnemyTank()

            # 显示我方坦克
            MainGame.playerTank.draw(MainGame.window, PLAYER_TANK_POSITION[0], PLAYER_TANK_POSITION[1])

            # 我方坦克移动
            if not MainGame.playerTank.stop:
                MainGame.playerTank.move()
                MainGame.playerTank.collideEnemyTank(MainGame.enemyTankList)

            # 显示我方坦克子弹
            self.drawPlayerBullet(MainGame.playerBulletList)

            # 展示敌方坦克子弹
            self.drawEnemyBullet()

            # 展示爆炸效果
            self.drawExplode()

            # 更新窗口
            pygame.display.update()
            
    def getPlayingModeEvent(self):
        # 获取所有事件
        eventList = pygame.event.get()
        for event in eventList:

            if event.type == pygame.QUIT:
                sys.exit()

            """
            stop属性用来控制坦克移动,当键盘按键按下时,坦克可以移动,一直按住一直移动,当按键抬起时,停止移动
            如果没有该属性,按一下按键移动一次,按一下移动一下,不能一直按住一直移动
            """
            if event.type == pygame.KEYDOWN:
                MainGame.playerTankMoveSound.play(-1)
                if event.key == pygame.K_w:
                    MainGame.playerTank.direction = 'UP'
                    MainGame.playerTank.stop = False
                elif event.key == pygame.K_s:
                    MainGame.playerTank.direction = 'DOWN'
                    MainGame.playerTank.stop = False
                elif event.key == pygame.K_a:
                    MainGame.playerTank.direction = 'LEFT'
                    MainGame.playerTank.stop = False
                elif event.key == pygame.K_d:
                    MainGame.playerTank.direction = 'RIGHT'
                    MainGame.playerTank.stop = False
                elif event.key == pygame.K_j:
                    # 判断子弹数量是否超过指定的个数
                    if len(MainGame.playerBulletList) < MainGame.playerBulletNumber:
                        bullet = MainGame.playerTank.shot()
                        MainGame.playerBulletList.append(bullet)

            if event.type == pygame.KEYUP:
                MainGame.playerTankMoveSound.stop()
                if event.key == pygame.K_w:
                    MainGame.playerTank.stop = True
                elif event.key == pygame.K_s:
                    MainGame.playerTank.stop = True
                elif event.key == pygame.K_a:
                    MainGame.playerTank.stop = True
                elif event.key == pygame.K_d:
                    MainGame.playerTank.stop = True

    def drawPlayerBullet(self, playerBulletList):
        # 遍历整个子弹列表,如果是没有被销毁的状态,就把子弹显示出来,否则从列表中删除
        for bullet in playerBulletList:
            if not bullet.isDestroy:
                bullet.draw(MainGame.window)
                bullet.move(MainGame.explodeList)
                bullet.playerBulletCollideEnemyTank(MainGame.enemyTankList, MainGame.explodeList)
            else:
                playerBulletList.remove(bullet)

    def drawEnemyTank(self):
        # 如果当前坦克为0,那么就该重新生成坦克
        if len(MainGame.enemyTankList) == 0:
            # 一次性产生三个,如果剩余坦克数量超过三,那只能产生三个
            n = min(3, MainGame.enemyTankTotalCount)
            # 如果最小是0,就说明敌人坦克没有了,那么就赢了
            if n == 0:
                print('赢了')
                return
            # 没有赢的话,就产生n个坦克
            self.initEnemyTank(n)
            # 总个数减去产生的个数
            MainGame.enemyTankTotalCount -= n
        # 遍历坦克列表,展示坦克并且移动
        for tank in MainGame.enemyTankList:
            # 坦克还有生命值
            if tank.life > 0:
                tank.draw(MainGame.window)
                tank.move()
                tank.collidePlayerTank(MainGame.playerTank)
                tank.collideEnemyTank(MainGame.enemyTankList)
                bullet = tank.shot()
                if bullet is not None:
                    MainGame.enemyTankBulletList.append(bullet)
            # 坦克生命值为0,就从列表中剔除
            else:
                MainGame.enemyTankCurrentCount -= 1
                MainGame.enemyTankList.remove(tank)
    
    def initEnemyTank(self, number):
        y = 0
        position = [0, 425, 850]
        index = 0
        for i in range(number):
            x = position[index]
            enemyTank = EnemyTank(x, y)
            MainGame.enemyTankList.append(enemyTank)
            index += 1

    def drawEnemyBullet(self):
        for bullet in MainGame.enemyTankBulletList:
            if not bullet.isDestroy:
                bullet.draw(MainGame.window)
                bullet.move(MainGame.explodeList)
                bullet.enemyBulletCollidePlayerTank(MainGame.playerTank, MainGame.explodeList)
            else:
                bullet.source.bulletCount -= 1
                MainGame.enemyTankBulletList.remove(bullet)

    def drawExplode(self):
        for e in MainGame.explodeList:
            if e.isDestroy:
                MainGame.explodeList.remove(e)
            else:
                e.draw(MainGame.window)

if __name__ == '__main__':
    MainGame().startGame()

3. 添加坦克开火音效

玩家坦克发射子弹是有音效的

修改getPlayingModeEvent()函数

def getPlayingModeEvent(self):
    # 获取所有事件
    eventList = pygame.event.get()
    for event in eventList:

        if event.type == pygame.QUIT:
            sys.exit()

        """
        stop属性用来控制坦克移动,当键盘按键按下时,坦克可以移动,一直按住一直移动,当按键抬起时,停止移动
        如果没有该属性,按一下按键移动一次,按一下移动一下,不能一直按住一直移动
        """
        if event.type == pygame.KEYDOWN:
            MainGame.playerTankMoveSound.play(-1)
            if event.key == pygame.K_w:
                MainGame.playerTank.direction = 'UP'
                MainGame.playerTank.stop = False
            elif event.key == pygame.K_s:
                MainGame.playerTank.direction = 'DOWN'
                MainGame.playerTank.stop = False
            elif event.key == pygame.K_a:
                MainGame.playerTank.direction = 'LEFT'
                MainGame.playerTank.stop = False
            elif event.key == pygame.K_d:
                MainGame.playerTank.direction = 'RIGHT'
                MainGame.playerTank.stop = False
            elif event.key == pygame.K_j:
                # 判断子弹数量是否超过指定的个数
                if len(MainGame.playerBulletList) < MainGame.playerBulletNumber:
                    bullet = MainGame.playerTank.shot()
                    MainGame.playerBulletList.append(bullet)
                    # 添加音效
                    Sound('../Sound/shoot.wav').play(0)

4. 添加装甲削减音效

当我方坦克击中时,如果有装甲,装甲较少时会有音效
当敌方坦克血量减少时,也会出现音效

修改子弹类中的playerBulletCollideEnemyTank()函数,增加敌方坦克血量减少音效

def playerBulletCollideEnemyTank(self, enemyTankList, explodeList):
    # 循环遍历坦克列表,检查是否发生了碰撞
    for tank in enemyTankList:
        if pygame.sprite.collide_rect(tank, self):
            tank.loseLife(self.damage)
            # 把子弹设置为销毁状态
            self.isDestroy = True
            if tank.life == 0:
                # 增加爆炸效果
                explode = Explode(tank, 50)
                explodeList.append(explode)
            else:
                Sound('../Sound/enemy.armor.hit.wav').play()

修改子弹类中的enemyBulletCollidePlayerTank()函数,增加我方坦克血量装甲音效

def enemyBulletCollidePlayerTank(self, playerTank, explodeList):
# 玩家坦克生命值为0,不用检测
if playerTank.life <= 0:
    return
# 检测是否发生碰撞
if pygame.sprite.collide_rect(playerTank, self):
    # 发生碰撞先减少护甲,护甲为0时扣减生命值
    if playerTank.armor > 0:
        playerTank.armor -= self.damage
        playerTank.armor = max(0, playerTank.armor)
        Sound('../Sound/enemy.armor.hit.wav').play()
    else:
        playerTank.loseLife(self.damage)
        # 增加爆炸效果
        explode = Explode(playerTank, 50)
        explodeList.append(explode)
        playerTank.life = max(0, playerTank.life)
        if playerTank.life != 0:
            playerTank.isResurrecting = True
    # 让子弹销毁
    self.isDestroy = True

5. 添加坦克爆炸音效

修改子弹类中的下面两个函数

def playerBulletCollideEnemyTank(self, enemyTankList, explodeList):
    # 循环遍历坦克列表,检查是否发生了碰撞
    for tank in enemyTankList:
        if pygame.sprite.collide_rect(tank, self):
            tank.loseLife(self.damage)
            # 把子弹设置为销毁状态
            self.isDestroy = True
            if tank.life == 0:
                # 增加爆炸效果
                explode = Explode(tank, 50)
                explodeList.append(explode)
                Sound('../Sound/kill.wav').play()
            else:
                Sound('../Sound/enemy.armor.hit.wav').play()

def enemyBulletCollidePlayerTank(self, playerTank, explodeList):
    # 玩家坦克生命值为0,不用检测
    if playerTank.life <= 0:
        return
    # 检测是否发生碰撞
    if pygame.sprite.collide_rect(playerTank, self):
        # 发生碰撞先减少护甲,护甲为0时扣减生命值
        if playerTank.armor > 0:
            playerTank.armor -= self.damage
            playerTank.armor = max(0, playerTank.armor)
            Sound('../Sound/enemy.armor.hit.wav').play()
        else:
            playerTank.loseLife(self.damage)
            # 增加爆炸效果
            explode = Explode(playerTank, 50)
            explodeList.append(explode)
            playerTank.life = max(0, playerTank.life)
            Sound('../Sound/kill.wav').play()
            if playerTank.life != C语言——坦克大战

学习 Python 之 Pygame 开发坦克大战

学习 Python 之 Pygame 开发坦克大战

学习 Python 之 Pygame 开发坦克大战

Egret学习-坦克大战开发

C/C++游戏项目完整教程:《坦克大战》