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

书读的越多而不加思考,你就会觉得你知道得很多;而当你读书而思考得越多的时候,你就会越清楚地看到,你知道得很少。

导读:本篇文章讲解 学习 Python 之 Pygame 开发坦克大战(三),希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

坦克大战物体碰撞检测编写

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

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

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

1. 实现敌方坦克与我方坦克间的碰撞

由于已经完成了屏幕中出现敌方和我方坦克,现在的问题就是如果我方坦克碰到了敌方坦克,应该是走不动的,即不能穿模

在敌方坦克类和我方坦克类中加入两个属性,用来记录上一次的位置,如果是你用的是继承,那么在父类加入

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

修改我方坦克类move()函数

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

修改敌方坦克类move()函数

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

加入碰撞检测函数
在两个类中都加入

pygame.sprite.collide_rect()函数用来检测物体碰撞,该物体必须继承pygame.sprite.Sprite类

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 collidePlayerTank(self, playerTank):
    # 遍历全部敌方坦克,检查有没有碰撞
    if pygame.sprite.collide_rect(self, playerTank):
        # 如果碰撞了,就保持原来的位置
        self.rect.left = self.prvX
        self.rect.top = self.prvY

在坦克移动下面调用该函数

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

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

    # 显示我方坦克
    MainGame.playerTank.draw(MainGame.window)

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

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

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

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

    # 更新窗口
    pygame.display.update()
# 遍历坦克列表,展示坦克并且移动
for tank in MainGame.enemyTankList:
    # 坦克还有生命值
    if tank.life > 0:
        tank.draw(MainGame.window)
        tank.move()
        tank.collidePlayerTank(MainGame.playerTank)
        bullet = tank.shot()
        if bullet is not None:
            MainGame.enemyTankBulletList.append(bullet)
    # 坦克生命值为0,就从列表中剔除
    else:
        MainGame.enemyTankCurrentCount -= 1
        MainGame.enemyTankList.remove(tank)

完整的我方坦克代码

import pygame as pg
import pygame.image
from ParentObject import ParentObject
from Teach.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: pg.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):
        # 坦克生命中为0,表示已经死亡,不再展示坦克
        if self.life <= 0:
            return
        # 获取展示的对象
        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

完整的敌方坦克代码

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

完整的主类代码

import pygame
import sys

from PlayerTank import PlayerTank
from EnemyTank import EnemyTank

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 = []

    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)

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

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

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

            # 显示我方坦克
            MainGame.playerTank.draw(MainGame.window)

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

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

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

            # 更新窗口
            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:
                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:
                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()
            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)
                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()
            else:
                bullet.source.bulletCount -= 1
                MainGame.enemyTankBulletList.remove(bullet)

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



运行一下,看看结果

2. 实现敌方坦克间的碰撞

敌方坦克与敌方坦克也是不能穿模的,需要实现一下
这个的代码跟上面的差不多

在敌方坦克类中添加敌方坦克间碰撞检测函数

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

在主类中的drawEnemyTank()函数中调用

# 遍历坦克列表,展示坦克并且移动
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)

完整的drawEnemyTank()函数

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)

运行一下,看看结果

发现实现啦

3. 实现玩家子弹与敌方坦克间的碰撞

在两个坦克类中增加生命值减少函数,默认情况下,每次减少一点生命值

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

在子弹类中增加碰撞检测函数

def playerBulletCollideEnemyTank(self, enemyTankList):
    # 循环遍历坦克列表,检查是否发生了碰撞
    for tank in enemyTankList:
        if pygame.sprite.collide_rect(tank, self):
        	# 坦克被击中就扣减生命值
            tank.loseLife(self.damage)
            # 把子弹设置为销毁状态
            self.isDestroy = True

在drawPlayerBullet()函数中调用

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

运行一下,我们就可以看到击中敌方坦克时,敌方坦克会变色,因为生命值发生了变化

在这里插入图片描述

4. 实现敌方子弹与我方坦克间的碰撞 和 玩家复活

首先我们要考虑到,当玩家生命值不为0时,被击中了需要在出生的复活,此时需要给玩家坦克类添加一个属性,用来判断此时玩家是否要复活

# 重生
self.isResurrecting = False

在子弹类中增加碰撞检测函数

def enemyBulletCollidePlayerTank(self, playerTank):
    # 玩家坦克生命值为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)
        else:
            playerTank.loseLife(self.damage)
            playerTank.life = max(0, playerTank.life)
            if playerTank.life != 0:
                playerTank.isResurrecting = True
        # 让子弹销毁
        self.isDestroy = True

在drawEnemyBullet()函数中调用

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

修改我方坦克类的draw()函数

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)

在while循环中修改draw()函数参数

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

测试一下,看看能不能实现玩家死亡

5. 爆炸效果类

现在敌方坦克和我方坦克都可以被消灭了,但是消灭的效果不是很好,下面增加一个爆炸效果类,更好地看到坦克被消灭

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):
    	pass

这里我分为了两种爆炸效果,它们的烦恼不同,即爆炸效果的图片大小不一样,为了让爆炸效果能看到,而不是一闪而过,我让图片加载五次

修改draw()函数

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

在主类中添加爆炸列表

class MainGame:

    ...
    
    # 爆炸列表
    explodeList = []

	...

在主类中增加显示爆炸效果函数

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

在while循环中调用drawExplode()

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

6. 为子弹爆炸添加爆炸效果

子弹爆炸添加爆炸效果

修改子弹类的move()函数

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

此时如果子弹击中边界,就会出现爆炸效果

修改调用处

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

试一试效果,看看子弹出界有没有爆炸效果

7. 为坦克爆炸添加爆炸效果

修改 子弹类中 playerBulletCollideEnemyTank() 函数和 enemyBulletCollidePlayerTank() 函数

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)

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

修改调用处

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

完整的敌方坦克类代码

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 = False
        # 开火开关
        self.fire = False
        # 步数
        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
import sys

from PlayerTank import PlayerTank
from EnemyTank import EnemyTank

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 = []

    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)

        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:
                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:
                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 pygame
from ParentObject import ParentObject
from Explode import Explode


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

    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)

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



版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由半码博客整理,本文链接:https://www.bmabk.com/index.php/post/122780.html

(0)

相关推荐

发表回复

登录后才能评论
半码博客——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!