当前位置: 首页 > news >正文

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

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

    • 坦克大战添加音效
      • 1. 初始化音效
      • 2. 加入游戏开始音效和坦克移动音效
      • 3. 添加坦克开火音效
      • 4. 添加装甲削减音效
      • 5. 添加坦克爆炸音效
      • 6. 添加子弹击中边界音效

坦克大战添加音效

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

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

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

1. 初始化音效

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

创建音乐类

import pygameclass Sound:def __init__(self, filename):self.filename = filenamepygame.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 = Falseelif event.key == pygame.K_s:MainGame.playerTank.direction = 'DOWN'MainGame.playerTank.stop = Falseelif event.key == pygame.K_a:MainGame.playerTank.direction = 'LEFT'MainGame.playerTank.stop = Falseelif event.key == pygame.K_d:MainGame.playerTank.direction = 'RIGHT'MainGame.playerTank.stop = Falseelif 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 = Trueelif event.key == pygame.K_s:MainGame.playerTank.stop = Trueelif event.key == pygame.K_a:MainGame.playerTank.stop = Trueelif event.key == pygame.K_d:MainGame.playerTank.stop = True

完整的主类代码

import pygame
import sysfrom PlayerTank import PlayerTank
from EnemyTank import EnemyTank
from Sound import SoundSCREEN_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):passdef 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 = Falseelif event.key == pygame.K_s:MainGame.playerTank.direction = 'DOWN'MainGame.playerTank.stop = Falseelif event.key == pygame.K_a:MainGame.playerTank.direction = 'LEFT'MainGame.playerTank.stop = Falseelif event.key == pygame.K_d:MainGame.playerTank.direction = 'RIGHT'MainGame.playerTank.stop = Falseelif 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 = Trueelif event.key == pygame.K_s:MainGame.playerTank.stop = Trueelif event.key == pygame.K_a:MainGame.playerTank.stop = Trueelif event.key == pygame.K_d:MainGame.playerTank.stop = Truedef 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 -= 1MainGame.enemyTankList.remove(tank)def initEnemyTank(self, number):y = 0position = [0, 425, 850]index = 0for i in range(number):x = position[index]enemyTank = EnemyTank(x, y)MainGame.enemyTankList.append(enemyTank)index += 1def 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 -= 1MainGame.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 = Falseelif event.key == pygame.K_s:MainGame.playerTank.direction = 'DOWN'MainGame.playerTank.stop = Falseelif event.key == pygame.K_a:MainGame.playerTank.direction = 'LEFT'MainGame.playerTank.stop = Falseelif event.key == pygame.K_d:MainGame.playerTank.direction = 'RIGHT'MainGame.playerTank.stop = Falseelif 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 = Trueif 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.damageplayerTank.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 = Trueif 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.damageplayerTank.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 != 0:playerTank.isResurrecting = True# 让子弹销毁self.isDestroy = True

6. 添加子弹击中边界音效

在子弹类中checkBullet()函数增加音效代码

def checkBullet(self, explodeList):toDestroy = False# 如果出界,就设置为销毁if self.rect.top < 0 or self.rect.top > 600:toDestroy = Trueif self.rect.left < 0 or self.rect.right > 900:toDestroy = Trueif toDestroy:explode = Explode(self, 25)explodeList.append(explode)self.isDestroy = TrueSound('../Sound/block.wav').play()

运行一下,看看整体的效果

完整的主类代码

