Python 中的 pygame 模块 的简单使用

一、pygame的安装

pygame 是一个Python模块,专为电子游戏设计

官方网站: https://www.pygame.org

1.安装pygame

# 在windows的命令行或是linux的命令行执行均可
pip3 install pygame

Python 中的 pygame 模块 的简单使用_第1张图片

2.验证

python -m pygame.examples.aliens

Python 中的 pygame 模块 的简单使用_第2张图片

 

二、pygame快速入门

项目准备:

1.新建飞机大战项目

2.新建一个hym_01_pygame入门.py

3.导入游戏素材图片

 

游戏的第一印象:

1.把一些静止的图像绘制到游戏窗口中

2.根据用户的交互或其他情况,移动这些图像,产生动画效果

3.根据图像之间是否发生重叠,判断敌机是否被摧毁等其他情况

 

01.使用pygame创建图形窗口

 

1.理解游戏中的坐标系

坐标系:原点在左上角 ( 0 , 0 );x轴水平方向向右,逐渐增加;y轴垂直方向向下,逐渐增加;

Python 中的 pygame 模块 的简单使用_第3张图片

● 在游戏中,所有可见的元素都是以矩形区域来描述位置的;

● 要描述一个矩形区域有4个要素:(x,y) (width,height)

● pygame专门提供了一个类 pygame.Rect 用于 描述矩形区域

Rect(x,y,width,height)                #描述矩形区域

坐标原点: (x,y)
宽度:width 高度:height
注意: size 返回的是一个元组 (width,height)

案例演练:

1.定义hero_rect矩形 描述 英雄的位置和大小

2.输出英雄的坐标原点(x和y)

3.输出英雄的尺寸(宽度 和 高度)

import pygame

hero_rect = pygame.Rect(100,500,120,125)

print("英雄的原点为(%d,%d)" %(hero_rect.x,hero_rect.y))
print("英雄的尺寸:宽为%d 高为%d" %(hero_rect.width,hero_rect.height))
print("英雄的尺寸:宽为%d 高为%d" %(hero_rect.size))
print(hero_rect.size)

Python 中的 pygame 模块 的简单使用_第4张图片

2.创建游戏主窗口

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

pygame.display.set_mode()    #初始化游戏显示窗口
pygame.dispaly.update()      #刷新屏幕内容显示,稍后使用

set_mode方法:

set_mode(resolution=(0,0),flags=0,depth=0)   #创建游戏显示窗口

参数解释:
resolution:指定屏幕的宽和高,默认创建的窗口大小和屏幕大小一致
flags:参数指定屏幕的附加选项,例如:是否全屏等,默认不需要传递
depth:参数表示颜色的位数,默认自动匹配

注意:必须使用变量记录set_mode方法的返回结果,因为后续所有的图像绘制都基于这个返回结果

3.简单的游戏循环

为了做到游戏程序启动后,不会立即退出,通常会在游戏程序中增加一个游戏循环;所谓游戏循环就是一个无限循环

import pygame

# 初始化pygame
pygame.init()

# 创建游戏的窗口  350 * 573(宽,高);注意:此窗口的大小是依据游戏的背景图片而设定的
screen=pygame.display.set_mode((350,573))

# 游戏循环
while True:
    pass

# 退出pygame
pygame.quit()

02.图像绘制

在游戏中,能够看到的元素大多都是图像;图像文件初始是保存在磁盘上的,如果需要使用,首先需要被加载到内存

要在屏幕上看到某一个图像的内容,需要以下三个步骤:

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

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

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

 

代码演练:

(1).绘制背景图像

1.加载 background.png 创建背景

2.将背景绘制在屏幕的 (0,0) 位置

3.调用屏幕更新显示背景图像

import pygame

# 初始化pygame
pygame.init()

# 创建游戏的窗口  350 * 573(宽,高)
screen=pygame.display.set_mode((350,573))

## 绘制背景图像

# 1.加载图像数据
bg = pygame.image.load("./images/background.png")
# 2.绘制图像 blit(图像,位置);
screen.blit(bg,(0,0))
# 3.更新屏幕显示
pygame.display.update()

# 游戏循环
while True:
    pass

# 退出pygame
pygame.quit()

