【Pygame小游戏(3)——坦克大战_坦克属性及碰撞检测】

 1、源码来源:

nullicon-default.png?t=N7T8https://github.com/wangxingyao/TankWar?tab=readme-ov-file

完整代码在文末

2、导入模块

import pygame  # 导入pygame模块
import bulletClass # 导入自定义模块

3、设置坦克升级之后的图像

# 玩家1和玩家2的不同坦克等级的图像文件路径
tank_T1_0 = r"..\image\tank_T1_0.png"
tank_T1_1 = r"..\image\tank_T1_1.png"
tank_T1_2 = r"..\image\tank_T1_2.png"
tank_T2_0 = r"..\image\tank_T2_0.png"
tank_T2_1 = r"..\image\tank_T2_1.png"
tank_T2_2 = r"..\image\tank_T2_2.png"

4、定义MyTank类并初始化精灵

class MyTank(pygame.sprite.Sprite):
    def __init__(self, playerNumber):
        # 初始化精灵
        pygame.sprite.Sprite.__init__(self)

5、设置玩家生命状态

        # 玩家生命状态
        self.life = True

6、 根据不同的玩家编号加载不同的坦克图像


        # 根据玩家编号加载不同等级的坦克图像
        if playerNumber == 1:
            self.tank_L0_image = pygame.image.load(tank_T1_0).convert_alpha()  # 0级坦克
            #pygame.image.load(tank_T1_1):使用 Pygame 的 image.load() 方法加载指定路径(tank_T1_1)中的图像文件。
            # 这个路径对应的是玩家1在1级时的坦克图像文件。
            #.convert_alpha():将加载的图像转换为包含 alpha 通道的图像格式(RGBA)
            # ,这允许图像支持透明背景,从而使渲染更高效且图像显示效果更好。
            self.tank_L1_image = pygame.image.load(tank_T1_1).convert_alpha()  # 1级坦克
            self.tank_L2_image = pygame.image.load(tank_T1_2).convert_alpha()  # 2级坦克
        if playerNumber == 2:
            self.tank_L0_image = pygame.image.load(tank_T2_0).convert_alpha()  # 0级坦克
            self.tank_L1_image = pygame.image.load(tank_T2_1).convert_alpha()  # 1级坦克
            self.tank_L2_image = pygame.image.load(tank_T2_2).convert_alpha()  # 2级坦克

7、坦克等级初始化

        # 坦克等级初始化为0级
        #因此,self.level = 0 的主要作用是确保每次创建 MyTank 实例时,坦克的等级都从最基础的状态开始。
        self.level = 0

在代码中,self.level = 0 的作用是初始化坦克的等级。具体而言:

  • 坦克等级self.level 代表坦克的当前等级。在这个游戏逻辑中,坦克可以升级或降级,从而改变其能力(例如子弹的速度和强度)。等级0代表初始状态,较低的能力,随着等级增加,坦克的能力会增强。

  • 初始化:在 MyTank 类的 __init__ 方法中,将 self.level 初始化为 0,表示玩家的坦克从最低等级(0级)开始。之后,玩家可以通过游戏中的某些行为(例如获得道具)来升级坦克,增加其等级。

因此,self.level = 0 的主要作用是确保每次创建 MyTank 实例时,坦克的等级都从最基础的状态开始。

8、设置坦克的动画及矩形边界

        #self.tank 是一个实例属性,用于存储当前坦克的图像。这个属性会在游戏中用于渲染坦克的外观。
        '''
        self.tank = self.tank_L0_image:
                这部分代码将之前加载的0级坦克图像(存储在 self.tank_L0_image 中)赋值给 self.tank。
                也就是说,坦克的外观现在被设置为0级时的图像。
        '''
        self.tank = self.tank_L0_image

        # 运动中的两种不同图像,用于坦克的动画切换
        '''
        self.tank_R0 和 self.tank_R1:

        这两个属性分别用于存储坦克在两种不同状态下的子图像(即坦克的不同帧或动画状态)。
        self.tank.subsurface((0, 0), (48, 48)):
                    1、self.tank 是当前坦克的完整图像。
                    2、subsurface((0, 0), (48, 48)) 方法用于从 self.tank 图像中截取一个子图像。
                    3、(0, 0) 是子图像的起始位置(左上角的坐标)。(48, 48) 是子图像的宽度和高度。这里截取的是一个 48x48 像素的正方形区域。
                    
                    self.tank_R0 因此存储了从 self.tank 的左上角 (0, 0) 开始的 48x48 像素区域。
                    self.tank.subsurface((48, 0), (48, 48)):
        '''
        self.tank_R0 = self.tank.subsurface((0, 0), (48, 48))
        '''
        同样地,这一行代码从 self.tank 图像的 (48, 0) 位置开始截取一个 48x48 像素的子图像。
        self.tank_R1 因此存储了从 self.tank 的位置 (48, 0) 开始的 48x48 像素区域。       
        '''
        self.tank_R1 = self.tank.subsurface((48, 0), (48, 48))

        # 设置坦克的矩形边界
        '''
        self.tank_R0.get_rect():
        self.tank_R0 是之前提取的坦克的一个子图像(即坦克在某种状态下的图像)。
        get_rect() 是 Pygame 提供的方法,用于获取该图像的矩形区域(Rect 对象)。这个 Rect 对象包括图像的尺寸(宽度和高度)以及初始位置(默认位置是 (0, 0))。
        self.rect:
        self.rect 是 MyTank 类的一个实例属性,用于存储坦克的 Rect 对象。
        通过 self.rect,可以方便地访问和修改坦克的位置、尺寸,以及进行碰撞检测等操作。
        
        '''
        self.rect = self.tank_R0.get_rect()
        '''
        self.rect = self.tank_R0.get_rect() 通过为坦克的图像 self.tank_R0 创建一个矩形对象
        self.rect,为后续的碰撞检测、位置控制和渲染操作提供了基础。
        这个矩形对象是 Pygame 中管理和操作精灵位置及碰撞的重要工具。
        '''