import pygame
import sysfrom PlayerTank import PlayerTank
from EnemyTank import EnemyTank
from Sound import SoundSCREEN_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):passdef 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 = Falseelif event.key == pygame.K_s:MainGame.playerTank.direction = 'DOWN'MainGame.playerTank.stop = Falseelif event.key == pygame.K_a:MainGame.playerTank.direction = 'LEFT'MainGame.playerTank.stop = Falseelif event.key == pygame.K_d:MainGame.playerTank.direction = 'RIGHT'MainGame.playerTank.stop = Falseelif 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)if event.type == pygame.KEYUP:MainGame.playerTankMoveSound.stop()if event.key == pygame.K_w:MainGame.playerTank.stop = Trueelif event.key == pygame.K_s:MainGame.playerTank.stop = Trueelif event.key == pygame.K_a:MainGame.playerTank.stop = Trueelif event.key == pygame.K_d:MainGame.playerTank.stop = Truedef 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 -= 1MainGame.enemyTankList.remove(tank)def initEnemyTank(self, number):y = 0position = [0, 425, 850]index = 0for i in range(number):x = position[index]enemyTank = EnemyTank(x, y)MainGame.enemyTankList.append(enemyTank)index += 1def 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 -= 1MainGame.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()

完整的敌方坦克类代码

import random
import pygame
import pygame.imagefrom ParentObject import ParentObject
from Bullet import Bulletclass EnemyTank(ParentObject):def __init__(self, x, y):super().__init__()types = [(1, 3), (2, 1), (3, 2), (4, 10)]# 随机产生一种坦克self.type = types[random.randint(0, len(types) - 1)]up = []down = []left = []right = []for i in range(1, self.type[1] + 1):up.append(pygame.image.load('../Image/Enemy/EnemyTank' + str(self.type[0]) + '/EnemyTank'+ str(self.type[0]) + 'Lv' + str(i) + '(UP).png'))down.append(pygame.image.load('../Image/Enemy/EnemyTank' + str(self.type[0]) + '/EnemyTank'+ str(self.type[0]) + 'Lv' + str(i) + '(DOWN).png'))left.append(pygame.image.load('../Image/Enemy/EnemyTank' + str(self.type[0]) + '/EnemyTank' + str(self.type[0]) + 'Lv' + str(i) + '(LEFT).png'))right.append(pygame.image.load('../Image/Enemy/EnemyTank' + str(self.type[0]) + '/EnemyTank' + str(self.type[0]) + 'Lv' + str(i) + '(RIGHT).png'))self.images = {'UP': up,'DOWN': down,'LEFT': left,'RIGHT': right}# 生命self.life = self.type[1]# 方向self.direction = 'DOWN'self.image: pygame.Surface = self.images[self.direction][self.life - 1]self.rect = self.image.get_rect()self.rect.left = xself.rect.top = y# 碰撞前的坐标self.prvX = self.rect.leftself.prvY = self.rect.top# 速度self.accumulationMax: float = 0self.accumulation = 0.1speed = 0maxBulletCount = 0damage = 1# 每种坦克都有不同的属性if self.type[0] == 1:speed = 3self.level = 1maxBulletCount = 1elif self.type[0] == 2:speed = 5self.level = 2maxBulletCount = 1damage = 3elif self.type[0] == 3:speed = 7self.level = 1maxBulletCount = 3damage = 2elif self.type[0] == 4:speed = 6self.level = 2maxBulletCount = 3damage = 1self.speed = speed# 移动开关self.stop = True# 开火开关self.fire = True# 步数self.step = 30# 伤害self.damage = damage# 子弹个数self.bulletCount = 0self.maxBulletCount = maxBulletCountdef loseLife(self, value = 1):self.life -= valuedef move(self):"""新增步数变量, 当坦克移动时, 步数进行减少, 当步数小于等于0的时候, 修改地方坦克的方向:return: None"""if self.stop:if self.step <= 0:self.direction = self.randDirection()self.step = 30else:if self.accumulationMax >= 1:self.accumulationMax = 0# 记录上一次的位置self.prvX = self.rect.leftself.prvY = self.rect.topif self.direction == 'LEFT':if self.rect.left > 0:self.rect.left -= self.speedelif self.direction == 'UP':if self.rect.top > 0:self.rect.top -= self.speedelif self.direction == 'DOWN':if self.rect.top < 555:self.rect.top += self.speedelif self.direction == 'RIGHT':if self.rect.left < 855:self.rect.left += self.speedself.step -= 1else:self.accumulationMax += self.accumulationdef shot(self):if self.fire:if self.bulletCount < self.maxBulletCount:num = random.randint(0, 100)if num == 5 or num == 6:self.bulletCount += 1return Bullet(self)return Nonedef draw(self, window):# 获取展示的对象self.image = self.images[self.direction][self.life - 1]window.blit(self.image, self.rect)def randDirection(self):directions = ['UP', 'DOWN', 'LEFT', 'RIGHT']index = random.randint(0, 3)return directions[index]def collidePlayerTank(self, playerTank):# 遍历全部敌方坦克,检查有没有碰撞if pygame.sprite.collide_rect(self, playerTank):# 如果碰撞了,就保持原来的位置self.rect.left = self.prvXself.rect.top = self.prvYdef collideEnemyTank(self, enemyTankList):for tank in enemyTankList:if pygame.sprite.collide_rect(self, tank) and tank != self:self.rect.left = self.prvXself.rect.top = self.prvY

