• 【python 第10日】打飞机的小游戏 pygame


    安装pygame

    • 首先安装pip,  python -m ensurepip --default-pip  或者下载安装包安装
    • 安装完pip,  安装模块可以python -m pip install Packagename 也可以直接pip install PackageName, 在pycharm里也可以直接下载File | Settings | Project: python-learn | Project Interpreter
    • 验证安装, python -m PackageName
      •   python -m PackageName  就相当于加载,并不执行
      •   python PackageName  直接执行

     本地文件路径选择,提示框

    单文件选择

    from  tkinter import Tk
    from tkinter import messagebox
    from tkinter import filedialog

    def get_file_path(msg):
    root = Tk()
    root.withdraw() # 把root隐藏为了防止多一个窗口
    # print(root.winfo_screenwidth()) #获取系统屏幕像素
    # print(root.winfo_screenheight())
    ret = messagebox.showinfo("提示", msg)
    if ret :
    filepath = filedialog.askopenfile()
    return filepath.name
    return ""

    多文件选择

    def get_files_path():
    root = Tk()
    root.withdraw() #把root隐藏为了防止多一个窗口
    ret = messagebox.showinfo("提示", msg)
    if ret:
    filepath = filedialog.askopenfiles()
    file_list = []
    for file in filepath:
    file_list.append(file.name)
    return file_list
    return ""

     打飞机的游戏

    分为三个文件: 

    • 一个是类文件,包含背景类,飞机类, 英雄类,子弹类 都是精灵
    • 一个是屏幕控制,初始化,加载背景,飞机,英雄,子弹自动出,检测碰撞,英雄发射子弹,事件检测
    • 最后一个是配置文件

    有待添加的事情:

    • 背景音乐,爆炸音乐,音乐控制
    • 爆炸效果,加载另外一个图片
    • 设置按键等等
    • 效果优化
    • 多个人play

    屏幕控制

    import os
    import random
    import sys
    
    from hitfeiji.conf.setting import BEIJING_SIZE
    
    sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
    
    import pygame
    from lib.plane_class import *
    from  conf.setting import *
    CREATE_ENEMY = pygame.USEREVENT
    CREATE_ZIDAN = pygame.USEREVENT + 1
    
    class PlaneMain:
        def __init__(self):
            #初始化窗口,背景
            # pygame.init()
            self.screen = pygame.display.set_mode(BEIJING_SIZE)
            #设置标题
            pygame.display.set_caption(GAME_TITLE)
            self.clock = pygame.time.Clock()
            self.__create_sprites()
            pygame.time.set_timer(CREATE_ENEMY, SHUAXIN_PINLV)
            pygame.time.set_timer(CREATE_ZIDAN , ZIDAN_PER)
            print("初始化完毕")
        def __event_handle(self):
    
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    PlaneMain.__game_over()
    
                if event.type == CREATE_ENEMY:
                    tmpfile = random.choice(ENEMY_PATH)
                    enemy = Enemy(tmpfile)
                    self.enemy_group.add(enemy)
                if event.type == CREATE_ZIDAN:
                    self.hero.fire()
    
                #获取键盘信息
                key_pressed = pygame.key.get_pressed()
                if key_pressed[pygame.K_RIGHT]:
                    self.hero.speed = HERO_SPEED
                elif key_pressed[pygame.K_LEFT]:
                    self.hero.speed = -HERO_SPEED
                else:
                    self.hero.speed = 0
    
        def __check_collide(self):
            pygame.sprite.groupcollide(self.hero.bullets, self.enemy_group, True, True)
            #不让死,可以注释掉
            if not WUDI:
                res = pygame.sprite.spritecollide(self.hero, self.enemy_group, True)
                if res :
                    self.__game_over()
    
        def __create_sprites(self):
            length = len(BEIJING_DEFAULT_PATH)
            BEIJING_DEFAULT_PATH_NEW = BEIJING_DEFAULT_PATH
            if length == 1:
                BEIJING_DEFAULT_PATH_NEW = BEIJING_DEFAULT_PATH*2
    
            #t添加背景组
            self.bg_group = pygame.sprite.Group()
            for path in BEIJING_DEFAULT_PATH_NEW :
                bg = BackGroud(path)
                self.bg_group.add(bg)
            print("背景图像加载完毕:",self.bg_group.sprites())
    
            #添加敌人组
            self.enemy_group = pygame.sprite.Group()
    
            #添加英雄组
            self.hero_group = pygame.sprite.Group()
            self.hero = Hero(FEIJI_DEFAULT_PATH)
            self.hero_group.add(self.hero)
    
            #设置字体
            self.font = FontClass("傲雪的游戏", FONT_POSITON, FONT_SIZE)
            self.font_group = pygame.sprite.Group(self.font)
    
        def __update_sprites(self):
            #刷新背景组
            self.bg_group.update()
            self.bg_group.draw(self.screen)
    
            #刷新敌人组
            self.enemy_group.update()
            self.enemy_group.draw(self.screen)
    
            #刷新英雄
            self.hero_group.update()
            self.hero_group.draw(self.screen)
    
            #子弹刷新
            self.hero.bullets.update()
            self.hero.bullets.draw(self.screen)
    
            #字体刷新
            self.font_group.update()
            self.font_group.draw(self.screen)
        @staticmethod
        def __game_over():
            print("游戏结束")
            pygame.quit()
            exit()
    
        def start_game(self):
            print("游戏开始")
    
            while True:
    
                #1设置刷新帧率
                self.clock.tick(FRAME_PER_SEC)
                #2.事件监听
                self.__event_handle()
                #3、碰撞检测
                self.__check_collide()
                #4、更新/监测精灵组
                self.__update_sprites()
                #5、更新显示
                pygame.display.update()
    
    if __name__ == '__main__':
        pygame.init()
        p = PlaneMain()
        p.start_game()

    类文件

    import os
    import random
    import sys
    import pygame
    
    from hitfeiji.conf.setting import ENEMY_SIZE
    
    sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
    
    from  conf.setting import *
    from lib.functions import *
    
    class FontClass(pygame.sprite.Sprite):
            def __init__(self, string, positon, size):
                super().__init__()
                print(self.__dict__)
                myfont = pygame.font.Font(FONT_PATH, size)
                self.image = myfont.render(string, True, FONT_COLOR)
                self.rect = self.image.get_rect()
                self.rect.x = positon[0]
                self.rect.y = positon[1]
    
    
    class GameSprites(pygame.sprite.Sprite):
        def __init__(self, filename, size, speed = 1, ):
            super().__init__()
            self.image = pygame.image.load(filename).convert_alpha()
            self.new_image = pygame.transform.smoothscale(self.image, size)
            self.image = self.new_image               #还是需要的否则图像不会变化
            self.rect = self.new_image.get_rect()
            self.speed = speed
    
        def update(self, *args):
            self.rect.y += self.speed
    
    class BackGroud(GameSprites):
        number = 0
        def __init__(self, filename, speed = 1):
            super().__init__(filename, BEIJING_SIZE, speed)
            self.rect.y = -BackGroud.number * BEIJING_SIZE[1]
            BackGroud.number += 1
    
        def update(self, *args):
            self.rect.y = self.rect.y + self.speed
            if self.rect.y > BEIJING_SIZE[1]:
                self.rect.y = - (BackGroud.number - 1)* BEIJING_SIZE[1]
    
    class Enemy(GameSprites):
        def __init__(self, filename ):
            self.speed = random.randint(1, 4)
            super().__init__(filename, ENEMY_SIZE, self.speed)
            self.rect.x = random.randint(0, BEIJING_SIZE[0]-ENEMY_SIZE[0])
            self.rect.bottom = 0
    
        def update(self):
            super().update()
            if self.rect.y > BEIJING_SIZE[1]:
                self.kill()
    
    class Hero(GameSprites):
        def __init__(self, filename):
            super().__init__(filename, FEIJI_SIZE, 0)
            self.rect.centerx = int(BEIJING_SIZE[1]/2)
            self.rect.y = BEIJING_SIZE[1] - FEIJI_SIZE[1]
            self.bullets = pygame.sprite.Group()
    
        def update(self, *args):
            self.rect.x += self.speed
            if self.rect.x < 0:
                self.rect.x = 0
            elif self.rect.x > BEIJING_SIZE[0]:
                self.rect.x = BEIJING_SIZE[0] - FEIJI_SIZE[0]
        def fire(self):
    
            for i in range(1,2):
                bullet = Bullet(ZIDAN_DEFAULT_PATH)
                bullet.rect.bottom = self.rect.y -20*i
                bullet.rect.centerx = self.rect.centerx
                self.bullets.add(bullet)
    
    class Bullet(GameSprites):
        def __init__(self, filename):
            super().__init__(filename, ZIDAN_SIZE, ZIDAN_SPEED)
            self.rect.x =  1
        def update(self):
            self.rect.y = self.rect.y + ZIDAN_SPEED
            if self.rect.bottom < 0:
                self.kill()
    
    if __name__ == '__main__':
        pass

    第七章 Pygame.sprite

    这个模块包含几个游戏中使用的简单类。最主要的是Sprite类,还有几个容纳SpriteGroup类。是否使用 这些类在Pygame中是可选的。这些类是轻量级的,仅仅提供了一个大部分游戏所共同需要的代码的起点。

    Sprite类是用作游戏中各种类型对象的基类。还有一个Group基类用来简单的容纳sprites。一个游戏可以创 建新的Group类用来操作它们包含的特殊的Sprite对象。

    基本的Sprite类可以把它 包含的Sprite画到Surface上。Group.draw方法需要每个Sprite都有一个Sprite.image属性和一个 Sprite.rect属性。Group.clear方法需要相同的属性,可以用于删除所有的Sprite。还有更高级的 Grouppygame.sprite.RenderUpdates可以跟踪图像脏的部 分(需要更新的部分),pygame.sprite.OrderedUpdates可以以叠加顺序 画Sprites

    最后,这个模块还包含几个碰撞检测函数。这些函数帮助我们找到 多个Group里面的Sprite有哪些是相交的。要找到碰撞,Sprite必须有一个rect属性。

    Sprite类不是线程安全 的。使用多线程时必须自己锁定它们。

    pygame.sprite.Sprite

    pygame.sprite.Sprite(*groups): return Sprite

        Sprite.update - 控制sprite的行为

        Sprite.add - sprite添加到group

        Sprite.remove - spritegroup里面删除

        Sprite.kill - srpite从所有group里面删除

        Sprite.alive - 判断是否有个Group包含这个sprite

    Sprite.groups - 列出所有包含这个SpriteGroup

    表示可见的游戏对象的简单基类。它的派生类需要覆盖Sprite.update方法,并给Sprite.image和 Sprite.rect属性赋值。初始化函数可以带任意个Group对象作为它们的成员。

    当从Sprite派生时,记得在把Sprite添加到组中之前一定要调用基类的初始化函数。

    Sprite.update

    Sprite.update(*args)

    控制sprite行为的方法,这个函数的默认实现什么都不做。

    Sprite.add

    Sprite.add(*groups): return None

    sprite添加到 group里面,参数可以给定任意多个Group对 象。Sprite会被添加到不包含它的Group里面去。

    Sprite.remove

    Sprite.remove(*groups): return None

    sprite从 groups里面删除,可以指定任意多个Group作为参 数。Sprite会从包含它的group里面删除。

    Sprite.kill

    Sprite.kill(): return None

    Sprite从所有的 group里面删除,Sprite会从所有包含它的 Group里面删除。这个函数不会改变Sprite本身的任何状态。这个函数用了以后还可以继续使用这个Sprite对象,包括把它添加到Group里 面。

    Sprite.alive

    Sprite.alive(): return bool

    判断是否有某个Group 包含这个Sprite,如果这个Sprite属于某个组或者多个组,这个函数返回True

    Sprite.groups

    Sprite.groups(): return group_list

    列出包含这个Sprite 的所有Group

    pygame.sprite.Group

    pygame.sprite.Group(*sprites): return Group

        Group.sprites - 列出这个Group包含的所有Sprites

        Group.copy - 复制这个group

        Group.add - Sprite添加到这个group

        Group.remove - Spritegroup里面删除

        Group.has - 判断这个Group是否包含一些Sprites

        Group.update - 调用所有包含的Spriteupdate方法

        Group.draw - Sprite图像画到Surface

        Group.clear - 用背景覆盖掉Sprite

    Group.empty - 删除Group包含的所有Sprite

    包含多个Sprite的容 器类,Sprite对象的简单容器。这个类 可以派生出包含更多特殊功能的类。构造函数可以带任意多个Sprite作为添加到Group里面的对象。Group支持下列标准的Python操作:

              in      判断一个Sprite是否在里面

              len     获取包含的Sprite的个数

              bool    判断这个Group是否包含了Sprite(或者是空的)

              iter    迭代包含的所有的Sprite

    Group包含的Sprite没有 排序,所以画Sprites或者迭代它们是没有一个确定的顺序的。

    Group.sprites

    Group.sprites(): return sprite_list

    列出这个Group包含 的Sprites

    返回这个Group包含的所有 Sprites的列表。你可以从这个group获得一个迭代子,但是你不能够迭代一个Group的同时并修改它。

    Group.copy

    Group.copy(): return Group

    复制Group,创建一个新的Group,包含和原 来的group完全相同的Sprites

    Group.add

    Group.add(*sprites): return None

    Sprites添加到这个Group里面,添加任意多个Sprite到这个 Group中。这个函数只会添加Group里面原来没有的Sprite进来。

    Group.remove

    Group.remove(*sprites): return None

    group中删除 Sprites,删除任意多个 Sprites。这个操作只对Group里面存在的Sprite进行。

    Group.has

    Group.has(*sprites): return None

    判断这个Group是否包含一些Sprites,如果Group包含所有给定的 Sprites,则函数返回True

    Group.update

    Group.update(*args): return None

    在包含的Sprites上调用update,在包含的所有Sprites上调用updateSprite基类有一个可以带任何参数并不作任何事情的update 函数。传给Group.update的参数对每一个Sprite对象。

    Group.draw

    Group.draw(Surface): return None

    Sprite图像复制 到Surface

    把包含的Sprites画到 Surface上去。这个函数用到Sprite.image作为源Surface,并且用到Sprite.rect作为位置。

    Group.clear

    Group.clear(Surface_dest, background): return None

    用背景来覆盖 Sprites

    Group.draw所画的 Sprites擦掉。目标SurfaceSprite的区域会被backgroup上的所填充。

    background通常是一个Surface图像,具有和目标Surface同样的大小。它也可以是回调函数,带两个 参数:目标Surface和清除的区域。background回调函数在一次clear的过程中会被调用多次。

    这是一个回调函数的例子,把Sprites清除为红色:

        def clear_callback(surf, rect):

            color = 255, 0, 0

            surf.fill(color, rect) 

    Group.empty

    Group.empty(): return None

    去除这个Group包含的所有 Sprites

    pygame.sprite.RenderUpdates

    pygame.sprite.RenderUpdates(*sprites): return RenderUpdates

    RenderUpdates.draw - 块复制Sprite图像,并跟踪改变的区域

    它包含一个扩展的draw函数,能够跟踪屏幕上改变的区域。

    RenderUpdates.draw

    RenderUpdates.draw(surface): return Rect_list

    把所有的Sprite画到 surface上,和Group.draw一样。这个函数返回一组矩形,表示屏幕上被改变的区域。返回的改变区域也包括之前被Group.clear影响 的区域。

    返回的Rect列表应该传给 pygame.display.update函数。这有助于提高软件显示模式下的游戏性能。这种更新的方法只在背景不会动的时候有效。

    pygame.sprite.OrderedUpdates

    pygame.sprite.OrderedUpdates(*spites): return OrderedUpdates

    它按照 Sprite添加的顺序,画图的RenderUpdates类。这使得从Group里添加和删除Sprites操作比普通的Group慢一点。

    pygame.sprite.GroupSingle

    pygame.sprite.GroupSingle(sprite=None): return GroupSingle

    GroupSingle仅 包含一个Sprite。当一个新的Sprite添加进去,老的就被删除了。

    pygame.sprite.spritecollide

    pygame.sprite.spritecollide(sprite, group, dokill): return Sprite_list

    在一个Group里面找和另一个Sprite相交的Sprites

    是否相交通过比较Sprite.rect属性来确定。dokill参数是一个布尔型的。如果设置成True,则所有相交的Sprite会从Group里面删除。

    pygame.sprite.groupcollide

    pygame.sprite.groupcollide(group1, group2, dokill1, dokill2): return Sprite_dict

    找到两个Group里面所有相交的Sprites

    这个函数会找到两个group里面 所有相交的Sprites。是否相交通过比较Sprite.rect属性来确定。

    group1里面的每一个Sprite会被添加到返回的字典里面,每一项的值是group2中相交的Sprites的列 表。

    两个dokill参数,哪一个是True,则对应的 Group里面相交的Sprites会被删除。

    pygame.sprite.spritecollideany

    pygame.sprite.spritecollideany(sprite, group): return bool

    简单的测试一个Sprite是否和Group里面的任意一个 Sprite相交

    如果给定的SpriteGroup里面的某个Sprite相交,则返回True。是否相交通过比较 Sprite.rect属性来确定。

    这个碰撞检测比 pygame.sprite.spritecollide更快,因为它要作的事情少一点。

    支付宝     
    您的资助是我最大的动力!
    金额随意,欢迎来赏!
    微信

    如果,您希望更容易地发现我的新博客,不妨点击一下绿色通道的关注我

    如果,想给予我更多的鼓励,求打       付款后有任何问题请给我留言!!!

    ------------------------------------------------------------------------------------------
    作者:【周sir】
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
  • 相关阅读:
    设计tag的sql语句,支持每个tag的个数,Access数据库非msSql
    ulObj ul = new ulObj();
    Access 日期比较用 #扩住日期 代码如下
    dw中IMG标记的正则替换
    许涛的 repeater itemCommand 事件代码(经典代码,不难)
    n1视觉图片列表样式[jquery代码][A标记里面一个IMG一个EM]
    flashbox小组件开发~~开源~~
    动态读取一张图片到mc里,读取txt中的内容 flash as 全站flash专题
    简单的jQueryTab 自写的小代码
    flashCs3 按钮事件没了?原来As3已经改为监听模式了!
  • 原文地址:https://www.cnblogs.com/zhouguanglu/p/10261728.html
Copyright © 2020-2023  润新知