忆童年!用Python实现愤怒的小鸟游戏


Posted in Python onJune 07, 2021

开发工具

Python版本:3.6.4
相关模块:
pygame模块;
以及一些python自带的模块。

环境搭建

安装Python并添加到环境变量,pip安装需要的相关模块即可。

原理介绍

这里简单介绍一下游戏的实现原理呗。首先是游戏的开始界面,大概是长这样的,比较简约:

忆童年!用Python实现愤怒的小鸟游戏

主要包括两个部分,即游戏的标题和游戏的开始以及退出按钮,这两部分的代码实现如下:

'''按钮类'''
class Button(pygame.sprite.Sprite):
    def __init__(self, screen, x, y, width, height, action=None, color_not_active=(189, 195, 199), color_active=(189, 195, 199)):
        pygame.sprite.Sprite.__init__(self)
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.action = action
        self.screen = screen
        self.color_active = color_active
        self.color_not_active = color_not_active
    '''添加文字'''
    def addtext(self, text, size=20, font='Times New Roman', color=(0, 0, 0)):
        self.font = pygame.font.Font(font, size)
        self.text = self.font.render(text, True, color)
        self.text_pos = self.text.get_rect()
        self.text_pos.center = (self.x + self.width / 2, self.y + self.height / 2)
    '''是否被鼠标选中'''
    def selected(self):
        pos = pygame.mouse.get_pos()
        if (self.x < pos[0] < self.x + self.width) and (self.y < pos[1] < self.y + self.height):
            return True
        return False
    '''画到屏幕上'''
    def draw(self):
        if self.selected():
            pygame.draw.rect(self.screen, self.color_active, (self.x, self.y, self.width, self.height))
        else:
            pygame.draw.rect(self.screen, self.color_not_active, (self.x, self.y, self.width, self.height))
        if hasattr(self, 'text'):
            self.screen.blit(self.text, self.text_pos)


'''文字标签类'''
class Label(pygame.sprite.Sprite):
    def __init__(self, screen, x, y, width, height):
        pygame.sprite.Sprite.__init__(self)
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.screen = screen
    '''添加文字'''
    def addtext(self, text, size=20, font='Times New Roman', color=(0, 0, 0)):
        self.font = pygame.font.Font(font, size)
        self.text = self.font.render(text, True, color)
        self.text_pos = self.text.get_rect()
        self.text_pos.center = (self.x + self.width / 2, self.y + self.height / 2)
    '''画到屏幕上'''
    def draw(self):
        if hasattr(self, 'text'):
            self.screen.blit(self.text, self.text_pos)

实现起来其实都比较简单,按钮类就是多了一个被鼠标选中之后(也就是鼠标的位置落在按钮的区域范围内时)改变颜色以直观地告诉玩家该按钮已经被选中了的功能。

如果玩家点击退出键(QUIT),则退出游戏:

def quitgame():
    pygame.quit()
    sys.exit()

若点击开始游戏按钮,则开始游戏:

def startgame():
    game_levels = GameLevels(cfg, screen)
    game_levels.start()

游戏界面大概长这样:

忆童年!用Python实现愤怒的小鸟游戏

玩家获胜的方法就是操作有限数量的小鸟将所有入侵的猪干掉,换句话说就是利用弹弓发射小鸟,让小鸟击中场上的所有猪。若小鸟全部发射完之后场上仍然有猪没有被击中,则玩家失败。判断游戏胜负关系的代码实现起来其实蛮简单的,大概是这样的:

'''游戏状态'''
def status(self, pigs, birds):
    status_codes = {
        'gaming': 0,
        'failure': 1,
        'victory': 2,
    }
    if len(pigs) == 0: return status_codes['victory']
    elif len(birds) == 0: return status_codes['failure']
    else: return status_codes['gaming']

接着,为了实现游戏,我们先定义一下所有我们需要的游戏精灵类。首先,是我们的主角,愤怒的小鸟:

