项目实列:飞机大战上(了解pygame)

目录

关于pygame:

关于SDL:

pygame的简单使用:

1.pygame的初始化和退出:

2.pygame中的坐标系:

3.绘制屏幕:(创建游戏窗口)

加载图像:

让游戏动起来:(游戏循环、游戏时钟)

精灵图跟精灵组:

事件监听:


关于pygame:

Pygame是跨平台Python模块,专为电子游戏设计,包含图像、声音。建立在SDL基础上,允许实时电子游戏研发而无需被低级语言束缚。(百度百科)

 

关于SDL:

SDL(Simple DirectMedia Layer)是一套开放源代码的跨平台多媒体开发库,使用C语言写成。SDL提供了数种控制图像、声音、输出入的函数,让开发者只要用相同或是相似的代码就可以开发出跨多个平台(Linux、Windows、Mac OS X等)的应用软件。目前SDL多用于开发游戏、模拟器、媒体播放器等多媒体应用领域。

 

 

pygame的简单使用:

主要了解一下功能:

 

 

 

1.pygame的初始化和退出:

简单的代码演示:

import pygame
import time


def game():
    print("游戏开始了")
    # 等待2s
    time.sleep(2)
    print("游戏结束了")


def main():
    # 使用pygame,需要初始化所有pygame模块
    pygame.init()

    # 调用游戏代码部分
    game()
    # 游戏退出时,卸载所有的pygame模块
    pygame.quit()


if __name__ == "__main__":
    main()

 

2.pygame中的坐标系:

pygame.Rect() :提供了很多方位信息

比如:

上面的长和宽对应的数字反过来了。

简单的代码演示:

def draw_rec():
    # 4个参数分别为 x , y, 宽, 长
    obj_position = pygame.Rect(50, 60, 100, 200)
    print(obj_position)
    obj_pos_list = list()
    obj_pos_list.append(obj_position.x)
    obj_pos_list.append(obj_position.y)
    obj_pos_list.append(obj_position.height)
    obj_pos_list.append(obj_position.width)
    for info_pos in obj_pos_list:
        print(info_pos)

 

3.绘制屏幕:(创建游戏窗口)

ygame 专门提供了一个 模块 pygame.display 用于创建、管理 游戏窗口

 

方法说明
pygame.display.set_mode()初始化游戏显示窗口
pygame.display.update()相当于刷新屏幕

set_mode 方法

set_mode(resolution=(0,0), flags=0, depth=0) -> Surface
  • 作用 —— 创建游戏显示窗口

  • 参数

    • resolution 指定屏幕的 ,默认创建的窗口大小和屏幕大小一致

    • flags 参数指定屏幕的附加选项,例如是否全屏等等,默认不需要传递

    • depth 参数表示颜色的位数,默认自动匹配

 

set_mode()方法的演示:

写了这个函数后,放在上面的game函数中,然后运行main函数:就会看到如下结果:

会出现一个pygame widows,尺寸的大小就是自己设置的参数。可以发现,这只是一个黑黑的窗口而已

为了是窗口能被我们清楚的看到,我在绘制完窗口后停留了20s,实际的应用中是将其设置为无限循环,然后在监听发生了什么时间之后

关闭窗口,也就是结束游戏

 

在创建好了窗口后,我们可以将我们的图片加载到窗口中

加载图像:

  1. 使用 pygame.image.load() 加载图像的数据

  2. 使用 游戏屏幕 对象,调用 blit 方法 将图像绘制到指定位置

  3. 调用 pygame.display.update() 方法更新整个屏幕的显示

 

绘制屏幕背景代码演示:

(需要图片等素材的朋友可以在下方留下邮箱)

首先在当前文件夹下准备好背景图片(图片的大小为480*700 ,所以我将创建的屏幕修改了)

代码部分有点模糊,我将代码在写一边:

def make_screen():
    # 宽480 长700
    screen = pygame.display.set_mode((480, 700))

    # 加载图片 ,并将图片保存起来
    bg = pygame.image.load("./images/background.png")

    # 将加载的图片绘制在屏幕上, 第一个参数是需要加载的图片,第二个是元组 表示从哪个点开始加载。
    screen.blit(bg, (0, 0))

    # 最后在更新屏幕,这样才能显示图像
    pygame.display.update()

    time.sleep(20)

 

让游戏动起来:(游戏循环、游戏时钟)

实现原理:只要我们在足够短的时间内,更新足够多的图片,比如果,一个飞机它会向上移的效果。只要我们在1s中内绘制60张图片,每张图片使飞机的位置向上移动的一个像素,在人的视觉下就会产生动画的效果。(就是所谓的帧率啦)

 

那我们如何才能设置这个所谓的帧率呢?

pygame中提供了工具:

  • pygame.time.Clock 可以非常方便的设置屏幕绘制速度 —— 刷新帧率

  • 要使用 时钟对象 需要两步:

    • 1)在 游戏初始化 创建一个 时钟对象

    • 2)在 游戏循环 中让时钟对象调用 tick(帧率) 方法

  • tick 方法会根据 上次被调用的时间,自动设置 游戏循环 中的延时

 

代码演示:

def test_frame_rate():
    t_start = time.time()
    clock = pygame.time.Clock()
    a = 0
    while True:
        clock.tick(60)
        a += 1
        if a == 600:
            break
    t_over = time.time()
    print("使用始终后所使用的时间为:", t_over-t_start)

    t_start_next = time.time()
    b = 0
    while True:
        b += 1
        if b == 60000:
            break
    t_over_next = time.time()
    print("正常时间为:", t_over_next-t_start_next)

测试结果为:(设置后就相当于, clock.tick(60)这哥们让cpu在1s中内经过它60次)

 

有了上面的基础。

