zoukankan      html  css  js  c++  java
  • Python

    目标

    • 使用 定时器 添加敌机
    • 设计 Enemy

    01,使用定时器添加敌机

    运行 代码,观察 敌机的 出现规律
    1,游戏启动柜后,每隔1秒出现一架敌机
    2,每架敌机 向屏幕下方飞行,飞行 **速度各不相同
    3,每架敌机出现的 水平位置 也不尽相同
    4,当敌机 从屏幕下方飞出,不会再飞回到屏幕中

    1.1 定时器

    • pygame 中可以使用 pygame.time.set_timer() 来添加 定时器
    • 所谓 定时器,就是 每隔一段时间,去执行一些动作
    set_timer(eventid, milliseconds)  - >  None
    
    • set_timer 可以创建一个 事件
    • 可以在 游戏循环事件监听 方法中捕获到该事件
    • 第1个参数 事件代号 需要基于常量 pygame.USEREVENT 来指定
      • USEREVENT 是一个整数,再增加事件可以使用 USEREVENT + 1 指定
    • 第2个参数就是 事件触发 间隔的 毫秒值

    定时器事件的监听

    • 通过 pygame.event.get() 可以获取当前时刻所有的 事件列表
    • 遍历列表 并且判断 event.type 是否等于 eventid,如果相等,表示 定时事件 发生

    1.2 定义并监听创建敌机事件

    pygame定时器 使用套路非常固定:
    1,定义 定时器常量 - - eventid
    2,在 初始化方法 中,调用 set_timer 方法 设置定时器事件
    3,在 游戏循环 中,监听定时器事件

    1)定义事件

    • plane_sprites.py 的顶部定义 事件常量
    # 创建敌机的定时器常量
    CREATE_ENEMY_EVENT = pygame.USEREVENT
    

    plane_sprites.py

    import pygame
    
    # 屏幕大小的常量
    SCREEN_RECT = pygame.Rect(0, 0, 480, 700)
    # 刷新的帧率
    FRAME_PER_SEC = 60
    # 创建敌机的定时器常量
    CREATE_ENEMY_EVENT = pygame.USEREVENT
    
    
    
    class GameSprite(pygame.sprite.Sprite):
        """飞机大战游戏精灵"""
    
        def __init__(self, image_name, speed=1):
            # 调用父类的初始化方法
            super().__init__()
    
            # 定义对象的属性
            self.image = pygame.image.load(image_name)
            self.rect = self.image.get_rect()
            self.speed = speed
    
        def update(self, *args):
            # 在屏幕的垂直方向上移动
            self.rect.y += self.speed
    
    
    class Background(GameSprite):
        """游戏背景精灵"""
        def __init__(self, is_alt=False):
            # 1,调用父类方法实现精灵的创建(image/rect/speed)
            super().__init__("./images/background.png")
    
            # 2,判断是否交替图像,如果是,需要设置初始位置
            if is_alt:
                self.rect.y = -self.rect.height
    
        def update(self, *args):
            # 1,调用父类的方法实现
            super().update()
    
            # 2,判断是否移除屏幕,如果移出屏幕,将图像设置到屏幕上方
            if self.rect.y >= SCREEN_RECT.height:
                self.rect.y = -self.rect.height
    
    

    plane_main.py

    
    import pygame
    from Aircraft_War.plane_sprites import *
    
    class PlaneGame(object):
        """飞机大战主游戏"""
    
        def __init__(self):
            print("游戏初始化")
            # 1,创建游戏的窗口
            # self.screen = pygame.display.set_mode((480, 700))
            self.screen = pygame.display.set_mode(SCREEN_RECT.size)
    
            # 2,创建游戏的时钟
            self.clock = pygame.time.Clock()
    
            # 3,调用私有方法, 精灵和精灵组的创建
            self.__create_sprites()
    
            # 4,设置定时器事件 - 创建敌机
            pygame.time.set_timer(CREATE_ENEMY_EVENT, 1000)
    
        def __create_sprites(self):
            bg1 = Background()
            bg2 = Background(True)
    
            self.back_group = pygame.sprite.Group(bg1, bg2)
    
        def start_game(self):
            print("游戏开始...")
    
            while True:
                # 1,设置刷新帧率
                self.clock.tick(FRAME_PER_SEC)
    
                # 2,事件监听
                self.__event_handler()
    
                # 3,碰撞检测
                self.__check_collide()
    
                # 4,更新/绘制精灵组
                self.__update_sprites()
    
                # 5,更新显示
                pygame.display.update()
    
    
        def __event_handler(self):
    
            for event in pygame.event.get():
                # 判断是否退出游戏
                if event.type == pygame.QUIT:
                    PlaneGame.__game_over()
                elif event.type == CREATE_ENEMY_EVENT:
                    print("敌机出场。。。")
    
        def __check_collide(self):
            pass
    
        def __update_sprites(self):
            self.back_group.update()
            self.back_group.draw(self.screen)
    
        @staticmethod
        def __game_over():
            print("游戏结束")
    
            pygame.QUIT()
            exit()
    
    
    if __name__ == '__main__':
        # 创建游戏对象
        game = PlaneGame()
    
        # 启动游戏
        game.start_game()
    
    

    02,设计 Enemy 类

    1,游戏启动后,每隔1秒出现一架敌机
    2,每架敌机 向屏幕下方飞行,飞行 速度各不相同
    3,每架敌机出现的 水平位置 也不尽相同
    4,当敌机 从屏幕下方飞出,不会再飞回到屏幕中

    • 初始化方法
      • 指定 敌机图片
      • 随机 敌机的 初始位置初始速度
    • 重写 update()
      • 判断 是否飞出屏幕,如果是,从 精灵组 删除

    2.1 敌机类的准备

    
    import pygame
    
    # 屏幕大小的常量
    SCREEN_RECT = pygame.Rect(0, 0, 480, 700)
    # 刷新的帧率
    FRAME_PER_SEC = 60
    # 创建敌机的定时器常量
    CREATE_ENEMY_EVENT = pygame.USEREVENT
    
    
    class GameSprite(pygame.sprite.Sprite):
        """飞机大战游戏精灵"""
        def __init__(self, image_name, speed=1):
            # 调用父类的初始化方法
            super().__init__()
    
            # 定义对象的属性
            self.image = pygame.image.load(image_name)
            self.rect = self.image.get_rect()
            self.speed = speed
    
        def update(self, *args):
            # 在屏幕的垂直方向上移动
            self.rect.y += self.speed
    
    
    class Background(GameSprite):
        """游戏背景精灵"""
        def __init__(self, is_alt=False):
            # 1,调用父类方法实现精灵的创建(image/rect/speed)
            super().__init__("./images/background.png")
    
            # 2,判断是否交替图像,如果是,需要设置初始位置
            if is_alt:
                self.rect.y = -self.rect.height
    
        def update(self, *args):
            # 1,调用父类的方法实现
            super().update()
    
            # 2,判断是否移除屏幕,如果移出屏幕,将图像设置到屏幕上方
            if self.rect.y >= SCREEN_RECT.height:
                self.rect.y = -self.rect.height
    
    
    class Enemy(GameSprite):
        """敌机精灵"""
        def __init__(self):
            # 1,调用父类方法,创建敌机精灵,同事指定敌机图片
            super().__init__("./images/enem1.png")
    
            # 2,指定敌机的初始随机速度
    
            # 3,指定敌机的初始随机位置
    
        def update(self, *args):
            # 1,调用父类方法,保持垂直方向的飞行
            super().update()
    
            # 3,判断是否飞出屏幕,如果是,需要从精灵组删除敌机
            if self.rect.y >= SCREEN_RECT.height:
                print("飞出屏幕,需要从精灵组删除")
    
    

    2.2 创建敌机

    演练步骤

    1,在 __create_sprites,添加 敌机精灵组

    • 敌机是 ** 定时被创建的**,因此在初始化方法中,不需要创建敌机

    2,在 __event_handler,创建敌机,并且 添加到精灵组

    • 调用 精灵组add 方法可以 向精灵组添加精灵

    3,在 __update_sprites,让 敌机精灵组 调用 updatedraw 方法

    演练代码

    
    
    import pygame
    from Aircraft_War.plane_sprites import *
    
    class PlaneGame(object):
        """飞机大战主游戏"""
    
        def __init__(self):
            print("游戏初始化")
            # 1,创建游戏的窗口
            # self.screen = pygame.display.set_mode((480, 700))
            self.screen = pygame.display.set_mode(SCREEN_RECT.size)
    
            # 2,创建游戏的时钟
            self.clock = pygame.time.Clock()
    
            # 3,调用私有方法, 精灵和精灵组的创建
            self.__create_sprites()
    
            # 4,设置定时器事件 - 创建敌机
            pygame.time.set_timer(CREATE_ENEMY_EVENT, 1000)
    
        def __create_sprites(self):
            # 创建背景精灵和精灵组
            bg1 = Background()
            bg2 = Background(True)
    
            self.back_group = pygame.sprite.Group(bg1, bg2)
    
            # 创建敌机的精灵组
            self.enemy_group = pygame.sprite.Group()
    
        def start_game(self):
            print("游戏开始...")
    
            while True:
                # 1,设置刷新帧率
                self.clock.tick(FRAME_PER_SEC)
    
                # 2,事件监听
                self.__event_handler()
    
                # 3,碰撞检测
                self.__check_collide()
    
                # 4,更新/绘制精灵组
                self.__update_sprites()
    
                # 5,更新显示
                pygame.display.update()
    
    
        def __event_handler(self):
    
            for event in pygame.event.get():
                # 判断是否退出游戏
                if event.type == pygame.QUIT:
                    PlaneGame.__game_over()
                elif event.type == CREATE_ENEMY_EVENT:
                    print("敌机出场。。。")
    
                    # 创建敌机精灵
                    enemy = Enemy()
    
                    # 将敌机精灵添加到敌机精灵组
                    self.enemy_group.add(enemy)
    
    
        def __check_collide(self):
            pass
    
        def __update_sprites(self):
            self.back_group.update()
            self.back_group.draw(self.screen)
    
            self.enemy_group.update()
            self.enemy_group.draw(self.screen)
    
        @staticmethod
        def __game_over():
            print("游戏结束")
    
            pygame.QUIT()
            exit()
    
    
    if __name__ == '__main__':
        # 创建游戏对象
        game = PlaneGame()
    
        # 启动游戏
        game.start_game()
    
    

    2.3 随机敌机位置和速度

    1)导入模块

    • 在导入模块时,建议 按照以下顺序导入
    1,官方标准模块导入
    2,第三方模块导入
    3,应用程序模块导入
    
    • 修改 plane_sprites.py 增加 random 的导入
    import random
    

    2)随机位置

    使用 pygame.Rect 提供的 bottom 属性,在指定敌机初始位置时,会比较方便

    • bottom = y + height
    • y = bottom - height

    代码实现

    • 修改 初始化方法,随机敌机出现 速度位置
    
    import random
    import pygame
    
    # 屏幕大小的常量
    SCREEN_RECT = pygame.Rect(0, 0, 480, 700)
    # 刷新的帧率
    FRAME_PER_SEC = 60
    # 创建敌机的定时器常量
    CREATE_ENEMY_EVENT = pygame.USEREVENT
    
    
    
    class GameSprite(pygame.sprite.Sprite):
        """飞机大战游戏精灵"""
        def __init__(self, image_name, speed=1):
            # 调用父类的初始化方法
            super().__init__()
    
            # 定义对象的属性
            self.image = pygame.image.load(image_name)
            self.rect = self.image.get_rect()
            self.speed = speed
    
        def update(self, *args):
            # 在屏幕的垂直方向上移动
            self.rect.y += self.speed
    
    
    class Background(GameSprite):
        """游戏背景精灵"""
        def __init__(self, is_alt=False):
            # 1,调用父类方法实现精灵的创建(image/rect/speed)
            super().__init__("./images/background.png")
    
            # 2,判断是否交替图像,如果是,需要设置初始位置
            if is_alt:
                self.rect.y = -self.rect.height
    
        def update(self, *args):
            # 1,调用父类的方法实现
            super().update()
    
            # 2,判断是否移除屏幕,如果移出屏幕,将图像设置到屏幕上方
            if self.rect.y >= SCREEN_RECT.height:
                self.rect.y = -self.rect.height
    
    
    class Enemy(GameSprite):
        """敌机精灵"""
        def __init__(self):
            # 1,调用父类方法,创建敌机精灵,同事指定敌机图片
            super().__init__("./images/enemy1.png")
    
            # 2,指定敌机的初始随机速度
            self.speed = random.randint(1, 6)
    
            # 3,指定敌机的初始随机位置
            self.rect.bottom = 0
    
            max_x = SCREEN_RECT.width - self.rect.width
            self.rect.x = random.randint(0, max_x)
    
        def update(self, *args):
            # 1,调用父类方法,保持垂直方向的飞行
            super().update()
    
            # 3,判断是否飞出屏幕,如果是,需要从精灵组删除敌机
            if self.rect.y >= SCREEN_RECT.height:
                print("飞出屏幕,需要从精灵组删除")
    
    

    2.4 移除屏幕销毁敌机

    • 敌机移出屏幕之后,如果 没有撞到英雄,敌机的历史使命已经结束
    • 需要从 敌机组 删除,否则会造成 内存浪费

    检测敌机被销毁

    • __del__ 内置方法会在对象被销毁前调用,在开发中,可以用于 判读对象是否被销毁
        def __del__(self):
            print("敌机挂了 %s" % self.rect)
    

    代码实现

    • 判断敌机是否飞出屏幕,如果是,调用 kill() 方法从所有组中删除
     # kill 方法可以将精灵从所有精灵组中移除,精灵就会被自动销毁
     self.kill()
    
    import random
    import pygame
    
    # 屏幕大小的常量
    SCREEN_RECT = pygame.Rect(0, 0, 480, 700)
    # 刷新的帧率
    FRAME_PER_SEC = 60
    # 创建敌机的定时器常量
    CREATE_ENEMY_EVENT = pygame.USEREVENT
    
    
    
    class GameSprite(pygame.sprite.Sprite):
        """飞机大战游戏精灵"""
        def __init__(self, image_name, speed=1):
            # 调用父类的初始化方法
            super().__init__()
    
            # 定义对象的属性
            self.image = pygame.image.load(image_name)
            self.rect = self.image.get_rect()
            self.speed = speed
    
        def update(self, *args):
            # 在屏幕的垂直方向上移动
            self.rect.y += self.speed
    
    
    class Background(GameSprite):
        """游戏背景精灵"""
        def __init__(self, is_alt=False):
            # 1,调用父类方法实现精灵的创建(image/rect/speed)
            super().__init__("./images/background.png")
    
            # 2,判断是否交替图像,如果是,需要设置初始位置
            if is_alt:
                self.rect.y = -self.rect.height
    
        def update(self, *args):
            # 1,调用父类的方法实现
            super().update()
    
            # 2,判断是否移除屏幕,如果移出屏幕,将图像设置到屏幕上方
            if self.rect.y >= SCREEN_RECT.height:
                self.rect.y = -self.rect.height
    
    
    class Enemy(GameSprite):
        """敌机精灵"""
        def __init__(self):
            # 1,调用父类方法,创建敌机精灵,同事指定敌机图片
            super().__init__("./images/enemy1.png")
    
            # 2,指定敌机的初始随机速度
            self.speed = random.randint(1, 6)
    
            # 3,指定敌机的初始随机位置
            self.rect.bottom = 0
    
            max_x = SCREEN_RECT.width - self.rect.width
            self.rect.x = random.randint(0, max_x)
    
        def update(self, *args):
            # 1,调用父类方法,保持垂直方向的飞行
            super().update()
    
            # 3,判断是否飞出屏幕,如果是,需要从精灵组删除敌机
            if self.rect.y >= SCREEN_RECT.height:
                print("飞出屏幕,需要从精灵组删除")
    
                # kill 方法可以将精灵从所有精灵组中移除,精灵就会被自动销毁
                self.kill()
    
        def __del__(self):
            print("敌机挂了 %s" % self.rect)
    
  • 相关阅读:
    Unix命令大全
    vs2008 与 IE8出现的兼容性问题
    Java 创建文件、文件夹以及临时文件
    如何修改Wamp中mysql默认空密码
    PAT 乙级真题 1003.数素数
    Tags support in htmlText flash as3
    DelphiXE4 FireMonkey 试玩记录,开发IOS应用 还是移植
    10 Great iphone App Review sites to Promote your Apps!
    HTML tags in textfield
    Delphi XE4 IOS 开发, "No eligible applications were found“
  • 原文地址:https://www.cnblogs.com/xiaoqshuo/p/9580241.html
Copyright © 2011-2022 走看看