Python 中的 pygame 模块 的简单使用_第5张图片

 

(2).绘制英雄图像

1.加载me1.png 创建英雄飞机

2.将英雄飞机绘制在屏幕的(200,500)位置

3.调用屏幕更新显示飞机图像

 

透明图像:(可以用ps制作)

png格式的图像是支持透明的,在绘制图像时,透明区域不会显示任何内容,但如果下方已经有内容,会透过透明区域显示出来

import pygame

# 初始化pygame
pygame.init()

# 创建游戏的窗口  350 * 573(宽,高)
screen=pygame.display.set_mode((350,573))

# 绘制背景图像

# 1.加载图像数据
bg = pygame.image.load("./images/background.png")
# 2.绘制图像
screen.blit(bg,(0,0))
# 3.更新屏幕显示
pygame.display.update()

## 绘制英雄图像

# 1.加载图像数据
hero = pygame.image.load("./images/me1.png")
# 2.绘制图像
screen.blit(hero,(140,450))
# 3.更新屏幕显示
pygame.display.update()

# 游戏循环
while True:
    pass

# 退出pygame
pygame.quit()

Python 中的 pygame 模块 的简单使用_第6张图片

update方法:

可以在screen对象完成所有blit方法之后,调用一次display.update方法,同样可以在屏幕上看到最终的绘制结果

● 使用display.set_mode()方法创建的screen对象时一个内存中的屏幕数据对象,可以理解为油画的画布;

● screen.blit方法可以在画布上绘制很多的图像,例如:英雄、敌机、子弹等,这些图像有可能会彼此重叠或覆盖;

● display.update()会将画布的最终结果绘制在屏幕上,这样可以提高屏幕绘制效率,增加游戏的流畅度;

import pygame

# 初始化pygame
pygame.init()

# 创建游戏的窗口  350 * 573(宽,高)
screen=pygame.display.set_mode((350,573))

# 绘制背景图像

# 1.加载图像数据
bg = pygame.image.load("./images/background.png")
# 2.绘制图像
screen.blit(bg,(0,0))

# 绘制英雄图像

# 1.加载图像数据
hero = pygame.image.load("./images/me1.png")
# 2.绘制图像
screen.blit(hero,(140,450))

## 在所有绘制工作完成之后,统一调用update方法:更新屏幕显示
pygame.display.update()

# 游戏循环
while True:
    pass

# 退出pygame
pygame.quit()

03.游戏循环和游戏时钟

现在英雄飞机已经被绘制到屏幕上,那么如何让飞机移动呢?

 

1.游戏中的动画实现原理

● 跟电影的原理类似,游戏中的动画效果,本质上是快速的在屏幕上绘制图像;

● 一般在电脑上每秒绘制60次,就能够到达非常连续高品质的动画效果,每次绘制的结果被称为帧;

 

2.游戏循环

游戏的两个组成部分:

Python 中的 pygame 模块 的简单使用_第7张图片

游戏循环的作用:

(1).保证游戏不会直接退出

(2).变化图像位置---动画效果

   ● 每隔 1/60 秒 移动以下所有图像的位置 

   ● 调用 pygame.display.update() 更新屏幕显示

(3).检测用户交互---按键、鼠标等.....

 

3.游戏时钟

pygame专门提供了一个类 pygame.time.clock 可以非常方便的设置屏幕绘制速度---刷新帧率;

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

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

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

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

import pygame

# 初始化pygame
pygame.init()

# 创建游戏的窗口  350 * 573(宽,高)
screen=pygame.display.set_mode((350,573))

# 绘制背景图像

# 1.加载图像数据
bg = pygame.image.load("./images/background.png")
# 2.绘制图像
screen.blit(bg,(0,0))


# 绘制英雄图像

# 1.加载图像数据
hero = pygame.image.load("./images/me1.png")
# 2.绘制图像
screen.blit(hero,(140,450))

# 在所有绘制工作完成之后,统一调用update方法:更新屏幕显示
pygame.display.update()

## 创建时钟对象
clock = pygame.time.Clock()

