忆童年!用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单例模式与metaclass
Jan 15 Python
Python 实现字符串中指定位置插入一个字符
May 02 Python
Python加载带有注释的Json文件实例
May 23 Python
Jupyter notebook远程访问服务器的方法
May 24 Python
将tensorflow的ckpt模型存储为npy的实例
Jul 09 Python
Linux下python制作名片示例
Jul 20 Python
Python提取频域特征知识点浅析
Mar 04 Python
Python中常用的高阶函数实例详解
Feb 21 Python
浅谈在django中使用filter()(即对QuerySet操作)时踩的坑
Mar 31 Python
Python 解析xml文件的示例
Sep 29 Python
使用numpy nonzero 找出非0元素
May 14 Python
在python中读取和写入CSV文件详情
Jun 28 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
令PHP初学者头疼十四条问题大总结
2008/11/12 PHP
PHP实现取得HTTP请求的原文
2014/08/18 PHP
php遍历类中包含的所有元素的方法
2015/05/12 PHP
php邮箱地址正则表达式验证
2015/11/13 PHP
JavaScript中的this实例分析
2011/04/28 Javascript
js函数名与form表单元素同名冲突的问题
2014/03/07 Javascript
node.js中的fs.readFileSync方法使用说明
2014/12/15 Javascript
javascript实现的简单计时器
2015/07/19 Javascript
最实用的jQuery分页插件
2016/10/09 Javascript
vue2.0嵌套路由实现豆瓣电影分页功能(附demo)
2017/03/13 Javascript
利用jsonp与代理服务器方案解决跨域问题
2017/09/14 Javascript
vue富文本编辑器组件vue-quill-edit使用教程
2018/09/21 Javascript
基于vue-cli npm run build之后vendor.js文件过大的解决方法
2018/09/27 Javascript
angularJS自定义directive之带参方法传递详解
2018/10/09 Javascript
vue使用vuex实现首页导航切换不同路由的方法
2019/05/08 Javascript
JS自定义右键菜单实现代码解析
2020/07/16 Javascript
vue自定义组件(通过Vue.use()来使用)即install的用法说明
2020/08/11 Javascript
js闭包和垃圾回收机制示例详解
2021/03/01 Javascript
使用python实现baidu hi自动登录的代码
2013/02/10 Python
Python学习笔记_数据排序方法
2014/05/22 Python
Python中set与frozenset方法和区别详解
2016/05/23 Python
Python的网络编程库Gevent的安装及使用技巧
2016/06/24 Python
Python中二维列表如何获取子区域元素的组成
2017/01/19 Python
python查看模块,对象的函数方法
2018/10/16 Python
一文秒懂python读写csv xml json文件各种骚操作
2019/07/04 Python
Python reduce函数作用及实例解析
2020/05/08 Python
浅谈Keras的Sequential与PyTorch的Sequential的区别
2020/06/17 Python
matplotlib 多个图像共用一个colorbar的实现示例
2020/09/10 Python
如何利用python发送邮件
2020/09/26 Python
HTML5探秘:用requestAnimationFrame优化Web动画
2018/06/03 HTML / CSS
详解基于 Canvas 手撸一个六边形能力图
2019/09/02 HTML / CSS
同事吵架检讨书
2014/02/05 职场文书
文明餐桌活动方案
2014/02/11 职场文书
高中美术教师事迹材料
2014/08/22 职场文书
获奖感言一句话
2015/07/31 职场文书
一文读懂navicat for mysql基础知识
2021/05/31 MySQL