忆童年!用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中的with...as用法介绍
May 28 Python
Python编程之序列操作实例详解
Jul 22 Python
Python机器学习之K-Means聚类实现详解
Feb 22 Python
解决pyttsx3无法封装的问题
Dec 24 Python
python实现剪切功能
Jan 23 Python
python3.4 将16进制转成字符串的实例
Jun 12 Python
Python OpenCV之图片缩放的实现(cv2.resize)
Jun 28 Python
在python中用print()输出多个格式化参数的方法
Jul 16 Python
python通过实例讲解反射机制
Oct 17 Python
浅谈Tensorflow加载Vgg预训练模型的几个注意事项
May 26 Python
pyCharm 设置调试输出窗口中文显示方式(字符码转换)
Jun 09 Python
python属于哪种语言
Aug 16 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实现查询百度google收录情况(示例代码)
2013/08/02 PHP
php遍历数组的4种方法总结
2014/07/05 PHP
php中get_meta_tags()、CURL与user-agent用法分析
2014/12/16 PHP
php+curl 发送图片处理代码分享
2015/07/09 PHP
PHP获取页面执行时间的方法(推荐)
2016/12/10 PHP
thinkphp 验证码 的使用小结
2017/05/07 PHP
JavaScript中的私有成员
2006/09/18 Javascript
如何用javascript去掉字符串里的所有空格
2007/02/08 Javascript
js对图片base64编码字符串进行解码并输出图像示例
2014/03/17 Javascript
JS给超链接加确认对话框的方法
2015/02/24 Javascript
JS留言功能的简单实现案例(推荐)
2016/06/23 Javascript
js html5 css俄罗斯方块游戏再现
2016/10/17 Javascript
简单好用的nodejs 爬虫框架分享
2017/03/26 NodeJs
JQuery实现定时刷新功能代码
2017/05/09 jQuery
利用SpringMVC过滤器解决vue跨域请求的问题
2018/02/10 Javascript
解决vue.js 数据渲染成功仍报错的问题
2018/08/25 Javascript
解决Vue+Element ui开发中碰到的IE问题
2018/09/03 Javascript
从0到1搭建element后台框架优化篇(打包优化)
2019/05/12 Javascript
vue element自定义表单验证请求后端接口验证
2019/12/11 Javascript
微信分享invalid signature签名错误踩过的坑
2020/04/11 Javascript
JavaScript用document.write()输出换行的示例代码
2020/11/26 Javascript
python实现按任意键继续执行程序
2016/12/30 Python
利用Python读取文件的四种不同方法比对
2017/05/18 Python
使用Python轻松完成垃圾分类(基于图像识别)
2019/07/09 Python
Pycharm编辑器功能之代码折叠效果的实现代码
2020/10/15 Python
html5实现滑块功能之type=&quot;range&quot;属性
2020/02/18 HTML / CSS
DKNY品牌官网:纽约大都会时尚风格
2016/10/20 全球购物
《明天,我们毕业》教学反思
2014/04/24 职场文书
工地安全标语
2014/06/07 职场文书
反四风个人对照检查材料
2014/09/26 职场文书
Python使用protobuf序列化和反序列化的实现
2021/05/19 Python
SQL注入的实现以及防范示例详解
2021/06/02 MySQL
MYSQL如何查看进程和kill进程
2022/03/13 MySQL
MySQL 中如何归档数据的实现方法
2022/03/16 SQL Server
使用Python开发冰球小游戏
2022/04/30 Python
python 学习GCN图卷积神经网络
2022/05/11 Python