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

坦克大战添加音效

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

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

坦克大战代码链接:百度网盘
链接:https://pan.baidu.com/s/1qFV-0hi0cgZS1Hnvx6mK6Q?pwd=90tk
提取码:90tk

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

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 != 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 = True
    if self.rect.left < 0 or self.rect.right > 900:
        toDestroy = True
    if toDestroy:
        explode = Explode(self, 25)
        explodeList.append(explode)
        self.isDestroy = True
        Sound('../Sound/block.wav').play()

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

完整的主类代码

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)
                        # 添加音效
                        Sound('../Sound/shoot.wav').play(0)

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



完整的敌方坦克类代码

import random
import pygame
import pygame.image

from ParentObject import ParentObject
from Bullet import Bullet


class 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 = x
        self.rect.top = y

        # 碰撞前的坐标
        self.prvX = self.rect.left
        self.prvY = self.rect.top

        # 速度
        self.accumulationMax: float = 0
        self.accumulation = 0.1

        speed = 0
        maxBulletCount = 0
        damage = 1
        # 每种坦克都有不同的属性
        if self.type[0] == 1:
            speed = 3
            self.level = 1
            maxBulletCount = 1
        elif self.type[0] == 2:
            speed = 5
            self.level = 2
            maxBulletCount = 1
            damage = 3
        elif self.type[0] == 3:
            speed = 7
            self.level = 1
            maxBulletCount = 3
            damage = 2
        elif self.type[0] == 4:
            speed = 6
            self.level = 2
            maxBulletCount = 3
            damage = 1
        self.speed = speed
        # 移动开关
        self.stop = True
        # 开火开关
        self.fire = True
        # 步数
        self.step = 30
        # 伤害
        self.damage = damage
        # 子弹个数
        self.bulletCount = 0
        self.maxBulletCount = maxBulletCount

    def loseLife(self, value = 1):
        self.life -= value

    def move(self):
        """
        新增步数变量, 当坦克移动时, 步数进行减少, 当步数小于等于0的时候, 修改地方坦克的方向
        :return: None
        """
        if self.stop:
            if self.step <= 0:
                self.direction = self.randDirection()
                self.step = 30
            else:
                if self.accumulationMax >= 1:
                    self.accumulationMax = 0
                    # 记录上一次的位置
                    self.prvX = self.rect.left
                    self.prvY = self.rect.top
                    if self.direction == 'LEFT':
                        if self.rect.left > 0:
                            self.rect.left -= self.speed
                    elif self.direction == 'UP':
                        if self.rect.top > 0:
                            self.rect.top -= self.speed
                    elif self.direction == 'DOWN':
                        if self.rect.top < 555:
                            self.rect.top += self.speed
                    elif self.direction == 'RIGHT':
                        if self.rect.left < 855:
                            self.rect.left += self.speed
                    self.step -= 1
                else:
                    self.accumulationMax += self.accumulation

    def shot(self):
        if self.fire:
            if self.bulletCount < self.maxBulletCount:
                num = random.randint(0, 100)
                if num == 5 or num == 6:
                    self.bulletCount += 1
                    return Bullet(self)
        return None

    def 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.prvX
            self.rect.top = self.prvY

    def collideEnemyTank(self, enemyTankList):
        for tank in enemyTankList:
            if pygame.sprite.collide_rect(self, tank) and tank != self:
                self.rect.left = self.prvX
                self.rect.top = self.prvY

完整的我方坦克类代码

import pygame
import pygame.image
from ParentObject import ParentObject
from Bullet import Bullet


class 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 = x
        self.rect.top = y

        # 速度
        self.accumulation: float = 0
        self.speed = 2
        # 移动开关
        self.stop = True
        # 重生
        self.isResurrecting = False
        # 碰撞前的坐标
        self.prvX = self.rect.left
        self.prvY = self.rect.top

        # 等级
        self.level = 1
        # 伤害
        self.damage = 1

    def move(self):
        if self.accumulation >= 1:
            self.accumulation = 0
            # 记录上一次的位置
            self.prvX = self.rect.left
            self.prvY = self.rect.top
            if self.direction == 'LEFT':
                if self.rect.left > 0:
                    self.rect.left -= self.speed
            elif self.direction == 'UP':
                if self.rect.top > 0:
                    self.rect.top -= self.speed
            elif self.direction == 'DOWN':
                if self.rect.top < 555:
                    self.rect.top += self.speed
            elif self.direction == 'RIGHT':
                if self.rect.left < 855:
                    self.rect.left += self.speed
        else:
            self.accumulation += 0.20


    def shot(self):
        return Bullet(self)

    def draw(self, window, x, y):
        # 坦克生命中为0,表示已经死亡,不再展示坦克
        if self.life <= 0:
            return
        # 判断坦克是否复合
        if self.isResurrecting:
            # 把坦克位置设置为指定的重生位置
            self.rect.left = x
            self.rect.top = y
            self.isResurrecting = False
            self.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.prvX
                self.rect.top = self.prvY

    def loseLife(self, value = 1):
        self.life -= value