9、根据玩家编号设置坦克的初始位置

        #self.tank 是一个实例属性,用于存储当前坦克的图像。这个属性会在游戏中用于渲染坦克的外观。
        '''
        self.tank = self.tank_L0_image:
                这部分代码将之前加载的0级坦克图像(存储在 self.tank_L0_image 中)赋值给 self.tank。
                也就是说,坦克的外观现在被设置为0级时的图像。
        '''
        self.tank = self.tank_L0_image

        # 运动中的两种不同图像,用于坦克的动画切换
        '''
        self.tank_R0 和 self.tank_R1:

        这两个属性分别用于存储坦克在两种不同状态下的子图像(即坦克的不同帧或动画状态)。
        self.tank.subsurface((0, 0), (48, 48)):
                    1、self.tank 是当前坦克的完整图像。
                    2、subsurface((0, 0), (48, 48)) 方法用于从 self.tank 图像中截取一个子图像。
                    3、(0, 0) 是子图像的起始位置(左上角的坐标)。(48, 48) 是子图像的宽度和高度。这里截取的是一个 48x48 像素的正方形区域。
                    
                    self.tank_R0 因此存储了从 self.tank 的左上角 (0, 0) 开始的 48x48 像素区域。
                    self.tank.subsurface((48, 0), (48, 48)):
        '''
        self.tank_R0 = self.tank.subsurface((0, 0), (48, 48))
        '''
        同样地,这一行代码从 self.tank 图像的 (48, 0) 位置开始截取一个 48x48 像素的子图像。
        self.tank_R1 因此存储了从 self.tank 的位置 (48, 0) 开始的 48x48 像素区域。       
        '''
        self.tank_R1 = self.tank.subsurface((48, 0), (48, 48))

        # 设置坦克的矩形边界
        '''
        self.tank_R0.get_rect():
        self.tank_R0 是之前提取的坦克的一个子图像(即坦克在某种状态下的图像)。
        get_rect() 是 Pygame 提供的方法,用于获取该图像的矩形区域(Rect 对象)。这个 Rect 对象包括图像的尺寸(宽度和高度)以及初始位置(默认位置是 (0, 0))。
        self.rect:
        self.rect 是 MyTank 类的一个实例属性,用于存储坦克的 Rect 对象。
        通过 self.rect,可以方便地访问和修改坦克的位置、尺寸,以及进行碰撞检测等操作。
        
        '''
        self.rect = self.tank_R0.get_rect()
        '''
        self.rect = self.tank_R0.get_rect() 通过为坦克的图像 self.tank_R0 创建一个矩形对象
        self.rect,为后续的碰撞检测、位置控制和渲染操作提供了基础。
        这个矩形对象是 Pygame 中管理和操作精灵位置及碰撞的重要工具。
        '''

10、设置子弹的初始化位置

   #这段代码是 MyTank 类中的 shoot 方法,用于坦克发射子弹。它主要根据坦克的方向设置子弹的初始位置,并将子弹的状态激活。
    def shoot(self):
        # 发射子弹
        #这行代码将子弹的 life 属性设置为 True,表示子弹处于激活状态,已经发射。
        self.bullet.life = True  # 激活子弹
        self.bullet.changeImage(self.dir_x, self.dir_y)  # 根据坦克方向改变子弹图像
        '''
        行代码根据坦克的当前方向 (dir_x 和 dir_y) 更新子弹的方向图像。 
        changeImage 方法用于调整子弹的图像,以使子弹朝向与坦克相同的方向发射。
        '''
        # 根据坦克当前方向设置子弹的初始位置
        if self.dir_x == 0 and self.dir_y == -1:  # 向上
            #如果坦克朝上 (dir_x = 0, dir_y = -1),
            self.bullet.rect.left = self.rect.left + 20
            '''
            .rect.left 表示矩形区域左边缘的 x 坐标,即矩形最左侧的水平位置。
            #则子弹的 left 坐标设置为坦克左侧加 20 像素,使子弹居中。
            '''
            self.bullet.rect.bottom = self.rect.top + 1
            '''
            .rect.bottom 表示矩形区域底边缘的 y 坐标,即矩形最下方的垂直位置。
            子弹的 bottom 坐标设置为坦克顶部的 top 坐标加 1 像素,确保子弹从坦克的顶部发射。
            '''
        elif self.dir_x == 0 and self.dir_y == 1:  # 向下
            #   如果坦克朝下 (dir_x = 0, dir_y = 1)
            self.bullet.rect.left = self.rect.left + 20
            #   则子弹的 left 坐标仍然设置为坦克左侧加 20 像素。
            self.bullet.rect.top = self.rect.bottom - 1
            #   子弹的 top 坐标设置为坦克底部的 bottom 坐标减 1 像素,使子弹从坦克底部发射。
        elif self.dir_x == -1 and self.dir_y == 0:  # 向左
            #   如果坦克朝左(dir_x=-1, dir_y=0)
            self.bullet.rect.right = self.rect.left - 1
            #   则子弹的 right 坐标设置为坦克左侧的 left 坐标减 1 像素,使子弹从坦克左侧发射。
            self.bullet.rect.top = self.rect.top + 20
            #   子弹的 top 坐标设置为坦克顶部加 20 像素,使子弹居中。
        elif self.dir_x == 1 and self.dir_y == 0:  # 向右
            #   如果坦克朝右 (dir_x = 1, dir_y = 0)
            self.bullet.rect.left = self.rect.right + 1
            #   则子弹的 left 坐标设置为坦克右侧的 right 坐标加 1 像素,使子弹从坦克右侧发射。
            self.bullet.rect.top = self.rect.top + 20
            #   子弹的 top 坐标设置为坦克顶部加 20 像素,使子弹居中。

11、设置坦克升级:使其更强;

        # 根据坦克等级设置子弹的速度和强度
        if self.level == 1:
            # 如果坦克等级为1
            self.bullet.speed = 16
            # 子弹的速度设置为16像素/帧。
            self.bullet.strong = False
            # 子弹的强度设置为 False,意味着这颗子弹可能无法穿透较坚硬的障碍物或敌方坦克。
        if self.level == 2:
            # 如果坦克等级为2
            self.bullet.speed = 16
            # 子弹的速度仍然为16像素/帧。
            self.bullet.strong = True
            # 子弹的强度设置为 True,意味着子弹可能更强大,可以穿透某些障碍物或击毁较强的敌方坦克。
        if self.level == 3:
            # 如果坦克等级为3
            self.bullet.speed = 48
            # 子弹的速度大幅提高至48像素/帧,表明坦克在最高等级时发射的子弹速度极快。
            self.bullet.strong = True
            # 子弹的强度保持为 True,意味着它不仅速度快,而且具有更强的破坏力。