完整的我方坦克类代码

import pygame
import pygame.image
from ParentObject import ParentObject
from Bullet import Bulletclass PlayerTank(ParentObject):def __init__(self, x, y, order, amour):""":param x: 坦克横坐标:param y: 坦克纵坐标:param order: 玩家坦克序号,1表示一号玩家,2表示二号玩家:param amour: 坦克初始护甲"""super().__init__()self.images = []if order == 1:self.images.append({'UP': pygame.image.load('../Image/Player1/45x45/UP1.png'),'DOWN': pygame.image.load('../Image/Player1/45x45/DOWN1.png'),'LEFT': pygame.image.load('../Image/Player1/45x45/LEFT1.png'),'RIGHT': pygame.image.load('../Image/Player1/45x45/RIGHT1.png')})self.images.append({'UP': pygame.image.load('../Image/Player1/45x45/UP2.png'),'DOWN': pygame.image.load('../Image/Player1/45x45/DOWN2.png'),'LEFT': pygame.image.load('../Image/Player1/45x45/LEFT2.png'),'RIGHT': pygame.image.load('../Image/Player1/45x45/RIGHT2.png')})self.images.append({'UP': pygame.image.load('../Image/Player1/45x45/UP3.png'),'DOWN': pygame.image.load('../Image/Player1/45x45/DOWN3.png'),'LEFT': pygame.image.load('../Image/Player1/45x45/LEFT3.png'),'RIGHT': pygame.image.load('../Image/Player1/45x45/RIGHT3.png')})self.images.append({'UP': pygame.image.load('../Image/Player1/45x45/UP4.png'),'DOWN': pygame.image.load('../Image/Player1/45x45/DOWN4.png'),'LEFT': pygame.image.load('../Image/Player1/45x45/LEFT4.png'),'RIGHT': pygame.image.load('../Image/Player1/45x45/RIGHT4.png')})self.images.append({'UP': pygame.image.load('../Image/Player1/45x45/UP5.png'),'DOWN': pygame.image.load('../Image/Player1/45x45/DOWN5.png'),'LEFT': pygame.image.load('../Image/Player1/45x45/LEFT5.png'),'RIGHT': pygame.image.load('../Image/Player1/45x45/RIGHT5.png')})self.images.append({'UP': pygame.image.load('../Image/Player1/45x45/UP6.png'),'DOWN': pygame.image.load('../Image/Player1/45x45/DOWN6.png'),'LEFT': pygame.image.load('../Image/Player1/45x45/LEFT6.png'),'RIGHT': pygame.image.load('../Image/Player1/45x45/RIGHT6.png')})# 生命self.life = 3# 装甲self.armor = amour# 方向self.direction = 'UP'# 根据护甲选择坦克的样子self.image: pygame.Surface = self.images[max(self.armor - 1, 0)][self.direction]self.rect = self.image.get_rect()self.rect.left = xself.rect.top = y# 速度self.accumulation: float = 0self.speed = 2# 移动开关self.stop = True# 重生self.isResurrecting = False# 碰撞前的坐标self.prvX = self.rect.leftself.prvY = self.rect.top# 等级self.level = 1# 伤害self.damage = 1def move(self):if self.accumulation >= 1:self.accumulation = 0# 记录上一次的位置self.prvX = self.rect.leftself.prvY = self.rect.topif self.direction == 'LEFT':if self.rect.left > 0:self.rect.left -= self.speedelif self.direction == 'UP':if self.rect.top > 0:self.rect.top -= self.speedelif self.direction == 'DOWN':if self.rect.top < 555:self.rect.top += self.speedelif self.direction == 'RIGHT':if self.rect.left < 855:self.rect.left += self.speedelse:self.accumulation += 0.20def shot(self):return Bullet(self)def draw(self, window, x, y):# 坦克生命中为0,表示已经死亡,不再展示坦克if self.life <= 0:return# 判断坦克是否复合if self.isResurrecting:# 把坦克位置设置为指定的重生位置self.rect.left = xself.rect.top = yself.isResurrecting = Falseself.direction = 'UP'# 获取展示的对象self.image = self.images[max(self.armor - 1, 0)][self.direction]# 画出图片window.blit(self.image, self.rect)def collideEnemyTank(self, enemyTankList):# 遍历全部敌方坦克,检查有没有碰撞for enemyTank in enemyTankList:if pygame.sprite.collide_rect(self, enemyTank):# 如果碰撞了,就保持原来的位置self.rect.left = self.prvXself.rect.top = self.prvYdef loseLife(self, value = 1):self.life -= value

