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语言——坦克大战