## 游戏循环:意味着游戏的正式开始!
## 无限循环执行的太快,要想达到良好动画效果,只需每秒执行60次即可
i = 0
while True:
    # 指定循环体内部的代码执行的频率;每秒执行60次
    clock.tick(60)
    # 输出i只是为了测试
    print(i)
    i += 1

# 退出pygame
pygame.quit()

4.英雄的简单动画实现

需求:

1.在游戏初始化定义一个 pygame.Rect 的变量记录英雄的初始位置

2.在游戏循环中每次让英雄的 y-1(向上移动)

3.y<=0 将英雄移到屏幕的底部

注意:每一次调用 update() 方法之前,需要把所有的游戏图像都重新绘制一遍,且应该最先绘制背景图像;

import pygame

# 初始化pygame
pygame.init()

# 创建游戏的窗口  350 * 573(宽,高)
screen=pygame.display.set_mode((350,573))

# 绘制背景图像

# 1.加载图像数据
bg = pygame.image.load("./images/background.png")
# 2.绘制图像
screen.blit(bg,(0,0))

# 绘制英雄图像

# 1.加载图像数据
hero = pygame.image.load("./images/me1.png")
# 2.绘制图像
screen.blit(hero,(140,450))

# 在所有绘制工作完成之后,统一调用update方法:更新屏幕显示
pygame.display.update()

# 创建时钟对象
clock = pygame.time.Clock()

# 1.定义rect记录飞机的初始位置 (x,y,宽,高)
hero_rect = pygame.Rect(140,450,80,78)

# 游戏循环:意味着游戏的正式开始!
while True:
    # 指定循环体内部的代码执行的频率;之所以将频率设置为1,只是为了观察图像变换
    clock.tick(1)
    # 2.修改飞机的位置
    hero_rect.y -= 30
    # 3.调用blit方法绘制图像
    # 绘制背景图像,防止出现飞机影像!!!
    screen.blit(bg, (0, 0))
    # 绘制英雄图像
    screen.blit(hero,hero_rect)
    # 4.调用update方法更新显示
    pygame.display.update()

# 退出pygame
pygame.quit()

改进:让飞机周而复始的循环飞行,即当飞机的头部飞到屏幕顶部时,让飞机回到屏幕底部继续向上飞行;

import pygame

# 初始化pygame
pygame.init()

# 创建游戏的窗口  350 * 573(宽,高)
screen=pygame.display.set_mode((350,573))

# 绘制背景图像

# 1.加载图像数据
bg = pygame.image.load("./images/background.png")
# 2.绘制图像
screen.blit(bg,(0,0))

# 绘制英雄图像

# 1.加载图像数据
hero = pygame.image.load("./images/me1.png")
# 2.绘制图像
screen.blit(hero,(140,450))

# 在所有绘制工作完成之后,统一调用update方法:更新屏幕显示
pygame.display.update()

# 创建时钟对象
clock = pygame.time.Clock()

# 1.定义rect记录飞机的初始位置 (x,y,width,height)
hero_rect = pygame.Rect(140,450,80,78)

# 游戏循环:意味着游戏的正式开始!
while True:
    # 指定循环体内部的代码执行的频率;
    clock.tick(1)
    # 2.修改飞机的位置
    hero_rect.y -= 1
    ## 判断飞机的位置;573为背景图像的高度
    if hero_rect.y <=0:
        hero_rect.y = 573
    # 3.调用blit方法绘制图像
    # 绘制背景图像,防止出现飞机影像!!!
    screen.blit(bg, (0, 0))
    # 绘制英雄图像
    screen.blit(hero,hero_rect)
    # 4.调用update方法更新显示
    pygame.display.update()

# 退出pygame
pygame.quit()

如果你想实现当飞机的尾部飞到屏幕顶部时,让飞机回到屏幕底部继续向上飞行;有以下两种方式:

if hero_rect.y <= -450:
    hero_rect.y = 573
if hero_rect.y + hero_rect.height <= 0:
    hero_rect.y = 573

5.在游戏循环中中的监听事件

事件:就是游戏启动后,用户针对游戏所作的操作;例如:点击关闭按钮,点击鼠标,按上下键等...

监听:在游戏循环中,判断用户具体的操作;只有捕获到用户具体的此操作才能针对性的做出响应;

 