完整的子弹类代码

import pygame
from ParentObject import ParentObject
from Explode import Explode
from Sound import Soundclass Bullet(ParentObject):def __init__(self, tank):super().__init__()self.images = {'UP': pygame.image.load('../Image/Bullet/Bullet(UP).png'),'DOWN': pygame.image.load('../Image/Bullet/Bullet(DOWN).png'),'LEFT': pygame.image.load('../Image/Bullet/Bullet(LEFT).png'),'RIGHT': pygame.image.load('../Image/Bullet/Bullet(RIGHT).png')}# 方向self.direction = tank.directionself.image: pygame.Surface = self.images[self.direction]self.rect = self.image.get_rect()# 坦克发射子弹的位置if self.direction == 'UP':self.rect.left = tank.rect.left + 17.5self.rect.top = tank.rect.top - 25elif self.direction == 'DOWN':self.rect.left = tank.rect.left + 17.5self.rect.top = tank.rect.top + 25elif self.direction == 'LEFT':self.rect.left = tank.rect.left - 25self.rect.top = tank.rect.top + 17.5elif self.direction == 'RIGHT':self.rect.left = tank.rect.left + 25self.rect.top = tank.rect.top + 17.5# 速度self.accumulationMax: float = 0self.accumulation = 0.25self.speed = 10# 销毁开关self.isDestroy = False# 发射源self.source = tank# 伤害self.damage = tank.damagedef move(self, explodeList):if self.accumulation >= 1:self.accumulation = 0if self.direction == 'LEFT':self.rect.left -= self.speedelif self.direction == 'UP':self.rect.top -= self.speedelif self.direction == 'DOWN':self.rect.top += self.speedelif self.direction == 'RIGHT':self.rect.left += self.speed# 检查子弹是否出界self.checkBullet(explodeList)else:self.accumulation += 0.20def checkBullet(self, explodeList):toDestroy = False# 如果出界,就设置为销毁if self.rect.top < 0 or self.rect.top > 600:toDestroy = Trueif self.rect.left < 0 or self.rect.right > 900:toDestroy = Trueif toDestroy:explode = Explode(self, 25)explodeList.append(explode)self.isDestroy = TrueSound('../Sound/block.wav').play()def draw(self, window):window.blit(self.image, self.rect)def playerBulletCollideEnemyTank(self, enemyTankList, explodeList):# 循环遍历坦克列表,检查是否发生了碰撞for tank in enemyTankList:if pygame.sprite.collide_rect(tank, self):tank.loseLife(self.damage)# 把子弹设置为销毁状态self.isDestroy = Trueif 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.damageplayerTank.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 != 0:playerTank.isResurrecting = True# 让子弹销毁self.isDestroy = True