'''小鸟'''
class Bird(pygame.sprite.Sprite):
    def __init__(self, screen, imagepaths, loc_info, velocity=None, color=(255, 255, 255), **kwargs):
        pygame.sprite.Sprite.__init__(self)
        assert len(loc_info) == 3
        assert len(imagepaths) == 1
        # 设置必要的属性常量
        self.color = color
        self.screen = screen
        self.loc_info = list(loc_info)
        self.imagepaths = imagepaths
        self.velocity = VelocityVector() if velocity is None else velocity
        self.type = 'bird'
        self.fly_path = []
        self.is_dead = False
        self.elasticity = 0.8
        self.is_loaded = False
        self.is_selected = False
        self.inverse_friction = 0.99
        self.gravity = VelocityVector(0.2, math.pi)
        # 屏幕大小
        self.screen_size = screen.get_rect().size
        self.screen_size = (self.screen_size[0], self.screen_size[1] - 50)
        # 导入图像
        self.image = pygame.image.load(imagepaths[0])
    '''画到屏幕上'''
    def draw(self):
        if not self.is_loaded:
            for point in self.fly_path:
                pygame.draw.ellipse(self.screen, self.color, (point[0], point[1], 3, 3), 1)
        position = self.loc_info[0] - self.loc_info[2], self.loc_info[1] - self.loc_info[2]
        self.screen.blit(self.image, position)
    '''判断有没有被鼠标选中'''
    def selected(self):
        pos = pygame.mouse.get_pos()
        dx, dy = pos[0] - self.loc_info[0], pos[1] - self.loc_info[1]
        dist = math.hypot(dy, dx)
        if dist < self.loc_info[2]:
            return True
        return False
    '''加载到弹弓上'''
    def load(self, slingshot):
        self.loc_info[0], self.loc_info[1] = slingshot.x, slingshot.y
        self.is_loaded = True
    '''重新设置位置'''
    def reposition(self, slingshot):
        pos = pygame.mouse.get_pos()
        if self.selected:
            self.loc_info[0], self.loc_info[1] = pos[0], pos[1]
            dx, dy = slingshot.x - self.loc_info[0], slingshot.y - self.loc_info[1]
            self.velocity.magnitude = min(int(math.hypot(dx, dy) / 2), 80)
            self.velocity.angle = math.pi / 2 + math.atan2(dy, dx)
    '''显示发射小鸟的路径'''
    def projectpath(self):
        if self.is_loaded:
            path = []
            bird = Bird(self.screen, self.imagepaths, self.loc_info, velocity=self.velocity)
            for i in range(30):
                bird.move()
                if i % 5 == 0: path.append((bird.loc_info[0], bird.loc_info[1]))
            for point in path:
                pygame.draw.ellipse(self.screen, self.color, (point[0], point[1], 2, 2))
    '''移动小鸟'''
    def move(self):
        # 根据重力改变小鸟的速度向量
        self.velocity = VectorAddition(self.velocity, self.gravity)
        self.loc_info[0] += self.velocity.magnitude * math.sin(self.velocity.angle)
        self.loc_info[1] -= self.velocity.magnitude * math.cos(self.velocity.angle)
        self.velocity.magnitude *= self.inverse_friction
        # 宽度超出屏幕
        if self.loc_info[0] > self.screen_size[0] - self.loc_info[2]:
            self.loc_info[0] = 2 * (self.screen_size[0] - self.loc_info[2]) - self.loc_info[0]
            self.velocity.angle *= -1
            self.velocity.magnitude *= self.elasticity
        elif self.loc_info[0] < self.loc_info[2]:
            self.loc_info[0] = 2 * self.loc_info[2] - self.loc_info[0]
            self.velocity.angle *= -1
            self.velocity.magnitude *= self.elasticity
        # 高度超出屏幕
        if self.loc_info[1] > self.screen_size[1] - self.loc_info[2]:
            self.loc_info[1] = 2 * (self.screen_size[1] - self.loc_info[2]) - self.loc_info[1]
            self.velocity.angle = math.pi - self.velocity.angle
            self.velocity.magnitude *= self.elasticity
        elif self.loc_info[1] < self.loc_info[2]:
            self.loc_info[1] = 2 * self.loc_info[2] - self.loc_info[1]
            self.velocity.angle = math.pi - self.velocity.angle
            self.velocity.magnitude *= self.elasticity

