面向对象的飞机大战编程

游戏框架分为两部分

1.创建一个plane_main.py的主文件,写出一个PlaneGame的主类。

import pygame
class PlaneGmae(object):
    def __init__(self):
        print('游戏初始化...')
    def start_game(self):
        print('游戏开始...')
if __name__ == '__main__':
    # 创建游戏对象
    game = PlaneGmae()
    # 启动游戏
    game.start_game()

运行结果为

D:\python\python36\python.exe D:/PycharmProjects/feijidazhan_1/feiji.py
游戏初始化...
游戏开始...

2.另新建一个plane_sprite.py 的模块

import pygame
class Game_Sprite(pygame.sprite.Sprite):#派生精灵子类
    '''飞机大战游戏精灵'''
    def __init__(self,image_name,speed = 1):
        # 继承父类的__init__()
        super().__init__()
        # 定义对象的属性
        self.image =pygame.image.load(image_name)
        self.rect = self.image.get_rect()
        '''self.image的get_rect()返回pygame.Rect(0,0,width,height)'''
        self.speed = speed
        def update(self):
           self.rect.y += self.speed

3. 主程序中设置游戏初始化的步骤

class PlaneGmae(object):
    def __init__(self):
        print('游戏初始化...')
        # 1.创建游戏屏幕
        self.screen = pygame.display.set_mode(SCREEN_RECT.size) #引入的常量
        # 2.创建游戏时钟
        self.clock = pygame.time.Clock()
        # 3.私有方法创建精灵和精灵组
        self.__creat_sprite()
    def __creat_sprite(self):
        pass

4主程序中游戏的开始部分的步骤

class PlaneGmae(object):
    游戏初始化部分...
    .......
    def start_game(self):
        print('游戏开始...')
        while True:
            # 1.设置帧率
            self.clock.tick(60)
            # 2. 事件监听
            self.__event_monitor()
            # 3. 碰撞检测
            self.__check_collide()
            # 4. 绘制图像
            self.__blit_photo()
            # 5.刷新显示
            pygame.display.update()

5.为了让程序可读性高,便于维护,建议是使用私有方法,由于上面的四个步骤都是私有方法,所以接下来在上面的主要类开始布置私有方法

    def __event_monitor(self):
        pass
    def __check_collide(self):
        pass
    def __blit_photo(self):
        pass
    @staticmethod
    def __game_over():
        print('退出游戏')
        # 卸载所有模块
        pygame.quit()
        # 退出程序
        exit()
  • 需要注意的上面有一个静态方法,由于这个方法调用这个类里的任何方法和属性,所以要把它编程静态方法,加修饰符@staticmethod 不用加self参数
  • 代码走到上面的这些就已经把飞机大战的游戏的整体框架搞定了
    shift+f10 执行一下代码,显示为:
image.png

6.接下来我们开始布置背景图(这里用到一个小套路,让背景图在垂直方向上移动,这样就可以让英雄飞机相对运动了)

1.在模块文档那里开始写背景类

class Background(Game_Sprite):
    def __init__(self,is_alt = False):
        super().__init__('./images/background.png')
        if is_alt:
            self.rect.bottom = 0
    def  update(self):
        # 让屏幕往下移动,所以可以用到父类的方法。所以可以继承
        super().update()
        # 判断底部照片是否超出屏幕
        if self.rect.y > SCREEN_RECT.height:
            self.rect.y =-SCREEN_RECT.height

2.回到主程序中的初始化部分那里,开始填写__creat_sprite()私有方法

 def __creat_sprite(self):
        # 创造背景精灵和精灵组
        bg1 = Background()
        bg2 = Background(True)
        self.bg_group = pygame.sprite.Group(bg1,bg2)

3.回到主程序中游戏开始部分那里,self.__blit_photo() 图像绘制更新那里

    def __blit_photo(self):
        # 背景图片的绘制
        self.bg_group.update()
        self.bg_group.draw(self.screen)

shift+f10 运行的效果是一向下移动的背景图

7.为了方便后面测试程序,我们在这里就开始写事件监听的代码,一旦检测到退出的信号就直接退出

    def __event_monitor(self):
        for event in pygame.event.get():
            # 判断监听是否有退出动作
            if event.type == pygame.QUIT:
                PlaneGmae. __game_over()
  • 注意静态方法的调用是直接类名.方法名

8.敌机的类的填写以及精灵类和精灵组的填写(由于敌机较多,要用到定时器)

class Enemy(Game_Sprite):
    def __init__(self):
        super().__init__('./images/enemy1')
        # 敌机初始化位置
        # 1.x轴上的随机位置
        Max_x = SCREEN_RECT.width-self.rect.width
        self.rect.x = random.randint(0,Max_x)
        # 2.y轴上的随机位置
        self.rect.bottom = 0
        # 初始速度的设置
        self.speed = random.randint(1,3)
    def update(self):
        # 继承父类的update让敌机向下移动
        super().update()
        # 判断敌机是否超出屏幕
        if self.rect.y > SCREEN_RECT.height:
            self.kill()
    def __del__(self):
        print('敌机挂了%s' % self.rect)

1.敌机定时器的三步骤:
a.在模块文件中写出定时器常量 eg:XXX = pygame.USEREVENT
b.在主程序的初始化中

pygame.time.set_timer(CREAT_TIMER,1000)

其中1000指的1000毫秒也就是1秒执行一个定时器的动作
c.在事件监听里

            elif event.type == CREAT_TIMER:
                print('产生敌机...')

那样就可以1秒一个敌机出现
2.开始在初始化位置创建精灵组

# 创建敌机精灵组
       self.enemy_group = pygame.sprite.Group()