完整的音乐类代码

import pygameclass Sound:def __init__(self, filename):self.filename = filenamepygame.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

完整的爆炸效果类代码

import pygame.imageclass Explode:def __init__(self, object, size):# 获取爆炸对象的位置self.rect = object.rectself.images = []self.images.append([pygame.image.load('../Image/Explode/Explode50x50.png'),pygame.image.load('../Image/Explode/Explode50x50.png'),pygame.image.load('../Image/Explode/Explode50x50.png'),pygame.image.load('../Image/Explode/Explode50x50.png'),pygame.image.load('../Image/Explode/Explode50x50.png')])self.images.append([pygame.image.load('../Image/Explode/Explode25x25.png'),pygame.image.load('../Image/Explode/Explode25x25.png'),pygame.image.load('../Image/Explode/Explode25x25.png'),pygame.image.load('../Image/Explode/Explode25x25.png'),pygame.image.load('../Image/Explode/Explode25x25.png')])self.mode = 0if size == 25:self.mode = 1self.index = 0self.image = self.images[self.mode][self.index]self.isDestroy = Falsedef draw(self, window):# 根据索引获取爆炸对象, 添加到主窗口if self.index < len(self.images):self.image = self.images[self.mode][self.index]self.index += 1window.blit(self.image, self.rect)else:self.isDestroy = Trueself.index = 0

至此,坦克大战出了地图中的固定景物外,都有音效和动作,下面就为地图添加墙之类的物体了

相关文章:

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

学习 Python 之 Pygame 开发坦克大战&#xff08;四&#xff09;坦克大战添加音效1. 初始化音效2. 加入游戏开始音效和坦克移动音效3. 添加坦克开火音效4. 添加装甲削减音效5. 添加坦克爆炸音效6. 添加子弹击中边界音效坦克大战添加音效 我的素材放到了百度网盘里&#xff0c;…...

New和Malloc的使用及其差异

1&#xff0c;new的使用关于new的定义&#xff1a;new其实就是告诉计算机开辟一段新的空间&#xff0c;但是和一般的声明不同的是&#xff0c;new开辟的空间在堆上&#xff0c;而一般声明的变量存放在栈上。通常来说&#xff0c;当在局部函数中new出一段新的空间&#xff0c;该…...

2023年细胞生物学复习汇总

细胞分化 1.什么是细胞分化&#xff1f;细胞分化的特点是什么&#xff1f; 答&#xff1a;&#xff08;1&#xff09;细胞分化&#xff08;cell differentiation&#xff09;是指同一来源的细胞逐渐产生出形态结构、功能特征各不相同的细胞类群的过程&#xff0c;其结果是在空间…...

光伏VSG-基于虚拟同步发电机的光伏并网逆变器系统MATLAB仿真

采用MATLAB2021b仿真&#xff01;&#xff01;&#xff01;仿真模型1光伏电池模块&#xff08;采用MATLAB自带光伏模块&#xff09;、MPPT控制模块、升压模块、VSG控制模块、电流滞环控制模块。2s时改变光照强度 &#xff01;&#xff01;&#xff01;VSG输出有功功率、无功功率…...

高可用 - 02 Keepalived_VRRP工作原理

文章目录Keepalived VS HeartbeatKeepalived的用途VRRP与工作原理物理路由器和虚拟路由器Keepalived VS Heartbeat Keepalived是Linux下一个轻量级的高可用解决方案&#xff0c;它与Heartbeat、RoseHA实现的功能类似&#xff0c;都可以实现服务或者网络的高可用&#xff0c;但…...

vue实现xml在线编辑功能

先看效果 避免误会 这是一个在线编辑器 我们可以在这上面随意的编写xml代码格式 我们修改上面的内容之后 就可以在控制台输出内容 如果这正是您想要的东西 那就可以先创建一个vue项目 我们先引入依赖 npm install brace -S npm install element-ui -S npm install vue-cli…...