代码实现:

pygame 中通过 pygame.event.get() 可以获得 用户当前所作的动作的时间列表;用户可以在同一时间做很多事情

# 捕获事件
event_list = pygame.event.get()
# 添加判断;仅当用户对游戏有操作时才输出事件列表
if len(event_list) > 0:
    print(event_list)
import pygame

# 初始化pygame
pygame.init()

# 创建游戏的窗口  350 * 573(宽,高)
screen=pygame.display.set_mode((350,573))

# 绘制背景图像

# 1.加载图像数据
bg = pygame.image.load("./images/background.png")
# 2.绘制图像
screen.blit(bg,(0,0))

# 绘制英雄图像

# 1.加载图像数据
hero = pygame.image.load("./images/me1.png")
# 2.绘制图像
screen.blit(hero,(140,450))

# 在所有绘制工作完成之后,统一调用update方法:更新屏幕显示
pygame.display.update()

# 创建时钟对象
clock = pygame.time.Clock()

# 1.定义rect记录飞机的初始位置 (x,y,width,height)
hero_rect = pygame.Rect(140,450,80,78)

# 游戏循环:意味着游戏的正式开始!
while True:
    # 指定循环体内部的代码执行的频率;
    clock.tick(1)

    ## 捕获事件
    event_list = pygame.event.get()
    # 添加判断;仅当用户对游戏有操作时才输出事件列表
    if len(event_list) > 0:
        print(event_list)

    # 2.修改飞机的位置
    hero_rect.y -= 40
    # 判断飞机的位置
    if hero_rect.y + hero_rect.height <= 0:
        hero_rect.y = 573
    # 3.调用blit方法绘制图像
    # 绘制背景图像,防止出现飞机影像!!!
    screen.blit(bg, (0, 0))
    # 绘制英雄图像
    screen.blit(hero,hero_rect)
    # 4.调用update方法更新显示
    pygame.display.update()

# 退出pygame
pygame.quit()

当你对游戏界面执行操作时,事件便会捕获到操作,但不会执行;比如鼠标点击关闭按钮,事件便会捕获到Qiut,但不会退出。

Python 中的 pygame 模块 的简单使用_第8张图片  

捕获并执行退出事件:

# 监听退出事件
# 遍历捕获的所有事件,pygame.event.get():捕获事件,数据类型为列表;
for event in pygame.event.get():
    # 判断事件类型是否为退出事件
    if event.type == pygame.QUIT:
        print("游戏退出...")
        # 卸载所有模块,退出pygame
        pygame.quit()
        # 退出系统,即终止当前正在执行的程序
        exit()
import pygame

# 初始化pygame
pygame.init()

# 创建游戏的窗口  350 * 573(宽,高)
screen=pygame.display.set_mode((350,573))

# 绘制背景图像

# 1.加载图像数据
bg = pygame.image.load("./images/background.png")
# 2.绘制图像
screen.blit(bg,(0,0))

# 绘制英雄图像

# 1.加载图像数据
hero = pygame.image.load("./images/me1.png")
# 2.绘制图像
screen.blit(hero,(140,450))

# 在所有绘制工作完成之后,统一调用update方法:更新屏幕显示
pygame.display.update()

# 创建时钟对象
clock = pygame.time.Clock()

# 1.定义rect记录飞机的初始位置 (x,y,width,height)
hero_rect = pygame.Rect(140,450,80,78)

# 游戏循环:意味着游戏的正式开始!
while True:
    # 指定循环体内部的代码执行的频率;
    clock.tick(1)

    ## 监听退出事件
    # 遍历捕获的所有事件,pygame.event.get():捕获事件,数据类型为列表;
    for event in pygame.event.get():
        # 判断事件类型是否为退出事件
        if event.type == pygame.QUIT:
            print("游戏退出...")
            # 卸载所有模块,退出pygame
            pygame.quit()
            # 退出系统,即终止当前正在执行的程序
            exit()

    # 2.修改飞机的位置
    hero_rect.y -= 40
    # 判断飞机的位置
    if hero_rect.y + hero_rect.height <= 0:
        hero_rect.y = 573
    # 3.调用blit方法绘制图像
    # 绘制背景图像,防止出现飞机影像!!!
    screen.blit(bg, (0, 0))
    # 绘制英雄图像
    screen.blit(hero,hero_rect)
    # 4.调用update方法更新显示
    pygame.display.update()