我们可以做如下演示:

1.建一个屏幕

2.绘制背景图片

3.在背景下,绘制一个英雄飞机

4.在没有任何操作的情况下,让飞机向上移动

主要代码如下:

def make_screen():
    # 宽480 长700
    screen = pygame.display.set_mode((480, 700))

    # 加载图片 ,并将图片保存起来
    bg = pygame.image.load("./images/background.png")

    # 将加载的图片绘制在屏幕上, 第一个参数是需要加载的图片,第二个是元组 表示从哪个点开始加载。
    screen.blit(bg, (0, 0))

    # 定义英雄的位置,并加载出英雄的位置
    hero_position = pygame.Rect(180, 500, 102, 126)
    hero_plane = pygame.image.load("./images/me1.png")
    screen.blit(hero_plane, hero_position)

    # 最后在更新屏幕,这样才能显示图像
    pygame.display.update()

    while True:
        clock = pygame.time.Clock()
        clock.tick(60)
        # 如果位置到了屏幕的顶端, 就不能在上去了
        if hero_position.y != 0:
            # 修改英雄的位置
            hero_position.y -= 1

        # 在绘制背景
        screen.blit(bg, (0, 0))

        # 绘制更新后的英雄
        screen.blit(hero_plane, hero_position)

        # 更新屏幕
        pygame.display.update()

如果只更新英雄位置,不更新背景位置会出现这样的现象:

如果下面先更新飞机,后更新背景:

飞机就会看不到。背景将飞机给覆盖掉了。

所以先更新背景,然后在背景的上面绘制飞机。

 

精灵图跟精灵组:

为了简化开发步骤,pygame 提供了两个类

  • pygame.sprite.Sprite —— 存储 图像数据 image位置 rect对象

  • pygame.sprite.Group

 

换句话来理解精灵与精灵组,就差不多使类与对象的的关系。

创建需要的各种类,就是精灵组,比如敌人的飞机。然后有很多实例,就是精灵。将各个精灵添加到精灵组中。将他们一起更新,保存他们所有的位置信息。这样比较方便

 

精灵

  • 在游戏开发中,通常把 显示图像的对象 叫做精灵 Sprite

  • 精灵 需要 有 两个重要的属性

    • image 要显示的图像

    • rect 图像要显示在屏幕的位置

  • 默认的 update() 方法什么事情也没做

    • 子类可以重写此方法,在每次刷新屏幕时,更新精灵位置

  • 注意pygame.sprite.Sprite 并没有提供 imagerect 两个属性

    • 需要程序员从 pygame.sprite.Sprite 派生子类

    • 并在 子类初始化方法 中,设置 imagerect 属性

精灵组

  • 一个 精灵组 可以包含多个 精灵 对象

  • 调用 精灵组 对象的 update() 方法

    • 可以 自动 调用 组内每一个精灵update() 方法

  • 调用 精灵组 对象的 draw(屏幕对象) 方法

    • 可以将 组内每一个精灵image 绘制在 rect 位置

 

代码演示:

首先派生精灵子类:

import pygame


class InSprites(pygame.sprite.Sprite):
    def __init__(self, image_name, speed=1):
        super().__init__()

        # 加载图像
        self.image = pygame.image.load(image_name)

        # 设置尺寸
        # image 的 get_rect() 方法,可以返回 pygame.Rect(0, 0, 图像宽, 图像高) 的对象
        self.rect = self.image.get_rect()

        # 记录速度
        self.speed = speed

    def update(self):
        self.rect.y += self.speed

 

然后在使用这个精灵子类:

主要代码如下:

def make_screen():
    # 宽480 长700
    screen = pygame.display.set_mode((480, 700))

    # 加载图片 ,并将图片保存起来
    bg = pygame.image.load("./images/background.png")

    # 将加载的图片绘制在屏幕上, 第一个参数是需要加载的图片,第二个是元组 表示从哪个点开始加载。
    screen.blit(bg, (0, 0))

    # 定义英雄的位置,并加载出英雄的位置
    """
    hero_position = pygame.Rect(180, 500, 102, 126)
    hero_plane = pygame.image.load("./images/me1.png")
    screen.blit(hero_plane, hero_position)
    """
    # 最后在更新屏幕,这样才能显示图像
    pygame.display.update()

    # 创建两个敌机精灵

    enemy1 = note_sprites.InSprites("./images/enemy1.png", 2)
    enemy2 = note_sprites.InSprites("./images/enemy2.png")

    # 为了使出现的时候时候不重叠,将其中的一驾飞机的x改变

    enemy1.rect.x = 200

    # 将精灵加入精灵组
    enemy_group = pygame.sprite.Group(enemy1, enemy2)

    while True:
        # 调用update方法,让精灵组中的所有精灵自动的调用update方法
        enemy_group.update()
        screen.blit(bg, (0, 0))
        enemy_group.draw(screen)

        pygame.display.update()

 

事件监听:

事件 event

  • 就是游戏启动后,用户针对游戏所做的操作

  • 例如:点击关闭按钮点击鼠标按下键盘...

监听

  • 游戏循环 中,判断用户 具体的操作

只有 捕获 到用户具体的操作,才能有针对性的做出响应

代码实现

  • pygame 中通过 pygame.event.get() 可以获得 用户当前所做动作事件列表

    • 用户可以同一时间做很多事情

主要代码:

for event in pygame.event.get():
            print(event)  # 打印监听到的事件
            # 判断用户是否点击了关闭按钮
            if event.type == pygame.QUIT:
                print("退出游戏...")

                pygame.quit()

                # 直接退出系统
                exit()

在窗口上有一些鼠标上的移动, 或者其他动作都会被捕捉到

按下关闭,就会退出游戏

 

 

 

 

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值