GitHub Workflow

GitHub Workflow 基本流程 把远程仓库克隆到本地 git clone xxxx.git在本地切换至新的分支 git checkout -b new_branch修改本地仓库的文件 项目修改完成后&#xff0c;查看修改的内容 git diff上传修改之后的内容到本地暂存区 git add modified_files将本地暂存区的代码更新…...

vue学习

vue 其实你只要安装一个vue-cli 就可以了 vue-cli 你可以用比较高的版本 这 当然是 可以滴...

Windows使用ssh协议远程连接ubuntu linux系统

Windows使用ssh协议远程连接ubuntu linux系统一、Windows远程连接ubuntu linux系统二、开启ubuntu ssh服务三、获取ubuntu子系统的ip地址四、从windows上通过ssh连接到ubuntu子系统五、设置ubuntu系统ssh自启动&#xff08;18.04&#xff09;一、Windows远程连接ubuntu linux系…...

大数据处理 - Overview

本文主要介绍大数据处理的一些思路。何谓海量数据处理?所谓海量数据处理&#xff0c;无非就是基于海量数据上的存储、处理、操作。何谓海量&#xff0c;就是数据量太大&#xff0c;所以导致要么是无法在较短时间内迅速解决&#xff0c;要么是数据太大&#xff0c;导致无法一次…...

12-Composer的配置与使用详解

1、自定义类与非类的自动加载与测试 # composer> php 包管理工具 &#xff0c;类似npm1.自己写的类&#xff0c;函数&#xff0c;接口&#xff0c;常量等全局成员&#xff0c;通过自动加载来实现按需加载 2.自己写的代码&#xff0c;有哪些依赖&#xff0c;用到了哪些外部成…...

RK3566开启wifi自适应

系统:linux(buildroot) 一、修改Makefile,使能RTW_ADAPTIVITY 文件路径:..\x3566_linux_v1.2.0\kernel\drivers\net\wireless\rockchip_wlan\rtl8821cs\Makefile 第74行&#xff1a; CONFIG_RTW_ADAPTIVITY_EN disable 改为&#xff1a; CONFIG_RTW_ADAPTIVITY_EN enab…...

shell编程之变量定义

typora-copy-images-to: pictures typora-root-url: …\pictures 文章目录typora-copy-images-to: pictures typora-root-url: ..\..\pictures一、SHELL介绍㈠ 什么是shell脚本&#xff1f;㈡ 什么时候用到脚本?㈢ shell脚本能干啥?㈣ 如何学习shell脚本&#xff1f;㈤ 学习s…...

Spring Cloud Alibaba 微服务简介

微服务简介 1 什么是微服务 2014年&#xff0c;Martin Fowler&#xff08;马丁福勒 &#xff09; 提出了微服务的概念&#xff0c;定义了微服务是由以单一应用程序构成的小服务&#xff0c;自己拥有自己的进程与轻量化处理&#xff0c;服务依业务功能设计&#xff0c;以全自动…...

【调试】GDB使用总结

启动 在shell下敲gdb命令即可启动gdb&#xff0c;启动后会显示下述信息&#xff0c;出现gdb提示符。 ➜ example gdb GNU gdb (Ubuntu 8.1.1-0ubuntu1) 8.1.1 Copyright (C) 2018 Free Software Foundation, Inc. License GPLv3: GNU GPL v…...

基于Spring、Spring MVC、MyBatis的招聘管理系统

文章目录项目介绍主要功能截图&#xff1a;首页账户管理招聘建议部分代码展示设计总结项目获取方式&#x1f345; 作者主页&#xff1a;Java韩立 &#x1f345; 简介&#xff1a;Java领域优质创作者&#x1f3c6;、 简历模板、学习资料、面试题库【关注我&#xff0c;都给你】 …...

软件测试基础