# 退出pygame
pygame.quit()

测试发现,当鼠标点击游戏界面的关闭按钮时,游戏退出。

 

04.精灵和精灵组

 

1.基本概念

在刚完成的案例中,我们了解到,游戏的一般步骤。首先,在游戏初始化时加载图像;其次,需要在游戏循环中,针对每一张图像,修改图像位置并重新绘制图像。假设我们的游戏需要处理100张图像,意味着游戏循环内部的代码就会变得非常繁琐。

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

● pygame.sprite.Sprite (精灵)      存储图像数据 image 和 位置 rect 的对象

● pygame.sprite.Group (精灵组)  包含多个精灵的对象

Python 中的 pygame 模块 的简单使用_第9张图片

2.派生精灵子类

明确步骤:

1.新建 plane_sprites.py 文件

2.定义 GameSprite 继承自 pygame.sprite.Sprite( pygame.模块.类)

注意:

(1).如果一个类的父类不是 object

(2).在重写初始化方法时,一定要先 super() 一下父类的 _init_ 方法

(3).保证父类中实现的 _init_ 代码能够被正常执行

 

属性:

● image精灵图形,使用 image_name 加载

● rect 精灵大小,默认使用图像大小

● speed 精灵移动速度,默认为1

方法:

● update 每次更新屏幕时在游戏循环内调用,让精灵的 self,rect.y += self.speed

提示:

● image 的 get_rect() 方法,可以返回 pygame.Rect(0,0,宽,高) 的对象

import pygame
## 导入plane_sprites文件中的所有模块
from plane_sprites import *

# 初始化pygame
pygame.init()

# 创建游戏的窗口  350 * 573(宽,高)
screen=pygame.display.set_mode((350,573))

# 绘制背景图像

# 1.加载图像数据
bg = pygame.image.load("./images/background.png")
# 2.绘制图像
screen.blit(bg,(0,0))

# 绘制英雄图像

# 1.加载图像数据
hero = pygame.image.load("./images/me1.png")
# 2.绘制图像
screen.blit(hero,(140,450))

# 在所有绘制工作完成之后,统一调用update方法:更新屏幕显示
pygame.display.update()

# 创建时钟对象
clock = pygame.time.Clock()

# 1.定义rect记录飞机的初始位置 (x,y,width,height)
hero_rect = pygame.Rect(140,450,80,78)

## 创建敌机的精灵
enemy = GameSprite("./images/enemy1.png")
enemy1 = GameSprite("./images/enemy1.png",2)
## 创建敌机的精灵组
enemy_group = pygame.sprite.Group(enemy,enemy1)


# 游戏循环:意味着游戏的正式开始!
while True:
    # 指定循环体内部的代码执行的频率;
    clock.tick(1)

    # 监听退出事件
    # 遍历捕获的所有事件,pygame.event.get():捕获事件,数据类型为列表;
    for event in pygame.event.get():
        # 判断事件类型是否为退出事件
        if event.type == pygame.QUIT:
            print("游戏退出...")
            # 卸载所有模块,退出pygame
            pygame.quit()
            # 退出系统,即终止当前正在执行的程序
            exit()

    # 2.修改飞机的位置
    hero_rect.y -= 40
    # 判断飞机的位置
    if hero_rect.y + hero_rect.height <= 0:
        hero_rect.y = 573
    # 3.调用blit方法绘制图像
    # 绘制背景图像,防止出现飞机影像!!!
    screen.blit(bg, (0, 0))
    # 绘制英雄图像
    screen.blit(hero,hero_rect)

    ## 精灵组调用两个方法
    # update:让组中的所有精灵更新位置
    enemy_group.update()
    # draw:在screen上绘制所有的精灵
    enemy_group.draw(screen)

    # 4.调用update方法更新显示
    pygame.display.update()

# 退出pygame
pygame.quit()

Python 中的 pygame 模块 的简单使用_第10张图片

你可能感兴趣的:(Python 中的 pygame 模块 的简单使用)