实现它主要需要考虑的是小鸟其实存在五种状态:

  • 排队状态,即在左下角等待进入弹弓时的状态,静止不动即可;
  • 就绪状态,即进入弹弓准备被发射的状态,其需要跟着鼠标不断地移动,使得玩家知道自己目前调整小鸟所到的位置被发射出去之后大概会是 什么样的角度和路径;
  • 飞行状态,即被弹弓发射出去之后的状态,需要根据重力和小鸟的初速度来计算其飞行路径并不断地移动;
  • 碰撞状态,即在飞行过程中撞击到其他物体例如小猪和木桩等时,运动状态发生了改变;
  • 静止状态,即小鸟完成飞行状态之后最终静止时的状态。

接着来实现一下小猪:

'''猪'''
class Pig(pygame.sprite.Sprite):
    def __init__(self, screen, imagepaths, loc_info, velocity=None, **kwargs):
        pygame.sprite.Sprite.__init__(self)
        assert len(loc_info) == 3
        assert len(imagepaths) == 3
        # 设置必要的属性常量
        self.screen = screen
        self.loc_info = list(loc_info)
        self.imagepaths = imagepaths
        self.velocity = VelocityVector() if velocity is None else velocity
        self.type = 'pig'
        self.is_dead = False
        self.elasticity = 0.8
        self.switch_freq = 20
        self.animate_count = 0
        self.inverse_friction = 0.99
        self.gravity = VelocityVector(0.2, math.pi)
        # 屏幕大小
        self.screen_size = screen.get_rect().size
        self.screen_size = (self.screen_size[0], self.screen_size[1] - 50)
        # 导入图像
        self.pig_images = []
        for imagepath in imagepaths: self.pig_images.append(pygame.image.load(imagepath))
        # 设置当前图像
        self.image = random.choice(self.pig_images[:2])
    '''画到屏幕上'''
    def draw(self):
        self.animate_count += 1
        if (self.animate_count % self.switch_freq == 0) and (not self.is_dead):
            self.animate_count = 0
            self.image = random.choice(self.pig_images[:2])
        position = self.loc_info[0] - self.loc_info[2], self.loc_info[1] - self.loc_info[2]
        self.screen.blit(self.image, position)
    '''移动猪'''
    def move(self):
        # 根据重力改变猪的速度向量
        self.velocity = VectorAddition(self.velocity, self.gravity)
        self.loc_info[0] += self.velocity.magnitude * math.sin(self.velocity.angle)
        self.loc_info[1] -= self.velocity.magnitude * math.cos(self.velocity.angle)
        self.velocity.magnitude *= self.inverse_friction
        # 宽度超出屏幕
        if self.loc_info[0] > self.screen_size[0] - self.loc_info[2]:
            self.loc_info[0] = 2 * (self.screen_size[0] - self.loc_info[2]) - self.loc_info[0]
            self.velocity.angle *= -1
            self.velocity.magnitude *= self.elasticity
        elif self.loc_info[0] < self.loc_info[2]:
            self.loc_info[0] = 2 * self.loc_info[2] - self.loc_info[0]
            self.velocity.angle *= -1
            self.velocity.magnitude *= self.elasticity
        # 高度超出屏幕
        if self.loc_info[1] > self.screen_size[1] - self.loc_info[2]:
            self.loc_info[1] = 2 * (self.screen_size[1] - self.loc_info[2]) - self.loc_info[1]
            self.velocity.angle = math.pi - self.velocity.angle
            self.velocity.magnitude *= self.elasticity
        elif self.loc_info[1] < self.loc_info[2]:
            self.loc_info[1] = 2 * self.loc_info[2] - self.loc_info[1]
            self.velocity.angle = math.pi - self.velocity.angle
            self.velocity.magnitude *= self.elasticity
    '''猪死掉了'''
    def setdead(self):
        self.is_dead = True
        self.image = self.pig_images[-1]