文章目录前言一、软件测试入门1.什么是软件测试&#xff1f;2.测试和开发的区别3.调试和测试的区别4.一些常问面试题5.测试人员需要具备的素质二、软件测试基础1.需求2.测试用例3.Bug4.软件的生命周期5.开发模型三、Bug1.如何创建bug2.Bug的级别3.Bug的生命周期4.跟开发产生争执…...

【算法基础】链表

一、单链表例题&#xff1a;实现一个单链表&#xff0c;链表初始为空&#xff0c;支持三种操作&#xff1a;向链表头插入一个数&#xff1b;删除第 k个插入的数后面的数&#xff1b;在第 k&#xfffd; 个插入的数后插入一个数。现在要对该链表进行 M次操作&#xff0c;进行完所…...

[AUTOSAR][Fls模块] Flash Driver Module

Flash Driver Module--jianqiang.xue一、 简介二、 措施方式一&#xff1a;将FLASH操作程序作为Bootloader组件的一部分固化在存储器中方式二&#xff1a;通过通讯口将该部分代码从上位机下载到指定的RAM方式三&#xff1a;将Flash功能函数作为数据运行(推荐&#xff01;&#…...

如何正确选择好用的投票平台微信公众平台投票链接链接投票平台

“年度人物楷模”网络评选投票_免费链接投票_作品投票通道_扫码投票怎样进行现在来说&#xff0c;公司、企业、学校更多的想借助短视频推广自己。通过微信投票小程序&#xff0c;网友们就可以通过手机拍视频上传视频参加活动&#xff0c;而短视频微信投票评选活动既可以给用户发…...

gocd部署应用

产品需要在多个环境部署测试&#xff0c;为了提高部署测试效率&#xff0c;故计划使用CD工具&#xff0c;jenkins确实足够强大&#xff0c;但是使用部署功能是需要安装插件的&#xff0c;再说自己本身只用部署功能&#xff0c;故决定找一个小巧的CD工具&#xff0c;经过一番查找…...

P2P视频聊天技术分析

整个P2P视频过程需要知道双方的媒体类型、流和候选者&#xff0c;所以这里就会用到一下技术&#xff1a; ​ 信令服务器socket.io ​ 状态机 ​ ICE服务器 ​ WebRTC框架 ​ 媒体协商 信令服务器Socket.io 信令服务器说白了作用就是发消息的中转站&#xff0c;A把msg发到…...

MyBatis 的一级、二级缓存机制

目录标题缓存什么是缓存为什么使用缓存什么样的数据能使用缓存&#xff0c;什么样的数据不能使用适用于缓存不适用于缓存MyBatis 一级缓存、二级缓存关系1. 一级缓存1.1 什么是一级缓存mybatis1.2 一级缓存配置1.3 什么情况下会命中一级缓存mybatis清除一级缓存的几种方法1.4 内…...

剑指 Offer 65. 不用加减乘除做加法

摘要 剑指 Offer 65. 不用加减乘除做加法 一、位运算 有符号整数通常用补码来表示和存储&#xff0c;补码具有如下特征&#xff1a; 正整数的补码与原码相同&#xff1b;负整数的补码为其原码除符号位外的所有位取反后加 11。可以将减法运算转化为补码的加法运算来实现。符…...

5年软件测试年薪30w+,我的坎坷之路谁又知道

在深圳做了五年软件测试工作&#xff0c;从之前的一脸懵的点点点&#xff0c;到现在会自动化测试&#xff0c;说一点点非计算机专业人员从事软件测试的心得体会&#xff0c;仅供参考交流。 大部分测试在公司没啥地位&#xff0c;当然如果你懂技术就还行&#xff0c;单纯点点点…...

【Opencv--自适应图像二值化】cv2.adaptiveThreshold()

【Opencv–adaptiveThreshold】自适应阈值图像二值化 文章目录【Opencv--adaptiveThreshold】自适应阈值图像二值化1. 介绍2. adaptiveThreshold函数2.1 函数调用2.2 补充说明3. 代码示例4. 效果4.1 原图&#xff08;ori.img&#xff09;4.2 处理后5. 参考1. 介绍 在这里 cv2.…...