完整的子弹类代码

import pygame
from ParentObject import ParentObject
from Explode import Explode
from Sound import Sound


class 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.direction
        self.image: pygame.Surface = self.images[self.direction]
        self.rect = self.image.get_rect()

        # 坦克发射子弹的位置
        if self.direction == 'UP':
            self.rect.left = tank.rect.left + 17.5
            self.rect.top = tank.rect.top - 25
        elif self.direction == 'DOWN':
            self.rect.left = tank.rect.left + 17.5
            self.rect.top = tank.rect.top + 25
        elif self.direction == 'LEFT':
            self.rect.left = tank.rect.left - 25
            self.rect.top = tank.rect.top + 17.5
        elif self.direction == 'RIGHT':
            self.rect.left = tank.rect.left + 25
            self.rect.top = tank.rect.top + 17.5

        # 速度
        self.accumulationMax: float = 0
        self.accumulation = 0.25
        self.speed = 10
        # 销毁开关
        self.isDestroy = False
        # 发射源
        self.source = tank
        # 伤害
        self.damage = tank.damage

    def move(self, explodeList):
        if self.accumulation >= 1:
            self.accumulation = 0
            if self.direction == 'LEFT':
                self.rect.left -= self.speed
            elif self.direction == 'UP':
                self.rect.top -= self.speed
            elif self.direction == 'DOWN':
                self.rect.top += self.speed
            elif self.direction == 'RIGHT':
                self.rect.left += self.speed
            # 检查子弹是否出界
            self.checkBullet(explodeList)
        else:
            self.accumulation += 0.20

    def checkBullet(self, explodeList):
        toDestroy = False
        # 如果出界,就设置为销毁
        if self.rect.top < 0 or self.rect.top > 600:
            toDestroy = True
        if self.rect.left < 0 or self.rect.right > 900:
            toDestroy = True
        if toDestroy:
            explode = Explode(self, 25)
            explodeList.append(explode)
            self.isDestroy = True
            Sound('../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 = 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 != 0:
                    playerTank.isResurrecting = True
            # 让子弹销毁
            self.isDestroy = True



完整的音乐类代码

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

完整的爆炸效果类代码

import pygame.image


class Explode:
    def __init__(self, object, size):
        # 获取爆炸对象的位置
        self.rect = object.rect
        self.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 = 0
        if size == 25:
            self.mode = 1
        self.index = 0
        self.image = self.images[self.mode][self.index]
        self.isDestroy = False

    def draw(self, window):
        # 根据索引获取爆炸对象, 添加到主窗口
        if self.index < len(self.images):
            self.image = self.images[self.mode][self.index]
            self.index += 1
            window.blit(self.image, self.rect)
        else:
            self.isDestroy = True
            self.index = 0

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

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Pygame是一个基于Python的游戏开发库,它提供了一系列用于游戏开发的功能和工具。通过Pygame,你可以使用Python语言来创建各种类型的游戏,包括坦克大战。 在Pygame开发坦克大战游戏,你可以按照以下步骤进行: 1. 安装Pygame库:首先,你需要在你的Python环境中安装Pygame库。可以使用pip命令来安装,如下所示: ``` pip install pygame ``` 2. 导入Pygame库:在你的Python代码中,使用`import pygame`语句来导入Pygame库。 3. 初始化Pygame:在你的代码中,使用`pygame.init()`函数来初始化Pygame。 4. 创建游戏窗口:使用`pygame.display.set_mode()`函数创建一个游戏窗口,设置窗口的大小和其他属性。 5. 加载游戏资源:加载游戏所需的图像、音频等资源文件,并将其存储在适当的变量中。 6. 处理用户输入:使用Pygame提供的事件处理机制来处理用户的键盘或鼠标输入。 7. 更新游戏状态:根据用户输入和游戏规则,更新游戏中的各个元素的状态。 8. 绘制游戏画面:使用Pygame提供的绘图函数来绘制游戏中的各个元素,包括坦克、子弹、地图等。 9. 游戏循环:使用一个无限循环来不断更新游戏状态和绘制游戏画面,以实现游戏的动态效果。 10. 游戏结束:根据游戏规则,判断游戏是否结束,并在适当的时候退出游戏循环。 以上是一个简单的坦克大战游戏开发的基本步骤。当然,具体的实现还需要根据你的需求和设计来进行。你可以参考Pygame官方文档和示例代码,以及其他相关教程和资源来更详细地学习和了解Pygame的使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值