猪在游戏中主要包括三种状态:

  • 静止状态,即未被击中时静止在某处的状态;
  • 被击中后的运动状态,即被其他物体击中之后根据动量守恒原理也一起运行时的状态;
  • 被击中后的静止状态,即因为被击中而产生运动之后又恢复静止时的状态、

游戏中的木块实现原理与小猪类似:

''地图里的木块'''
class Block(pygame.sprite.Sprite):
    def __init__(self, screen, imagepaths, loc_info, velocity=None, **kwargs):
        pygame.sprite.Sprite.__init__(self)
        assert len(loc_info) == 3
        assert len(imagepaths) == 2
        # 设置必要的属性常量
        self.type = 'block'
        self.screen = screen
        self.loc_info = list(loc_info)
        self.imagepaths = imagepaths
        self.velocity = VelocityVector() if velocity is None else velocity
        self.elasticity = 0.7
        self.is_destroyed = False
        self.inverse_friction = 0.99
        self.gravity = VelocityVector(0.2, math.pi)
        # 导入图像
        self.block_images = []
        for imagepath in imagepaths: self.block_images.append(pygame.transform.scale(pygame.image.load(imagepath), (100, 100)))
        # 屏幕大小
        self.screen_size = screen.get_rect().size
        self.screen_size = (self.screen_size[0], self.screen_size[1] - 50)
        # 设置当前图像
        self.image = self.block_images[0]
        self.rect = self.image.get_rect()
        self.rotate_angle = math.radians(0)
    '''画到屏幕上'''
    def draw(self):
        pygame.transform.rotate(self.image, self.rotate_angle)
        self.screen.blit(self.image, (self.loc_info[0] - self.rect.width // 2, self.loc_info[1]))
    '''设置为损坏状态'''
    def setdestroy(self):
        self.is_destroyed = True
        self.image = self.block_images[1]
    '''移动木块'''
    def move(self):
        # 根据重力改变木块的速度向量
        self.velocity = VectorAddition(self.velocity, self.gravity)
        self.loc_info[0] += self.velocity.magnitude * math.sin(self.velocity.angle)
        self.loc_info[1] -= self.velocity.magnitude * math.cos(self.velocity.angle)
        self.velocity.magnitude *= self.inverse_friction
        # 宽度超出屏幕
        if self.loc_info[0] > self.screen_size[0] - self.rect.width:
            self.loc_info[0] = 2 * (self.screen_size[0] - self.rect.width) - self.loc_info[0]
            self.velocity.angle *= -1
            self.rotate_angle = -self.velocity.angle
            self.velocity.magnitude *= self.elasticity
        elif self.loc_info[0] < self.rect.width:
            self.loc_info[0] = 2 * self.rect.width - self.loc_info[0]
            self.velocity.angle *= -1
            self.rotate_angle = -self.velocity.angle
            self.velocity.magnitude *= self.elasticity
        # 高度超出屏幕
        if self.loc_info[1] > self.screen_size[1] - self.rect.height:
            self.loc_info[1] = 2 * (self.screen_size[1] - self.rect.height) - self.loc_info[1]
            self.velocity.angle = math.pi - self.velocity.angle
            self.rotate_angle = math.pi - self.velocity.angle
            self.velocity.magnitude *= self.elasticity
        elif self.loc_info[1] < self.rect.height:
            self.loc_info[1] = 2 * self.rect.height - self.loc_info[1]
            self.velocity.angle = math.pi - self.velocity.angle
            self.rotate_angle = math.pi - self.velocity.angle
            self.velocity.magnitude *= self.elasticity

最后,我们来实现一下墙和弹弓就可以啦:

'''弹弓'''
class Slingshot(pygame.sprite.Sprite):
    def __init__(self, screen, x, y, width, height, color=(66, 73, 73), line_color=(100, 30, 22), **kwargs):
        pygame.sprite.Sprite.__init__(self)
        self.x = x
        self.y = y
        self.color = color
        self.width = width
        self.height = height
        self.screen = screen
        self.line_color = line_color
        self.type = 'slingshot'
    '''画到屏幕上'''
    def draw(self, bird=None):
        pygame.draw.rect(self.screen, self.color, (self.x, self.y + self.height * 1 / 3, self.width, self.height * 2 / 3))
        if bird is not None and bird.is_loaded:
            pygame.draw.line(self.screen, self.line_color, (self.x, self.y + self.height / 6), (bird.loc_info[0], bird.loc_info[1] + bird.loc_info[2] / 2), 10)
            pygame.draw.line(self.screen, self.line_color, (self.x + self.width, self.y + self.height / 6), (bird.loc_info[0] + bird.loc_info[2], bird.loc_info[1] + bird.loc_info[2] / 2), 10)
        pygame.draw.rect(self.screen, self.color, (self.x - self.width / 4, self.y, self.width / 2, self.height / 3), 5)
        pygame.draw.rect(self.screen, self.color, (self.x + self.width * 3 / 4, self.y, self.width / 2, self.height / 3), 5)


'''墙'''
class Slab(pygame.sprite.Sprite):
    def __init__(self, screen, imagepaths, x, y, width, height, color=(255, 255, 255)):
        pygame.sprite.Sprite.__init__(self)
        self.x = x
        self.y = y
        self.color = color
        self.width = width
        self.height = height
        self.screen = screen
        self.imagepaths = imagepaths
        if self.width > self.height:
            self.image = pygame.image.load(self.imagepaths[0])
        else:
            self.image = pygame.image.load(self.imagepaths[1])
        self.image = pygame.transform.scale(self.image, (self.width, self.height))
        self.type = 'wall'
    '''画到屏幕上'''
    def draw(self):
        self.screen.blit(self.image, (self.x, self.y))

由此,我们完成了所有游戏精灵的定义,可以开始实现游戏的主循环啦,具体的代码实现如下:

'''开始游戏'''
def start(self):
    # 导入所有游戏精灵
    game_sprites = self.loadlevelmap()
    birds, pigs, blocks, walls = game_sprites['birds'], game_sprites['pigs'], game_sprites['blocks'], game_sprites['walls']
    slingshot = Slingshot(self.screen, 200, self.screen_size[1] - 200, 30, 200)
    birds[0].load(slingshot)
    score_label = Label(self.screen, 50, 10, 100, 50)
    score_label.addtext(f'SCORE: {self.score}', 25, self.cfg.FONTPATH['Comic_Kings'], (236, 240, 241))
    birds_remaining_label = Label(self.screen, 120, 50, 100, 50)
    birds_remaining_label.addtext(f"BIRDS REMAINING: {len(birds)}", 25, self.cfg.FONTPATH['Comic_Kings'], (236, 240, 241))
    pigs_remaining_label = Label(self.screen, 110, 90, 100, 50)
    pigs_remaining_label.addtext(f"PIGS REMAINING: {len(pigs)}", 25, self.cfg.FONTPATH['Comic_Kings'], (236, 240, 241))
    carles_label = Label(self.screen, self.screen_size[0] - 270, self.screen_size[1] - 20, 300, 100)
    carles_label.addtext('CARLES', 60, self.cfg.FONTPATH['arfmoochikncheez'], (113, 125, 126))
    # 游戏主循环
    clock = pygame.time.Clock()
    blocks_to_remove, pigs_to_remove = [], []
    while True:
        # --按键检测
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                self.quitgame()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_q:
                    self.quitgame()
                elif event.key == pygame.K_r:
                    self.start()
                elif event.key == pygame.K_p or event.key == pygame.K_ESCAPE:
                    self.pauseinterface()
            elif event.type == pygame.MOUSEBUTTONDOWN:
                if birds[0].selected():
                    birds[0].is_selected = True
            elif event.type == pygame.MOUSEBUTTONUP:
                if birds[0].is_selected:
                    birds[0].is_selected = False
                    birds[0].start_flying = True
        # --背景颜色填充
        color = self.cfg.BACKGROUND_COLOR
        for i in range(3):
            color = (color[0] + 5, color[1] + 5, color[2] + 5)
            pygame.draw.rect(self.screen, color, (0, i * 300, self.screen_size[0], 300))
        pygame.draw.rect(self.screen, (77, 86, 86), (0, self.screen_size[1], self.screen_size[0], 50))
        # --判断游戏是否结束,若没有则导入新的小鸟
        if (not birds[0].is_loaded) and self.still(pigs + birds + blocks):
            birds.pop(0)
            if self.status(pigs, birds) == 2:
                self.score += len(birds) * 100
                self.switchlevelinterface()
            elif self.status(pigs, birds) == 1:
                self.failureinterface()
            birds[0].load(slingshot)
            birds[0].start_flying = False
        # --重置小鸟的位置
        if birds[0].is_selected:
            birds[0].reposition(slingshot)
        if hasattr(birds[0], 'start_flying') and birds[0].start_flying:
            birds[0].is_loaded = False
        # --弹弓
        slingshot.draw(birds[0])
        # --判断猪是否撞上木桩
        for i in range(len(pigs)):
            for j in range(len(blocks)):
                pig_magnitude_1, block_magnitude_1 = pigs[i].velocity.magnitude, blocks[j].velocity.magnitude
                pigs[i], blocks[j], is_collision = self.collision(pigs[i], blocks[j])
                pig_magnitude_2, block_magnitude_2 = pigs[i].velocity.magnitude, blocks[j].velocity.magnitude
                if is_collision:
                    if abs(pig_magnitude_2 - pig_magnitude_2) > 2:
                        blocks_to_remove.append(blocks[j])
                        blocks[j].setdestroy()
                    if abs(block_magnitude_2 - block_magnitude_1) > 2:
                        pigs_to_remove.append(pigs[i])
                        pigs[i].setdead()
        # --判断鸟是否撞上木桩
        for i in range(len(birds)):
            if not (birds[i].is_loaded or birds[i].velocity.magnitude == 0):
                for j in range(len(blocks)):
                    bird_magnitude_1, block_magnitude_1 = birds[i].velocity.magnitude, blocks[j].velocity.magnitude
                    birds[i], blocks[j], is_collision = self.collision(birds[i], blocks[j])
                    bird_magnitude_2, block_magnitude_2 = birds[i].velocity.magnitude, blocks[j].velocity.magnitude
                    if is_collision:
                        if abs(bird_magnitude_1 - bird_magnitude_2) > 2:
                            if blocks[j] not in blocks_to_remove:
                                blocks_to_remove.append(blocks[j])
                                blocks[j].setdestroy()
        # --判断猪是否撞上猪或者猪撞墙
        for i in range(len(pigs)):
            pigs[i].move()
            for j in range(i+1, len(pigs)):
                pig1_magnitude_1, pig2_magnitude_1 = pigs[i].velocity.magnitude, pigs[j].velocity.magnitude
                pigs[i], pigs[j], is_collision = self.collision(pigs[i], pigs[j])
                pig1_magnitude_2, pig2_magnitude_2 = pigs[i].velocity.magnitude, pigs[j].velocity.magnitude
                if abs(pig1_magnitude_1 - pig1_magnitude_2) > 2:
                    if pigs[j] not in pigs_to_remove:
                        pigs_to_remove.append(pigs[j])
                        pigs[j].setdead()
                if abs(pig2_magnitude_1 - pig2_magnitude_2) > 2:
                    if pigs[i] not in pigs_to_remove:
                        pigs_to_remove.append(pigs[i])
                        pigs[i].setdead()
            for wall in walls: pigs[i] = self.collision(pigs[i], wall)[0]
            pigs[i].draw()
        # --判断鸟是否撞到猪或者鸟是否撞到墙
        for i in range(len(birds)):
            if (not birds[i].is_loaded) and (birds[i].velocity.magnitude):
                birds[i].move()
                for j in range(len(pigs)):
                    bird_magnitude_1, pig_magnitude_1 = birds[i].velocity.magnitude, pigs[j].velocity.magnitude
                    birds[i], pigs[j], is_collision = self.collision(birds[i], pigs[j])
                    bird_magnitude_2, pig_magnitude_2 = birds[i].velocity.magnitude, pigs[j].velocity.magnitude
                    if is_collision:
                        if abs(bird_magnitude_2 - bird_magnitude_1) > 2:
                            if pigs[j] not in pigs_to_remove:
                                pigs_to_remove.append(pigs[j])
                                pigs[j].setdead()
            if birds[i].is_loaded: birds[i].projectpath()
            for wall in walls: birds[i] = self.collision(birds[i], wall)[0]
            birds[i].draw()
        # --判断木桩是否撞到了木桩或者木桩撞到墙
        for i in range(len(blocks)):
            for j in range(i+1, len(blocks)):
                block1_magnitude_1, block2_magnitude_1 = blocks[i].velocity.magnitude, blocks[j].velocity.magnitude
                blocks[i], blocks[j], is_collision = self.collision(blocks[i], blocks[j])
                block1_magnitude_2, block2_magnitude_2 = blocks[i].velocity.magnitude, blocks[j].velocity.magnitude
                if is_collision:
                    if abs(block1_magnitude_2 - block1_magnitude_1) > 2:
                        if blocks[j] not in blocks_to_remove:
                            blocks_to_remove.append(blocks[j])
                            blocks[j].setdestroy()
                    if abs(block2_magnitude_2 - block2_magnitude_1) > 2:
                        if blocks[i] not in blocks_to_remove:
                            blocks_to_remove.append(blocks[i])
                            blocks[i].setdestroy()
            blocks[i].move()
            for wall in walls: blocks[i] = self.collision(blocks[i], wall)[0]
            blocks[i].draw()
        # --墙
        for wall in walls: wall.draw()
        # --显示文字
        score_label.addtext(f'SCORE: {self.score}', 25, self.cfg.FONTPATH['Comic_Kings'], (236, 240, 241))
        score_label.draw()
        birds_remaining_label.addtext(f"BIRDS REMAINING: {len(birds)}", 25, self.cfg.FONTPATH['Comic_Kings'], (236, 240, 241))
        birds_remaining_label.draw()
        pigs_remaining_label.addtext(f"PIGS REMAINING: {len(pigs)}", 25, self.cfg.FONTPATH['Comic_Kings'], (236, 240, 241))
        pigs_remaining_label.draw()
        carles_label.draw()
        # --画面刷新
        pygame.display.update()
        clock.tick(self.cfg.FPS)
        # --删除无效的元素
        if self.still(birds + pigs + blocks):
            for pig in pigs_to_remove:
                if pig in pigs:
                    pigs.remove(pig)
                    self.score += 100
            for block in blocks_to_remove:
                if block in blocks:
                    blocks.remove(block)
                    self.score += 50
            pigs_to_remove = []
            blocks_to_remove = []

其实就是一些按键检测和碰撞检测以及一些分数之类的游戏状态实时更新,感觉没啥好讲的,总之,就这么简单就完事啦~

到此这篇关于忆童年!用Python实现愤怒的小鸟游戏的文章就介绍到这了,更多相关Python愤怒的小鸟内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
Python类的基础入门知识
Nov 24 Python
浅谈MySQL中的触发器
May 05 Python
举例讲解Linux系统下Python调用系统Shell的方法
Nov 07 Python
python自带的http模块详解
Nov 06 Python
Python常见工厂函数用法示例
Mar 21 Python
Python socket实现简单聊天室
Apr 01 Python
解决PyCharm的Python.exe已经停止工作的问题
Nov 29 Python
django 实现编写控制登录和访问权限控制的中间件方法
Jan 15 Python
PyQT实现菜单中的复制,全选和清空的功能的方法
Jun 17 Python
python3.6编写的单元测试示例
Aug 17 Python
Python流程控制常用工具详解
Feb 24 Python
python中os包的用法
Jun 01 Python
python单元测试之pytest的使用
Jun 07 #Python
Python趣味实战之手把手教你实现举牌小人生成器
怎么用Python识别手势数字
利用python调用摄像头的实例分析
Jun 07 #Python
python通过opencv调用摄像头操作实例分析
Jun 07 #Python
Python爬虫之用Xpath获取关键标签实现自动评论盖楼抽奖(二)
Jun 07 #Python
还在手动盖楼抽奖?教你用Python实现自动评论盖楼抽奖(一)
Jun 07 #Python
You might like
安装apache2.2.22配置php5.4(具体操作步骤)
2013/06/26 PHP
php生成二维码图片方法汇总
2016/12/17 PHP
laravel5.6框架操作数据curd写法(查询构建器)实例分析
2020/01/26 PHP
Yii使用EasyWechat实现小程序获取用户的openID的方法
2020/04/29 PHP
JavaScript的parseInt 进制问题
2009/05/07 Javascript
jQuery效果 slideToggle() 方法(在隐藏和显示之间切换)
2011/06/28 Javascript
js点击列表文字对应该行显示背景颜色的实现代码
2015/08/05 Javascript
JavaScript实现九九乘法表的简单实例
2016/06/07 Javascript
AngularJS 作用域详解及示例代码
2016/08/17 Javascript
Angular 2.x学习教程之结构指令详解
2017/05/25 Javascript
利用node.js制作命令行工具方法教程(一)
2017/06/22 Javascript
JS使用正则表达式获取小括号、中括号及花括号内容的方法示例
2018/06/01 Javascript
vue click.stop阻止点击事件继续传播的方法
2018/09/04 Javascript
jQuery事件委托代码实践详解
2019/06/21 jQuery
解析JS在获取当前月的最后一天遇到的坑
2019/08/30 Javascript
webpack4 optimization使用总结
2019/11/10 Javascript
微信小程序保持session会话的方法
2020/03/20 Javascript
浅谈vue 二级路由嵌套和二级路由高亮问题
2020/08/06 Javascript
JavaScript数组类型Array相关的属性与方法详解
2020/09/08 Javascript
[01:06:18]DOTA2-DPC中国联赛 正赛 Phoenix vs Dynasty BO3 第二场 1月26日
2021/03/11 DOTA
python错误处理详解
2014/09/28 Python
Pandas数据离散化原理及实例解析
2019/11/16 Python
从numpy数组中取出满足条件的元素示例
2019/11/26 Python
python双向链表原理与实现方法详解
2019/12/03 Python
在python3中使用shuffle函数要注意的地方
2020/02/28 Python
jupyter notebook中美观显示矩阵实例
2020/04/17 Python
Python过滤掉numpy.array中非nan数据实例
2020/06/08 Python
python中zip()函数遍历多个列表方法
2021/02/18 Python
HTML5新增的8类INPUT输入类型介绍
2015/07/06 HTML / CSS
英国和世界各地鲜花速递专家:Arena Flowers
2018/02/10 全球购物
高校优秀辅导员事迹材料
2014/05/07 职场文书
小学安全汇报材料
2014/08/14 职场文书
电力安全教育培训心得体会
2016/01/11 职场文书
react中的DOM操作实现
2021/06/30 Javascript
JavaScript 原型与原型链详情
2021/11/02 Javascript
python中出现invalid syntax报错的几种原因分析
2022/02/12 Python