洛谷P8601[蓝桥杯][2013年第四届真题]剪格子

题目描述如图 11 所示&#xff0c;33 的格子中填写了一些整数。我们沿着图中的红色线剪开&#xff0c;得到两个部分&#xff0c;每个部分的数字和都是 60。本题的要求就是请你编程判定&#xff1a;对给定的 mn 的格子中的整数&#xff0c;是否可以分割为两个部分&#xff0c;使…...

配置alias实现快速生成.gitignore文件

git工具&#xff1a;版本控制开发工具。 cscope工具&#xff1a;用于浏览C源码的工具&#xff0c;类似于ctags。在代码根目录下执行cscope -Rbq&#xff0c;然后产生三个索引文件&#xff08;cscope.out、cscope.in.out和cscope.po.out三个文件&#xff09;。 在Linux下使用vi…...

MySQL数据库调优————GROUP BY及DISTINCT优化

GROUP BY 三种处理GROUP BY的方式 松散索引扫描&#xff08;Loose Index Scan&#xff09;紧凑索引扫描&#xff08;Tight Index Scan&#xff09;临时表&#xff08;Temporary table&#xff09; 三种方式的性能一次递减 松散索引扫描 无需扫描满足条件的所有索引键即可返…...

LRU缓存算法

双向链表哈希表&#xff08;非线程安全&#xff09; https://leetcode.cn/problems/lru-cache/solutions/259678/lruhuan-cun-ji-zhi-by-leetcode-solution/ /*** LRU算法: 哈希表双向链表实现* 1. 双向链表按照被使用的顺序来存储, 靠近头部的节点是最近使用的, 靠近尾部的节…...

国外的电商网站有哪些/搜seo

一般来说&#xff0c;STM32的型号是这样表示的 STM32F103XYxxx 这XY是什么意思呢&#xff1f;其实啊&#xff0c;这个X表示引脚数量&#xff0c;具体的值有如下形式&#xff1a; R64PIN V100PIN Z144PIN Y表示FLASH容量大小&#xff0c;具体有如下取值&#xff1a; 4 16K…...

手机购物网站设计/网络运营seo是什么

原文链接:http://blog.csdn.net/xizero00/article/details/50914471 一、Layer的作用简介 Layer实际上定义了Layer的基本操作&#xff0c;即初始化层、前向传播和反向传播。在前向传播中根据bottom blob得到top blob&#xff0c;反向传播则根据top反传到bottom。而且在前传的…...

东莞人才网站/百度app下载链接

美女&#xff0c;当你选择丈夫时&#xff0c;请先把电子工程师与以下的职业作一番比较&#xff1a;      医生几乎所有女人都喜欢追求当医生的。所以不要期望你们的婚姻能持续五年以上&#xff0c;因为早晚有一天&#xff0c;他会跟某个护士小姐跑掉的&#xff0c;或是被…...

售卖网站建设实验报告/网络营销出来可以干什么工作

es6 的 import 语法跟 require 不同&#xff0c;而且 import 必须放在文件的最开始&#xff0c;且前面不允许有其他逻辑代码&#xff0c;这和其他所有编程语言风格一致。 import不同与require&#xff0c;它是编译时的&#xff08;require是运行时的&#xff09;&#xff0c;它…...

厦门网站制作公司推荐/网站策划书模板

文章目录编程工具spyderIPYHONanaconda是集成很多工具的集成平台&#xff0c;将很多第三方的开发调试环境集成到了一起。anaconda来源于包管理和环境管理工具conda可以管理调试包编程工具spyder ipython对运行结果显示&#xff0c;文件导航实际应用不太需要&#xff0c;如下改界…...

直播网站app开发/app开发费用一览表

SDK Manager 打不开, "系统找不到指定路径 " "Unable to access jarfile lib\archquery.jar"问题的解决办法参考文章&#xff1a; &#xff08;1&#xff09;SDK Manager 打不开, "系统找不到指定路径 " "Unable to access jarfile lib\ar…...