12、设置坦克降级:

    def levelDown(self):
        # 坦克降级
        if self.level > 0:
            # 如果坦克的等级大于0
            self.level -= 1
            # 则将等级降低1。等级最小为0,在这个条件下,降级会将等级减少到下一个等级。
        if self.level == 0:
            # 如果当前等级是0
            self.tank = self.tank_L0_image
            # 设置坦克的图像为等级0的图像 self.tank_L0_image
            self.bullet.speed = 6
            # 设置子弹的速度为6像素/帧(较低的速度,反映了较低等级的子弹效果)。
            self.bullet.strong = False
            # 将子弹的强度设置为 False,表示子弹没有穿透能力或威力较小。
        if self.level == 1:
            # 如果当前等级是1
            self.tank = self.tank_L1_image
            # 设置坦克的图像为等级1的图像 self.tank_L1_image。
        if self.level == 2:
            #  如果当前等级是2
            self.tank = self.tank_L2_image
            # 置坦克的图像为等级2的图像 self.tank_L2_image

13、判断坦克向上移动的碰撞检测

    def moveUp(self, tankGroup, brickGroup, ironGroup):
        '''
        这是方法的定义。moveUp 是一个用于控制坦克向上移动的方法。方法接收三个参数:
        tankGroup(其他坦克的组)、brickGroup(砖块的组)、ironGroup(铁块的组),
        这些参数用于后续的碰撞检测。
        '''
        self.rect = self.rect.move(self.speed * 0, self.speed * -1)
        '''
        这行代码让坦克向上移动。self.speed * 0 表示水平速度为 0,
        self.speed * -1 表示垂直速度为负,即向上移动。
        self.rect是坦克在屏幕上的位置和大小的矩形区域,
        这里使用 move 方法将坦克向上移动 self.speed 个像素。
        '''
        self.tank_R0 = self.tank.subsurface((0, 0),(48, 48))
        '''
        这行代码更新坦克的图像为向上的图像(第一帧动画)。
        self.tank.subsurface((0, 0),(48, 48)) 表示从坦克的整体图像中截取一部分区域来显示。
        (0, 0) 是起点坐标,(48, 48) 是截取的区域大小。
        '''
        self.tank_R1 = self.tank.subsurface((48, 0),(48, 48))
        '''
        这行代码更新坦克的图像为向上的图像(第二帧动画)。
        类似于上一行代码,它从坦克的整体图像中截取另一部分区域,用于实现简单的动画效果。
        '''
        self.dir_x, self.dir_y = 0, -1
        '''
        这行代码设置坦克的方向为“向上”。dir_x = 0 表示水平不动,dir_y = -1 表示垂直向上。
        这两个变量用于后续操作(例如射击方向)的判断,表示当前坦克朝向的方向。
        '''

        if self.rect.top < 3:
            #这行代码检查坦克的顶部是否已经接近屏幕的顶部(小于3个像素)
            self.rect = self.rect.move(self.speed * 0, self.speed * 1)
            '''
            .move 方法在游戏开发中常用于更新对象的位置,尤其是在处理对象的移动和碰撞检测时。
            通过它,可以轻松地计算和调整对象的位置,并生成新的位置矩形,而不会影响原始位置数据。
            '''
            #  如果坦克已经到达上边界,这行代码将坦克的位置向下移动,避免超出边界。
            return True
            #  返回 True,表示发生了碰撞或越界。

        if pygame.sprite.spritecollide(self, brickGroup, False, None) \
            or pygame.sprite.spritecollide(self, ironGroup, False, None):
            # 这行代码检测坦克是否与 brickGroup(砖块群)中的任何一个对象发生了碰撞。
            # 这部分代码继续检测坦克是否与 ironGroup(钢铁块群)中的任何一个对象发生了碰撞。
            self.rect = self.rect.move(self.speed * 0, self.speed * 1)
            # 如果坦克已经到达上边界,这行代码将坦克的位置向下移动,避免超出边界。
            return True
            #   返回 True,表示发生了碰撞或越界。
        if pygame.sprite.spritecollide(self, tankGroup, False, None):
            # 这行代码检测坦克是否与 tankGroup(其他坦克)中的任何一个对象发生了碰撞。
            # 如果检测到与其他坦克发生碰撞,坦克会被向下移动,并返回 True。
            self.rect = self.rect.move(self.speed * 0, self.speed * 1)
            # 如果坦克与其他坦克发生碰撞,这行代码将坦克的位置向下移动,避免与其他坦克重叠。
            return True
            # 再次返回 True,表示发生了碰撞。
        return False
    # 如果没有发生碰撞(即没有与上边界、砖块、钢铁块或其他坦克碰撞),返回 False,表示坦克可以继续移动。