3.在事件监听那里去写精灵组,因为这是持续不断的要精灵组的

 elif event.type == CREAT_TIMER:
                print('产生敌机...')
                # 敌机精灵
                enemy = Enemy()

                # 敌机精灵组
                self.enemy_group.add(enemy)

4.将敌机精灵组进行绘制

 # 敌机的绘制
        self.enemy_group.update()
        self.enemy_group.draw(self.screen)
  • 此时屏幕开始持续出现敌机


    image.png

9.开始英雄的类已经精灵的布置

class Hero(Game_Sprite):
    # 继承父类,设置imgae和speed
    def __init__(self):
        super().__init__('./images/me1.png',0)
        # 确定好英雄的初始位置
        self.rect.centerx = SCREEN_RECT.centerx
        self.rect.bottom = SCREEN_RECT.bottom-120
  • 在创建精灵的私有方法里开始创建英雄的精灵和精灵组
# 创建英雄精灵和精灵组
       self. hero_sprite = Hero()  #此对象要在其他方法被调用所以加self
        self.hero_sprite_group = pygame.sprite.Group(hero_sprite)
  • 绘制图像
 # 英雄的绘制
        self.hero_sprite_group.update()
        self.hero_sprite_group.draw(self.screen)
  • shift + f10


    image.png

10.开始让飞机在左右移动但是不能超出左右边界

  • 1.使用键盘按键获取按键元组
# 使用键盘方法获取按键元组
        keys_pressed = pygame.key.get_pressed()
        # 判断元组中对应按键索引值
        if keys_pressed[pygame.K_RIGHT]:
            self.hero_sprite.speed = 2
        elif keys_pressed[pygame.K_LEFT]:
            self.hero_sprite.speed = -2
        else:
            self.hero_sprite.speed = 0
  • 这个按键元组的value值是1时键值就是左右的一种

  • 此时的Hero类

class Hero(Game_Sprite):
    # 继承父类,设置imgae和speed
    def __init__(self):
        super().__init__('./images/me1.png',0)
        # 确定好英雄的初始位置
        self.rect.centerx = SCREEN_RECT.centerx
        self.rect.bottom = SCREEN_RECT.bottom-120
    def update(self):
        # 因为是左右移动,所以可以完全改写父类方法
        self.rect.x += self.speed

        # 判断英雄飞机是否飞出屏幕外
        if self.rect.x < 0:
            self.rect.x = 0
        elif self.rect.x > SCREEN_RECT.width-self.rect.width:
            self.rect.right = SCREEN_RECT.right
  • 此时的效果为,英雄可以左右移动但不会超出边界


    image.png

11.开始设置子弹

  • 1.设置子弹的类
class Bullet(Game_Sprite):
    def __init__(self):
        # 继承父类,加载图片
        super().__init__('./images/bullet1.png',-2)
        # 初始位置先不要管,等到英雄类里再去弄
    def update(self):
        # 继承父类方法,让子弹移动
        super().update()

        # 判断子弹是否超出屏幕
        if self.rect.bottom < 0:
            self.kill()
    def __del__(self):
        print('超出子弹被销毁%s'%self.rect)

注意下,这里不要设置子弹的初始位置,因为子弹的初始位置是要和英雄一起弄得

  • 2.设置子弹的定时器
# 子弹常量
HERO_FIRE = pygame.USEREVENT+1
 # 5. 发射子弹的定时器调用
        pygame.time.set_timer(HERO_FIRE,500)
 elif event.type ==  HERO_FIRE:
                self.hero_sprite.fire()

考虑到子弹是要和英雄一起弄的,我们把创建子弹精灵和精灵组放到英雄类中去

    1. 在英雄的类初始化方法里设置子弹精灵组
class Hero(Game_Sprite):
    # 继承父类,设置imgae和speed
    def __init__(self):
        super().__init__('./images/me1.png',0)
        # 确定好英雄的初始位置
        self.rect.centerx = SCREEN_RECT.centerx
        self.rect.bottom = SCREEN_RECT.bottom-120

        # 创建子弹精灵组
        self.bullets = pygame.sprite.Group()
  • 4 .开始设置在英雄类里设置fire()方法
            elif event.type ==  HERO_FIRE:
                self.hero_sprite.fire()
def fire(self):
      print('发射子弹...')
      for i in range(3):
          # 创建子弹精灵
          bullet = Bullet()
          # 设置子弹的初始位置
          bullet.rect.bottom = self.rect.y- i*20
          bullet.rect.centerx = self.rect.centerx
          # 设置子弹的精灵组
          self.bullets.add(bullet)
  • 5 .开始将子弹精灵组放到绘制图像的方法里
 # 子弹的绘制
        self.hero_sprite.bullets.update()
        self.hero_sprite.bullets.draw(self.screen)

呈现的效果为


image.png

12.开始碰撞检测

 def __check_collide(self):
        # 子弹碰到飞机
        pygame.sprite.groupcollide(self.hero_sprite.bullets,self.enemy_group,True,True)
        # 敌机撞毁飞机
        enemies = pygame.sprite.spritecollide(self.hero_sprite, self.enemy_group, True)
        # 判断列表是否有内容
        if len(enemies) > 0:
            # 让英雄牺牲
            self.hero_sprite.kill()

            # 结束游戏
            PlaneGmae.__game_over()

shift +f10


image.png

碰撞的基础知识

image.png

image.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,905评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,140评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,791评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,483评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,476评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,516评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,905评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,560评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,778评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,557评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,635评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,338评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,925评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,898评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,142评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,818评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,347评论 2 342

推荐阅读更多精彩内容