学习 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
至此,坦克大战出了地图中的固定景物外,都有音效和动作,下面就为地图添加墙之类的物体了
相关文章:
![](https://www.ngui.cc/images/no-images.jpg)
学习 Python 之 Pygame 开发坦克大战(四)
学习 Python 之 Pygame 开发坦克大战(四)坦克大战添加音效1. 初始化音效2. 加入游戏开始音效和坦克移动音效3. 添加坦克开火音效4. 添加装甲削减音效5. 添加坦克爆炸音效6. 添加子弹击中边界音效坦克大战添加音效 我的素材放到了百度网盘里,…...
![](https://img-blog.csdnimg.cn/img_convert/ec43f7f5f6b0ceacae649c4038099600.png)
New和Malloc的使用及其差异
1,new的使用关于new的定义:new其实就是告诉计算机开辟一段新的空间,但是和一般的声明不同的是,new开辟的空间在堆上,而一般声明的变量存放在栈上。通常来说,当在局部函数中new出一段新的空间,该…...
![](https://www.ngui.cc/images/no-images.jpg)
2023年细胞生物学复习汇总
细胞分化 1.什么是细胞分化?细胞分化的特点是什么? 答:(1)细胞分化(cell differentiation)是指同一来源的细胞逐渐产生出形态结构、功能特征各不相同的细胞类群的过程,其结果是在空间…...
![](https://img-blog.csdnimg.cn/img_convert/f5d8adf8b59b476bae061c0327e633ec.png)
光伏VSG-基于虚拟同步发电机的光伏并网逆变器系统MATLAB仿真
采用MATLAB2021b仿真!!!仿真模型1光伏电池模块(采用MATLAB自带光伏模块)、MPPT控制模块、升压模块、VSG控制模块、电流滞环控制模块。2s时改变光照强度 !!!VSG输出有功功率、无功功率…...
![](https://img-blog.csdnimg.cn/be6ef26cd5564380ac3b44e5512dde59.jpeg#pic_center)
高可用 - 02 Keepalived_VRRP工作原理
文章目录Keepalived VS HeartbeatKeepalived的用途VRRP与工作原理物理路由器和虚拟路由器Keepalived VS Heartbeat Keepalived是Linux下一个轻量级的高可用解决方案,它与Heartbeat、RoseHA实现的功能类似,都可以实现服务或者网络的高可用,但…...
![](https://img-blog.csdnimg.cn/5cb7f24ce3504f45a0c043d24cbe0680.png)
vue实现xml在线编辑功能
先看效果 避免误会 这是一个在线编辑器 我们可以在这上面随意的编写xml代码格式 我们修改上面的内容之后 就可以在控制台输出内容 如果这正是您想要的东西 那就可以先创建一个vue项目 我们先引入依赖 npm install brace -S npm install element-ui -S npm install vue-cli…...
![](https://www.ngui.cc/images/no-images.jpg)
GitHub Workflow
GitHub Workflow 基本流程 把远程仓库克隆到本地 git clone xxxx.git在本地切换至新的分支 git checkout -b new_branch修改本地仓库的文件 项目修改完成后,查看修改的内容 git diff上传修改之后的内容到本地暂存区 git add modified_files将本地暂存区的代码更新…...
![](https://www.ngui.cc/images/no-images.jpg)
vue学习
vue 其实你只要安装一个vue-cli 就可以了 vue-cli 你可以用比较高的版本 这 当然是 可以滴...
![](https://img-blog.csdnimg.cn/4e7972bed10c49bc99e944f84f96e2cc.png)
Windows使用ssh协议远程连接ubuntu linux系统
Windows使用ssh协议远程连接ubuntu linux系统一、Windows远程连接ubuntu linux系统二、开启ubuntu ssh服务三、获取ubuntu子系统的ip地址四、从windows上通过ssh连接到ubuntu子系统五、设置ubuntu系统ssh自启动(18.04)一、Windows远程连接ubuntu linux系…...
![](https://www.ngui.cc/images/no-images.jpg)
大数据处理 - Overview
本文主要介绍大数据处理的一些思路。何谓海量数据处理?所谓海量数据处理,无非就是基于海量数据上的存储、处理、操作。何谓海量,就是数据量太大,所以导致要么是无法在较短时间内迅速解决,要么是数据太大,导致无法一次…...
![](https://img-blog.csdnimg.cn/5446fd91dd5a4535bdd7279e357e9fcf.png)
12-Composer的配置与使用详解
1、自定义类与非类的自动加载与测试 # composer> php 包管理工具 ,类似npm1.自己写的类,函数,接口,常量等全局成员,通过自动加载来实现按需加载 2.自己写的代码,有哪些依赖,用到了哪些外部成…...
![](https://www.ngui.cc/images/no-images.jpg)
RK3566开启wifi自适应
系统:linux(buildroot) 一、修改Makefile,使能RTW_ADAPTIVITY 文件路径:..\x3566_linux_v1.2.0\kernel\drivers\net\wireless\rockchip_wlan\rtl8821cs\Makefile 第74行: CONFIG_RTW_ADAPTIVITY_EN disable 改为: CONFIG_RTW_ADAPTIVITY_EN enab…...
![](https://www.ngui.cc/images/no-images.jpg)
shell编程之变量定义
typora-copy-images-to: pictures typora-root-url: …\pictures 文章目录typora-copy-images-to: pictures typora-root-url: ..\..\pictures一、SHELL介绍㈠ 什么是shell脚本?㈡ 什么时候用到脚本?㈢ shell脚本能干啥?㈣ 如何学习shell脚本?㈤ 学习s…...
![](https://img-blog.csdnimg.cn/img_convert/9243fb37a8b68a34473dc67d881e16a2.png)
Spring Cloud Alibaba 微服务简介
微服务简介 1 什么是微服务 2014年,Martin Fowler(马丁福勒 ) 提出了微服务的概念,定义了微服务是由以单一应用程序构成的小服务,自己拥有自己的进程与轻量化处理,服务依业务功能设计,以全自动…...
![](https://www.ngui.cc/images/no-images.jpg)
【调试】GDB使用总结
启动 在shell下敲gdb命令即可启动gdb,启动后会显示下述信息,出现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…...
![](https://img-blog.csdnimg.cn/da1884cedd4447c9b8d55574662870c9.png)
基于Spring、Spring MVC、MyBatis的招聘管理系统
文章目录项目介绍主要功能截图:首页账户管理招聘建议部分代码展示设计总结项目获取方式🍅 作者主页:Java韩立 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 …...
![](https://img-blog.csdnimg.cn/1f6024a052f94991963c9b31dd50c759.png)
软件测试基础
文章目录前言一、软件测试入门1.什么是软件测试?2.测试和开发的区别3.调试和测试的区别4.一些常问面试题5.测试人员需要具备的素质二、软件测试基础1.需求2.测试用例3.Bug4.软件的生命周期5.开发模型三、Bug1.如何创建bug2.Bug的级别3.Bug的生命周期4.跟开发产生争执…...
![](https://img-blog.csdnimg.cn/img_convert/f9328b5b173e407f8e9b292dba1949c8.png)
【算法基础】链表
一、单链表例题:实现一个单链表,链表初始为空,支持三种操作:向链表头插入一个数;删除第 k个插入的数后面的数;在第 k� 个插入的数后插入一个数。现在要对该链表进行 M次操作,进行完所…...
![](https://img-blog.csdnimg.cn/b5471d54472a44daa356d613101dbfa2.png)
[AUTOSAR][Fls模块] Flash Driver Module
Flash Driver Module--jianqiang.xue一、 简介二、 措施方式一:将FLASH操作程序作为Bootloader组件的一部分固化在存储器中方式二:通过通讯口将该部分代码从上位机下载到指定的RAM方式三:将Flash功能函数作为数据运行(推荐!&#…...
![](https://img-blog.csdnimg.cn/img_convert/daa85cc12cbff468fa28b7399f870fff.jpeg)
如何正确选择好用的投票平台微信公众平台投票链接链接投票平台
“年度人物楷模”网络评选投票_免费链接投票_作品投票通道_扫码投票怎样进行现在来说,公司、企业、学校更多的想借助短视频推广自己。通过微信投票小程序,网友们就可以通过手机拍视频上传视频参加活动,而短视频微信投票评选活动既可以给用户发…...
![](https://img-blog.csdnimg.cn/img_convert/9e144804e9ab8d53964081b8e03cf908.png)
gocd部署应用
产品需要在多个环境部署测试,为了提高部署测试效率,故计划使用CD工具,jenkins确实足够强大,但是使用部署功能是需要安装插件的,再说自己本身只用部署功能,故决定找一个小巧的CD工具,经过一番查找…...
![](https://img-blog.csdnimg.cn/08c10ad5eca54e6ba6cd060d64c5bebd.png)
P2P视频聊天技术分析
整个P2P视频过程需要知道双方的媒体类型、流和候选者,所以这里就会用到一下技术: 信令服务器socket.io 状态机 ICE服务器 WebRTC框架 媒体协商 信令服务器Socket.io 信令服务器说白了作用就是发消息的中转站,A把msg发到…...
![](https://img-blog.csdnimg.cn/8502bf7c408841d2a313919149491d8b.png)
MyBatis 的一级、二级缓存机制
目录标题缓存什么是缓存为什么使用缓存什么样的数据能使用缓存,什么样的数据不能使用适用于缓存不适用于缓存MyBatis 一级缓存、二级缓存关系1. 一级缓存1.1 什么是一级缓存mybatis1.2 一级缓存配置1.3 什么情况下会命中一级缓存mybatis清除一级缓存的几种方法1.4 内…...
![](https://www.ngui.cc/images/no-images.jpg)
剑指 Offer 65. 不用加减乘除做加法
摘要 剑指 Offer 65. 不用加减乘除做加法 一、位运算 有符号整数通常用补码来表示和存储,补码具有如下特征: 正整数的补码与原码相同;负整数的补码为其原码除符号位外的所有位取反后加 11。可以将减法运算转化为补码的加法运算来实现。符…...
![](https://www.ngui.cc/images/no-images.jpg)
5年软件测试年薪30w+,我的坎坷之路谁又知道
在深圳做了五年软件测试工作,从之前的一脸懵的点点点,到现在会自动化测试,说一点点非计算机专业人员从事软件测试的心得体会,仅供参考交流。 大部分测试在公司没啥地位,当然如果你懂技术就还行,单纯点点点…...
![](https://img-blog.csdnimg.cn/6dd11855af644d9c97dea427243e24d2.png)
【Opencv--自适应图像二值化】cv2.adaptiveThreshold()
【Opencv–adaptiveThreshold】自适应阈值图像二值化 文章目录【Opencv--adaptiveThreshold】自适应阈值图像二值化1. 介绍2. adaptiveThreshold函数2.1 函数调用2.2 补充说明3. 代码示例4. 效果4.1 原图(ori.img)4.2 处理后5. 参考1. 介绍 在这里 cv2.…...
![](https://img-blog.csdnimg.cn/img_convert/9b66939be6cf4625bb425f28edf9ca18.png)
洛谷P8601[蓝桥杯][2013年第四届真题]剪格子
题目描述如图 11 所示,33 的格子中填写了一些整数。我们沿着图中的红色线剪开,得到两个部分,每个部分的数字和都是 60。本题的要求就是请你编程判定:对给定的 mn 的格子中的整数,是否可以分割为两个部分,使…...
![](https://www.ngui.cc/images/no-images.jpg)
配置alias实现快速生成.gitignore文件
git工具:版本控制开发工具。 cscope工具:用于浏览C源码的工具,类似于ctags。在代码根目录下执行cscope -Rbq,然后产生三个索引文件(cscope.out、cscope.in.out和cscope.po.out三个文件)。 在Linux下使用vi…...
![](https://img-blog.csdnimg.cn/2aadb15bad8d4c4d83bf1e037e3c8f0f.png)
MySQL数据库调优————GROUP BY及DISTINCT优化
GROUP BY 三种处理GROUP BY的方式 松散索引扫描(Loose Index Scan)紧凑索引扫描(Tight Index Scan)临时表(Temporary table) 三种方式的性能一次递减 松散索引扫描 无需扫描满足条件的所有索引键即可返…...
![](https://www.ngui.cc/images/no-images.jpg)
LRU缓存算法
双向链表哈希表(非线程安全) https://leetcode.cn/problems/lru-cache/solutions/259678/lruhuan-cun-ji-zhi-by-leetcode-solution/ /*** LRU算法: 哈希表双向链表实现* 1. 双向链表按照被使用的顺序来存储, 靠近头部的节点是最近使用的, 靠近尾部的节…...
国外的电商网站有哪些/搜seo
一般来说,STM32的型号是这样表示的 STM32F103XYxxx 这XY是什么意思呢?其实啊,这个X表示引脚数量,具体的值有如下形式: R64PIN V100PIN Z144PIN Y表示FLASH容量大小,具体有如下取值: 4 16K…...
手机购物网站设计/网络运营seo是什么
原文链接:http://blog.csdn.net/xizero00/article/details/50914471 一、Layer的作用简介 Layer实际上定义了Layer的基本操作,即初始化层、前向传播和反向传播。在前向传播中根据bottom blob得到top blob,反向传播则根据top反传到bottom。而且在前传的…...
![](/images/no-images.jpg)
东莞人才网站/百度app下载链接
美女,当你选择丈夫时,请先把电子工程师与以下的职业作一番比较: 医生几乎所有女人都喜欢追求当医生的。所以不要期望你们的婚姻能持续五年以上,因为早晚有一天,他会跟某个护士小姐跑掉的,或是被…...
![](/images/no-images.jpg)
售卖网站建设实验报告/网络营销出来可以干什么工作
es6 的 import 语法跟 require 不同,而且 import 必须放在文件的最开始,且前面不允许有其他逻辑代码,这和其他所有编程语言风格一致。 import不同与require,它是编译时的(require是运行时的),它…...
![](https://img-blog.csdnimg.cn/20191022182346262.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl8zOTI4OTg3Ng==,size_16,color_FFFFFF,t_70)
厦门网站制作公司推荐/网站策划书模板
文章目录编程工具spyderIPYHONanaconda是集成很多工具的集成平台,将很多第三方的开发调试环境集成到了一起。anaconda来源于包管理和环境管理工具conda可以管理调试包编程工具spyder ipython对运行结果显示,文件导航实际应用不太需要,如下改界…...
![](/images/no-images.jpg)
直播网站app开发/app开发费用一览表
SDK Manager 打不开, "系统找不到指定路径 " "Unable to access jarfile lib\archquery.jar"问题的解决办法参考文章: (1)SDK Manager 打不开, "系统找不到指定路径 " "Unable to access jarfile lib\ar…...