14、判断坦克向下移动的碰撞检测

    这段代码定义了一个名为 moveDown 的方法,用于处理坦克对象向下移动的逻辑,
    同时检查是否与其他对象发生碰撞
    '''
    def moveDown(self, tankGroup, brickGroup, ironGroup):
        self.rect = self.rect.move(self.speed * 0, self.speed * 1)
        '''
        这里 self.rect 是坦克对象的矩形边界框。
        self.speed * 0 表示水平方向不移动。
        self.speed * 1 表示垂直方向向下移动,self.speed 是坦克的速度。
        .move(0, self.speed) 方法根据速度将坦克的位置向下移动。    
         '''
        self.tank_R0 = self.tank.subsurface((0, 48),(48, 48))
        self.tank_R1 = self.tank.subsurface((48, 48),(48, 48))
        '''
        self.tank 是坦克的当前图像,subsurface 方法从图像中截取指定区域
        ((0, 48) 到 (48, 96) 和 (48, 48) 到 (96, 96) 的两个子图像)。
        self.tank_R0 和 self.tank_R1 分别表示坦克在当前帧中的两个不同姿态,用于动画效果。
        '''
        self.dir_x, self.dir_y = 0, 1
        # self.dir_x 和 self.dir_y 表示坦克的移动方向。0, 1 表示坦克朝向下方。
        if self.rect.bottom > 630 - 3:
            # 如果坦克的底部超出了屏幕的边界(假设屏幕高度为 630 像素,3 像素是边界缓冲区)
            self.rect = self.rect.move(self.speed * 0, self.speed * -1)
            # 将其移动回去(self.speed * -1)
            return True
            # 并返回 True,表示发生了碰撞。

        if pygame.sprite.spritecollide(self, brickGroup, False, None) \
            or pygame.sprite.spritecollide(self, ironGroup, False, None):
            # pygame.sprite.spritecollide
            # 方法用于检测坦克与 brickGroup(砖块组)或 ironGroup(铁块组)之间的碰撞。
            self.rect = self.rect.move(self.speed * 0, self.speed * -1)
            # 将其移动回去(self.speed * -1)
            return True
            # 并返回 True,表示发生了碰撞。
        if pygame.sprite.spritecollide(self, tankGroup, False, None):
            #  检查坦克是否与其他坦克(tankGroup)发生碰撞。如果是
            self.rect = self.rect.move(self.speed * 0, self.speed * -1)
            # 将其移动回去(self.speed * -1)
            return True
            # 将坦克移动回去并返回 True。
        return False
        #  如果没有发生任何碰撞,则返回 False。

15、判断坦克向左移动的碰撞检测

    '''
        这段代码定义了一个名为 moveLeft 的方法,用于处理坦克对象向左移动的逻辑,
        同时检查是否与其他对象发生碰撞
        '''
    def moveLeft(self, tankGroup, brickGroup, ironGroup):
        self.rect = self.rect.move(self.speed * -1, self.speed * 0)
        '''
        这里 self.rect 是坦克对象的矩形边界框。
        self.speed * 0 表示水平方向不移动。
        self.speed * 1 表示垂直方向向下移动,self.speed 是坦克的速度。
        .move(0, self.speed) 方法根据速度将坦克的位置向下移动。    
        '''
        self.tank_R0 = self.tank.subsurface((0, 96),(48, 48))
        self.tank_R1 = self.tank.subsurface((48, 96),(48, 48))
        '''
        self.tank 是坦克的当前图像,subsurface 方法从图像中截取指定区域
        ((0, 96) 到 (48, 48) 和 (48, 96) 到 (48, 48) 的两个子图像)。
        self.tank_R0 和 self.tank_R1 分别表示坦克在当前帧中的两个不同姿态,用于动画效果。
        '''
        self.dir_x, self.dir_y = -1, 0
        # self.dir_x 和 self.dir_y 表示坦克的移动方向。-1, 0 表示坦克朝向左方。
        if self.rect.left < 3:
            # 这行代码检查坦克的  左边  是否已经接近屏幕的  左部(小于3个像素)
            self.rect = self.rect.move(self.speed * 1, self.speed * 0)
            # 将其移动回去(self.speed * 1)
            return True
        # # 将坦克移动回去并返回 True。
        if pygame.sprite.spritecollide(self, brickGroup, False, None) \
            or pygame.sprite.spritecollide(self, ironGroup, False, None):
            # 这行代码检测坦克是否与 brickGroup(砖块群),ironGroup(钢铁块群)中的任何一个对象发生了碰撞。
            self.rect = self.rect.move(self.speed * 1, self.speed * 0)
            # 将其移动回去(self.speed * -1)
            return True
            # 返回 True,表示发生了碰撞。
        if pygame.sprite.spritecollide(self, tankGroup, False, None):
            #  检查坦克是否与其他坦克(tankGroup)发生碰撞
            self.rect = self.rect.move(self.speed * 1, self.speed * 0)
            # 将其移动回去(self.speed * -1)
            return True
            # 返回 True,表示发生了碰撞。
        return False
        #  如果没有发生任何碰撞,则返回 False。

16、判断坦克向右移动的碰撞检测

    '''
            这段代码定义了一个名为 moveRight 的方法,用于处理坦克对象向右移动的逻辑,
            同时检查是否与其他对象发生碰撞
            '''

    def moveRight(self, tankGroup, brickGroup, ironGroup):
        self.rect = self.rect.move(self.speed * 1, self.speed * 0)
        '''
        这里 self.rect 是坦克对象的矩形边界框。
        self.speed * 0 表示水平方向不移动。
        self.speed * 1 表示垂直方向向下移动,self.speed 是坦克的速度。
        .move(0, self.speed) 方法根据速度将坦克的位置向下移动。    
        '''
        self.tank_R0 = self.tank.subsurface((0, 144),(48, 48))
        self.tank_R1 = self.tank.subsurface((48, 144),(48, 48))
        '''
        self.tank 是坦克的当前图像,subsurface 方法从图像中截取指定区域
        ((0, 144) 到 (48, 48) 和 (48,144) 到 (48, 48) 的两个子图像)。
        self.tank_R0 和 self.tank_R1 分别表示坦克在当前帧中的两个不同姿态,用于动画效果。
        '''
        self.dir_x, self.dir_y = 1, 0
        # self.dir_x 和 self.dir_y 表示坦克的移动方向。1, 0 表示坦克朝向右方。
        if self.rect.right > 630 - 3:
            # 如果坦克的底部超出了屏幕的边界(假设屏幕高度为 630 像素,3 像素是边界缓冲区)
            self.rect = self.rect.move(self.speed * -1, self.speed * 0)
            # 将其移动回去(self.speed * -1)
            return True
            # 返回结果为True 表示发生了碰撞
        if pygame.sprite.spritecollide(self, brickGroup, False, None) \
            or pygame.sprite.spritecollide(self, ironGroup, False, None):
            # 这行代码检测坦克是否与 brickGroup(砖块群),ironGroup(钢铁块群)中的任何一个对象发生了碰撞。
            self.rect = self.rect.move(self.speed * -1, self.speed * 0)
            # 将其移动回去(self.speed * -1)
            return True
            # 返回结果为True,表示发生了碰撞
        if pygame.sprite.spritecollide(self, tankGroup, False, None):
            #  检查坦克是否与其他坦克(tankGroup)发生碰撞
            self.rect = self.rect.move(self.speed * -1, self.speed * 0)
            ## 将其移动回去(self.speed * -1)
            return True
            # 返回结果为True,表示发生了碰撞
        return False
    #  如果没有发生任何碰撞,则返回 False。

完整代码:

import pygame  # 导入pygame模块
import bulletClass # 导入自定义模块

# 玩家1和玩家2的不同坦克等级的图像文件路径
tank_T1_0 = r"..\image\tank_T1_0.png"
tank_T1_1 = r"..\image\tank_T1_1.png"
tank_T1_2 = r"..\image\tank_T1_2.png"
tank_T2_0 = r"..\image\tank_T2_0.png"
tank_T2_1 = r"..\image\tank_T2_1.png"
tank_T2_2 = r"..\image\tank_T2_2.png"


class MyTank(pygame.sprite.Sprite):
    def __init__(self, playerNumber):
        # 初始化精灵
        pygame.sprite.Sprite.__init__(self)

        # 玩家生命状态
        self.life = True

        # 根据玩家编号加载不同等级的坦克图像
        if playerNumber == 1:
            self.tank_L0_image = pygame.image.load(tank_T1_0).convert_alpha()  # 0级坦克
            #pygame.image.load(tank_T1_1):使用 Pygame 的 image.load() 方法加载指定路径(tank_T1_1)中的图像文件。
            # 这个路径对应的是玩家1在1级时的坦克图像文件。
            #.convert_alpha():将加载的图像转换为包含 alpha 通道的图像格式(RGBA)
            # ,这允许图像支持透明背景,从而使渲染更高效且图像显示效果更好。
            self.tank_L1_image = pygame.image.load(tank_T1_1).convert_alpha()  # 1级坦克
            self.tank_L2_image = pygame.image.load(tank_T1_2).convert_alpha()  # 2级坦克
        if playerNumber == 2:
            self.tank_L0_image = pygame.image.load(tank_T2_0).convert_alpha()  # 0级坦克
            self.tank_L1_image = pygame.image.load(tank_T2_1).convert_alpha()  # 1级坦克
            self.tank_L2_image = pygame.image.load(tank_T2_2).convert_alpha()  # 2级坦克

        # 坦克等级初始化为0级
        #因此,self.level = 0 的主要作用是确保每次创建 MyTank 实例时,坦克的等级都从最基础的状态开始。
        self.level = 0

        # 初始状态为0级坦克
        #self.tank 是一个实例属性,用于存储当前坦克的图像。这个属性会在游戏中用于渲染坦克的外观。
        '''
        self.tank = self.tank_L0_image:
                这部分代码将之前加载的0级坦克图像(存储在 self.tank_L0_image 中)赋值给 self.tank。
                也就是说,坦克的外观现在被设置为0级时的图像。
        '''
        self.tank = self.tank_L0_image

        # 运动中的两种不同图像,用于坦克的动画切换
        '''
        self.tank_R0 和 self.tank_R1:

        这两个属性分别用于存储坦克在两种不同状态下的子图像(即坦克的不同帧或动画状态)。
        self.tank.subsurface((0, 0), (48, 48)):
                    1、self.tank 是当前坦克的完整图像。
                    2、subsurface((0, 0), (48, 48)) 方法用于从 self.tank 图像中截取一个子图像。
                    3、(0, 0) 是子图像的起始位置(左上角的坐标)。(48, 48) 是子图像的宽度和高度。这里截取的是一个 48x48 像素的正方形区域。
                    
                    self.tank_R0 因此存储了从 self.tank 的左上角 (0, 0) 开始的 48x48 像素区域。
                    self.tank.subsurface((48, 0), (48, 48)):
        '''
        self.tank_R0 = self.tank.subsurface((0, 0), (48, 48))
        '''
        同样地,这一行代码从 self.tank 图像的 (48, 0) 位置开始截取一个 48x48 像素的子图像。
        self.tank_R1 因此存储了从 self.tank 的位置 (48, 0) 开始的 48x48 像素区域。       
        '''
        self.tank_R1 = self.tank.subsurface((48, 0), (48, 48))

        # 设置坦克的矩形边界
        '''
        self.tank_R0.get_rect():
        self.tank_R0 是之前提取的坦克的一个子图像(即坦克在某种状态下的图像)。
        get_rect() 是 Pygame 提供的方法,用于获取该图像的矩形区域(Rect 对象)。这个 Rect 对象包括图像的尺寸(宽度和高度)以及初始位置(默认位置是 (0, 0))。
        self.rect:
        self.rect 是 MyTank 类的一个实例属性,用于存储坦克的 Rect 对象。
        通过 self.rect,可以方便地访问和修改坦克的位置、尺寸,以及进行碰撞检测等操作。
        
        '''
        self.rect = self.tank_R0.get_rect()
        '''
        self.rect = self.tank_R0.get_rect() 通过为坦克的图像 self.tank_R0 创建一个矩形对象
        self.rect,为后续的碰撞检测、位置控制和渲染操作提供了基础。
        这个矩形对象是 Pygame 中管理和操作精灵位置及碰撞的重要工具。
        '''


        # 根据玩家编号设置坦克的初始位置
        '''
        if playerNumber == 1: 和 if playerNumber == 2::
        这两条判断语句用于区分不同玩家。在这段代码中,
        playerNumber 参数决定了这是第1位玩家还是第2位玩家。
        '''

        if playerNumber == 1:
            self.rect.left, self.rect.top = 3 + 24 * 8, 3 + 24 * 24
            '''
            这行代码在 playerNumber == 1 的情况下执行,设定第1位玩家的坦克位置。
            self.rect.left 和 self.rect.top 分别是坦克矩形区域的左边缘和上边缘的坐标。
            3 + 24 * 8 和 3 + 24 * 24 是计算出的初始坐标,基于网格或像素单位系统计算,确保坦克出现在特定的起始位置。
            '''
        if playerNumber == 2:
            self.rect.left, self.rect.top = 3 + 24 * 16, 3 + 24 * 24
            '''
            这行代码在 playerNumber == 2 的情况下执行,设定第2位玩家的坦克位置。
            与第1位玩家类似,这里的计算方式相同,只是 left 坐标增加了 24 * 8 的距离,将坦克放置在另一个初始位置。
            '''

        # 坦克速度、方向、生命值及子弹冷却状态
        self.speed = 3  #这行代码设置坦克的初始速度为 3。这个值决定了坦克在游戏中每次移动时的位置变化量,即坦克移动的快慢。
        self.dir_x, self.dir_y = 0, -1  # 坦克初始朝向(向上)
        '''
        这行代码设置坦克的初始方向为向上。
        #dir_x 和 dir_y 分别表示坦克在水平方向和垂直方向上的移动方向。0, -1 
        表示坦克在水平方向上没有移动(dir_x = 0),而在垂直方向上向上移动(dir_y = -1)。
        '''
        self.life = 3  # 生命值为3
        '''
        这行代码为坦克设置初始生命值为 3。
        生命值表示坦克能够承受的最大伤害次数,当生命值减至 0 时,坦克将被摧毁。
        '''
        self.bulletNotCooling = True  # 子弹是否在冷却中
        '''
        这行代码设置子弹的初始冷却状态为 True,即子弹不在冷却中,坦克可以立即发射子弹。
        冷却状态通常用于控制子弹的发射频率,防止坦克连续发射子弹而破坏游戏平衡。
        '''
        self.bullet = bulletClass.Bullet()  # 创建一个子弹实例
        '''
        这行代码创建了一个 Bullet 类的实例,并将其赋值给 self.bullet。
        这个实例用于管理坦克发射的子弹,包括子弹的属性(如速度、方向、强度)和行为(如移动、碰撞检测)。
        '''
    #这段代码是 MyTank 类中的 shoot 方法,用于坦克发射子弹。它主要根据坦克的方向设置子弹的初始位置,并将子弹的状态激活。
    def shoot(self):
        # 发射子弹
        #这行代码将子弹的 life 属性设置为 True,表示子弹处于激活状态,已经发射。
        self.bullet.life = True  # 激活子弹
        self.bullet.changeImage(self.dir_x, self.dir_y)  # 根据坦克方向改变子弹图像
        '''
        行代码根据坦克的当前方向 (dir_x 和 dir_y) 更新子弹的方向图像。 
        changeImage 方法用于调整子弹的图像,以使子弹朝向与坦克相同的方向发射。
        '''
        # 根据坦克当前方向设置子弹的初始位置
        if self.dir_x == 0 and self.dir_y == -1:  # 向上
            #如果坦克朝上 (dir_x = 0, dir_y = -1),
            self.bullet.rect.left = self.rect.left + 20
            '''
            .rect.left 表示矩形区域左边缘的 x 坐标,即矩形最左侧的水平位置。
            #则子弹的 left 坐标设置为坦克左侧加 20 像素,使子弹居中。
            '''
            self.bullet.rect.bottom = self.rect.top + 1
            '''
            .rect.bottom 表示矩形区域底边缘的 y 坐标,即矩形最下方的垂直位置。
            子弹的 bottom 坐标设置为坦克顶部的 top 坐标加 1 像素,确保子弹从坦克的顶部发射。
            '''
        elif self.dir_x == 0 and self.dir_y == 1:  # 向下
            #   如果坦克朝下 (dir_x = 0, dir_y = 1)
            self.bullet.rect.left = self.rect.left + 20
            #   则子弹的 left 坐标仍然设置为坦克左侧加 20 像素。
            self.bullet.rect.top = self.rect.bottom - 1
            #   子弹的 top 坐标设置为坦克底部的 bottom 坐标减 1 像素,使子弹从坦克底部发射。
        elif self.dir_x == -1 and self.dir_y == 0:  # 向左
            #   如果坦克朝左(dir_x=-1, dir_y=0)
            self.bullet.rect.right = self.rect.left - 1
            #   则子弹的 right 坐标设置为坦克左侧的 left 坐标减 1 像素,使子弹从坦克左侧发射。
            self.bullet.rect.top = self.rect.top + 20
            #   子弹的 top 坐标设置为坦克顶部加 20 像素,使子弹居中。
        elif self.dir_x == 1 and self.dir_y == 0:  # 向右
            #   如果坦克朝右 (dir_x = 1, dir_y = 0)
            self.bullet.rect.left = self.rect.right + 1
            #   则子弹的 left 坐标设置为坦克右侧的 right 坐标加 1 像素,使子弹从坦克右侧发射。
            self.bullet.rect.top = self.rect.top + 20
            #   子弹的 top 坐标设置为坦克顶部加 20 像素,使子弹居中。


        # 根据坦克等级设置子弹的速度和强度
        if self.level == 1:
            # 如果坦克等级为1
            self.bullet.speed = 16
            # 子弹的速度设置为16像素/帧。
            self.bullet.strong = False
            # 子弹的强度设置为 False,意味着这颗子弹可能无法穿透较坚硬的障碍物或敌方坦克。
        if self.level == 2:
            # 如果坦克等级为2
            self.bullet.speed = 16
            # 子弹的速度仍然为16像素/帧。
            self.bullet.strong = True
            # 子弹的强度设置为 True,意味着子弹可能更强大,可以穿透某些障碍物或击毁较强的敌方坦克。
        if self.level == 3:
            # 如果坦克等级为3
            self.bullet.speed = 48
            # 子弹的速度大幅提高至48像素/帧,表明坦克在最高等级时发射的子弹速度极快。
            self.bullet.strong = True
            # 子弹的强度保持为 True,意味着它不仅速度快,而且具有更强的破坏力。

    # 增加坦克的等级,使其变得更强。
    def levelUp(self):
        # 坦克升级
        if self.level < 2:
            # 如果坦克的等级低于2
            self.level += 1
            #  则将等级提高1
        if self.level == 0:
            # 如果当前等级是0
            self.tank = self.tank_L0_image
            # 设置坦克的图像为等级0的图像 self.tank_L0_image。
        if self.level == 1:
            # 如果当前等级是1
            self.tank = self.tank_L1_image
            # 设置坦克的图像为等级1的图像 self.tank_L1_image。
        if self.level == 2:
            # 如果当前等级是2
            self.tank = self.tank_L2_image
            # 设置坦克的图像为等级2的图像 self.tank_L2_image
        if self.level == 3:
            # 如果等级等于3
            self.tank = self.tank_L2_image
            # 将坦克图像设置为等级2的图像 self.tank_L2_image。

    def levelDown(self):
        # 坦克降级
        if self.level > 0:
            # 如果坦克的等级大于0
            self.level -= 1
            # 则将等级降低1。等级最小为0,在这个条件下,降级会将等级减少到下一个等级。
        if self.level == 0:
            # 如果当前等级是0
            self.tank = self.tank_L0_image
            # 设置坦克的图像为等级0的图像 self.tank_L0_image
            self.bullet.speed = 6
            # 设置子弹的速度为6像素/帧(较低的速度,反映了较低等级的子弹效果)。
            self.bullet.strong = False
            # 将子弹的强度设置为 False,表示子弹没有穿透能力或威力较小。
        if self.level == 1:
            # 如果当前等级是1
            self.tank = self.tank_L1_image
            # 设置坦克的图像为等级1的图像 self.tank_L1_image。
        if self.level == 2:
            #  如果当前等级是2
            self.tank = self.tank_L2_image
            # 置坦克的图像为等级2的图像 self.tank_L2_image

    def moveUp(self, tankGroup, brickGroup, ironGroup):
        '''
        这是方法的定义。moveUp 是一个用于控制坦克向上移动的方法。方法接收三个参数:
        tankGroup(其他坦克的组)、brickGroup(砖块的组)、ironGroup(铁块的组),
        这些参数用于后续的碰撞检测。
        '''
        self.rect = self.rect.move(self.speed * 0, self.speed * -1)
        '''
        这行代码让坦克向上移动。self.speed * 0 表示水平速度为 0,
        self.speed * -1 表示垂直速度为负,即向上移动。
        self.rect是坦克在屏幕上的位置和大小的矩形区域,
        这里使用 move 方法将坦克向上移动 self.speed 个像素。
        '''
        self.tank_R0 = self.tank.subsurface((0, 0),(48, 48))
        '''
        这行代码更新坦克的图像为向上的图像(第一帧动画)。
        self.tank.subsurface((0, 0),(48, 48)) 表示从坦克的整体图像中截取一部分区域来显示。
        (0, 0) 是起点坐标,(48, 48) 是截取的区域大小。
        '''
        self.tank_R1 = self.tank.subsurface((48, 0),(48, 48))
        '''
        这行代码更新坦克的图像为向上的图像(第二帧动画)。
        类似于上一行代码,它从坦克的整体图像中截取另一部分区域,用于实现简单的动画效果。
        '''
        self.dir_x, self.dir_y = 0, -1
        '''
        这行代码设置坦克的方向为“向上”。dir_x = 0 表示水平不动,dir_y = -1 表示垂直向上。
        这两个变量用于后续操作(例如射击方向)的判断,表示当前坦克朝向的方向。
        '''

        if self.rect.top < 3:
            #这行代码检查坦克的顶部是否已经接近屏幕的顶部(小于3个像素)
            self.rect = self.rect.move(self.speed * 0, self.speed * 1)
            '''
            .move 方法在游戏开发中常用于更新对象的位置,尤其是在处理对象的移动和碰撞检测时。
            通过它,可以轻松地计算和调整对象的位置,并生成新的位置矩形,而不会影响原始位置数据。
            '''
            #  如果坦克已经到达上边界,这行代码将坦克的位置向下移动,避免超出边界。
            return True
            #  返回 True,表示发生了碰撞或越界。

        if pygame.sprite.spritecollide(self, brickGroup, False, None) \
            or pygame.sprite.spritecollide(self, ironGroup, False, None):
            # 这行代码检测坦克是否与 brickGroup(砖块群)中的任何一个对象发生了碰撞。
            # 这部分代码继续检测坦克是否与 ironGroup(钢铁块群)中的任何一个对象发生了碰撞。
            self.rect = self.rect.move(self.speed * 0, self.speed * 1)
            # 如果坦克已经到达上边界,这行代码将坦克的位置向下移动,避免超出边界。
            return True
            #   返回 True,表示发生了碰撞或越界。
        if pygame.sprite.spritecollide(self, tankGroup, False, None):
            # 这行代码检测坦克是否与 tankGroup(其他坦克)中的任何一个对象发生了碰撞。
            # 如果检测到与其他坦克发生碰撞,坦克会被向下移动,并返回 True。
            self.rect = self.rect.move(self.speed * 0, self.speed * 1)
            # 如果坦克与其他坦克发生碰撞,这行代码将坦克的位置向下移动,避免与其他坦克重叠。
            return True
            # 再次返回 True,表示发生了碰撞。
        return False
    # 如果没有发生碰撞(即没有与上边界、砖块、钢铁块或其他坦克碰撞),返回 False,表示坦克可以继续移动。
    '''
    这段代码定义了一个名为 moveDown 的方法,用于处理坦克对象向下移动的逻辑,
    同时检查是否与其他对象发生碰撞
    '''
    def moveDown(self, tankGroup, brickGroup, ironGroup):
        self.rect = self.rect.move(self.speed * 0, self.speed * 1)
        '''
        这里 self.rect 是坦克对象的矩形边界框。
        self.speed * 0 表示水平方向不移动。
        self.speed * 1 表示垂直方向向下移动,self.speed 是坦克的速度。
        .move(0, self.speed) 方法根据速度将坦克的位置向下移动。    
         '''
        self.tank_R0 = self.tank.subsurface((0, 48),(48, 48))
        self.tank_R1 = self.tank.subsurface((48, 48),(48, 48))
        '''
        self.tank 是坦克的当前图像,subsurface 方法从图像中截取指定区域
        ((0, 48) 到 (48, 96) 和 (48, 48) 到 (96, 96) 的两个子图像)。
        self.tank_R0 和 self.tank_R1 分别表示坦克在当前帧中的两个不同姿态,用于动画效果。
        '''
        self.dir_x, self.dir_y = 0, 1
        # self.dir_x 和 self.dir_y 表示坦克的移动方向。0, 1 表示坦克朝向下方。
        if self.rect.bottom > 630 - 3:
            # 如果坦克的底部超出了屏幕的边界(假设屏幕高度为 630 像素,3 像素是边界缓冲区)
            self.rect = self.rect.move(self.speed * 0, self.speed * -1)
            # 将其移动回去(self.speed * -1)
            return True
            # 并返回 True,表示发生了碰撞。

        if pygame.sprite.spritecollide(self, brickGroup, False, None) \
            or pygame.sprite.spritecollide(self, ironGroup, False, None):
            # pygame.sprite.spritecollide
            # 方法用于检测坦克与 brickGroup(砖块组)或 ironGroup(铁块组)之间的碰撞。
            self.rect = self.rect.move(self.speed * 0, self.speed * -1)
            # 将其移动回去(self.speed * -1)
            return True
            # 并返回 True,表示发生了碰撞。
        if pygame.sprite.spritecollide(self, tankGroup, False, None):
            #  检查坦克是否与其他坦克(tankGroup)发生碰撞。如果是
            self.rect = self.rect.move(self.speed * 0, self.speed * -1)
            # 将其移动回去(self.speed * -1)
            return True
            # 将坦克移动回去并返回 True。
        return False
        #  如果没有发生任何碰撞,则返回 False。

    '''
        这段代码定义了一个名为 moveLeft 的方法,用于处理坦克对象向左移动的逻辑,
        同时检查是否与其他对象发生碰撞
        '''
    def moveLeft(self, tankGroup, brickGroup, ironGroup):
        self.rect = self.rect.move(self.speed * -1, self.speed * 0)
        '''
        这里 self.rect 是坦克对象的矩形边界框。
        self.speed * 0 表示水平方向不移动。
        self.speed * 1 表示垂直方向向下移动,self.speed 是坦克的速度。
        .move(0, self.speed) 方法根据速度将坦克的位置向下移动。    
        '''
        self.tank_R0 = self.tank.subsurface((0, 96),(48, 48))
        self.tank_R1 = self.tank.subsurface((48, 96),(48, 48))
        '''
        self.tank 是坦克的当前图像,subsurface 方法从图像中截取指定区域
        ((0, 96) 到 (48, 48) 和 (48, 96) 到 (48, 48) 的两个子图像)。
        self.tank_R0 和 self.tank_R1 分别表示坦克在当前帧中的两个不同姿态,用于动画效果。
        '''
        self.dir_x, self.dir_y = -1, 0
        # self.dir_x 和 self.dir_y 表示坦克的移动方向。-1, 0 表示坦克朝向左方。
        if self.rect.left < 3:
            # 这行代码检查坦克的  左边  是否已经接近屏幕的  左部(小于3个像素)
            self.rect = self.rect.move(self.speed * 1, self.speed * 0)
            # 将其移动回去(self.speed * 1)
            return True
        # # 将坦克移动回去并返回 True。
        if pygame.sprite.spritecollide(self, brickGroup, False, None) \
            or pygame.sprite.spritecollide(self, ironGroup, False, None):
            # 这行代码检测坦克是否与 brickGroup(砖块群),ironGroup(钢铁块群)中的任何一个对象发生了碰撞。
            self.rect = self.rect.move(self.speed * 1, self.speed * 0)
            # 将其移动回去(self.speed * -1)
            return True
            # 返回 True,表示发生了碰撞。
        if pygame.sprite.spritecollide(self, tankGroup, False, None):
            #  检查坦克是否与其他坦克(tankGroup)发生碰撞
            self.rect = self.rect.move(self.speed * 1, self.speed * 0)
            # 将其移动回去(self.speed * -1)
            return True
            # 返回 True,表示发生了碰撞。
        return False
        #  如果没有发生任何碰撞,则返回 False。

    '''
            这段代码定义了一个名为 moveRight 的方法,用于处理坦克对象向右移动的逻辑,
            同时检查是否与其他对象发生碰撞
            '''

    def moveRight(self, tankGroup, brickGroup, ironGroup):
        self.rect = self.rect.move(self.speed * 1, self.speed * 0)
        '''
        这里 self.rect 是坦克对象的矩形边界框。
        self.speed * 0 表示水平方向不移动。
        self.speed * 1 表示垂直方向向下移动,self.speed 是坦克的速度。
        .move(0, self.speed) 方法根据速度将坦克的位置向下移动。    
        '''
        self.tank_R0 = self.tank.subsurface((0, 144),(48, 48))
        self.tank_R1 = self.tank.subsurface((48, 144),(48, 48))
        '''
        self.tank 是坦克的当前图像,subsurface 方法从图像中截取指定区域
        ((0, 144) 到 (48, 48) 和 (48,144) 到 (48, 48) 的两个子图像)。
        self.tank_R0 和 self.tank_R1 分别表示坦克在当前帧中的两个不同姿态,用于动画效果。
        '''
        self.dir_x, self.dir_y = 1, 0
        # self.dir_x 和 self.dir_y 表示坦克的移动方向。1, 0 表示坦克朝向右方。
        if self.rect.right > 630 - 3:
            # 如果坦克的底部超出了屏幕的边界(假设屏幕高度为 630 像素,3 像素是边界缓冲区)
            self.rect = self.rect.move(self.speed * -1, self.speed * 0)
            # 将其移动回去(self.speed * -1)
            return True
            # 返回结果为True 表示发生了碰撞
        if pygame.sprite.spritecollide(self, brickGroup, False, None) \
            or pygame.sprite.spritecollide(self, ironGroup, False, None):
            # 这行代码检测坦克是否与 brickGroup(砖块群),ironGroup(钢铁块群)中的任何一个对象发生了碰撞。
            self.rect = self.rect.move(self.speed * -1, self.speed * 0)
            # 将其移动回去(self.speed * -1)
            return True
            # 返回结果为True,表示发生了碰撞
        if pygame.sprite.spritecollide(self, tankGroup, False, None):
            #  检查坦克是否与其他坦克(tankGroup)发生碰撞
            self.rect = self.rect.move(self.speed * -1, self.speed * 0)
            ## 将其移动回去(self.speed * -1)
            return True
            # 返回结果为True,表示发生了碰撞
        return False
    #  如果没有发生任何碰撞,则返回 False。

如果注释看着乱自行删除


  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值