Python进阶篇八Pygame的Event事件模块

Posted deepboat

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python进阶篇八Pygame的Event事件模块相关的知识,希望对你有一定的参考价值。

目录

八、Pygame的Event事件模块

事件(Event)是 Pygame 的重要模块之一,它是构建整个游戏程序的核心,比如常用的鼠标点击、键盘敲击、游戏窗口移动、调整窗口大小、触发特定的情节、退出游戏等,这些都可以看做是“事件”。

8.1 事件类型

Pygame 定义了一个专门用来处理事件的结构,即事件队列,该结构遵循遵循队列“先到先处理”的基本原则,通过事件队列,我们可以有序的、逐一的处理用户的操作(触发事件)。下述表格列出了 Pygame 中常用的游戏事件:

名称说明
QUIT用户按下窗口的关闭按钮
ATIVEEVENTPygame被激活或者隐藏
KEYDOWN键盘按下
KEYUP键盘放开
MOUSEMOTION鼠标移动
MOUSEBUTTONDOWN鼠标按下
MOUSEBUTTONUP鼠标放开
JOYAXISMOTION游戏手柄(Joystick or pad) 移动
JOYBALLMOTION 游戏球(Joy ball) 移动
JOYHATMOTION游戏手柄(Joystick) 移动
JOYBUTTONDOWN游戏手柄按下
JOYBUTTONUP游戏手柄放开
VIDEORESIZEPygame窗口缩放
VIDEOEXPOSEPygame窗口部分公开(expose)
USEREVENT触发一个用户事件

注意,当使用 Pygame 做游戏开发时,上述事件并非都会应用的到,因此在学习的过程中,我们要懂得触类旁通、举一反三。

8.2 事件处理方法

名称说明
pygame.event.get()从事件队列中获取一个事件,并从队列中删除该事件
pygame.event.wait() 阻塞直至事件发生才会继续执行,若没有事件发生将一直处于阻塞状态
pygame.event.set_blocked() 控制哪些事件禁止进入队列,如果参数值为None,则表示禁止所有事件进入
pygame.event.set_allowed()  控制哪些事件允许进入队列
pygame.event.pump() 调用该方法后,Pygame 会自动处理事件队列
pygame.event.poll() 会根据实际情形返回一个真实的事件,或者一个None
pygame.event.peek()  检测某类型事件是否在队列中
pygame.event.clear()从队列中清除所有的事件
pygame.event.get_blocked() 检测某一类型的事件是否被禁止进入队列
pygame.event.post()  放置一个新的事件到队列中
pygame.event.Event()  创建一个用户自定义的新事件

当我们使用 Pygame 处理事件时,逻辑一般都是相似的。首先是判断事件的类型,然后根据不同的事件操作,执行不同的游戏操作。因此这种情况非常适合使用 if … else 语句。如下所示:

import pygame

while True:
    # 等待事件发生
    event = pygame.event.wait()
    if event.type == pygame.QUIT:
        exit()
    if event.type == pygame.MOUSEBUTTONDOWN:
        print('鼠标按下', event.pos)
    if event.type == pygame.MOUSEBUTTONUP:
        print('鼠标弹起')
    if event.type == pygame.MOUSEMOTION:
        print('鼠标移动')
        # 键盘事件
    if event.type == pygame.KEYDOWN:
        # 打印按键的英文字符
        print('键盘按下', chr(event.key))
    if event.type == pygame.KEYUP:
        print('键盘弹起')

8.3 处理键盘事件

键盘事件提供了一个 key 属性,通过该属性可以获取键盘的按键。Pygame 将键盘上的字母键、数字键、组合键等按键以常量的方式进行了定义,下表列出了部分常用按键的常量:

名称说明
K_BACKSPACE退格键(Backspace)
K_TAB制表键(Tab)
K_CLEAR清除键(Clear)
K_RETURN回车键(Enter)
K_PAUSE暂停键(Pause)
K_ESCAPE退出键(Escape)
K_SPACE空格键(Space)
K_0...K_90…9
K_a...Kza…z
K_DELETE删除键(delete)
K_KP0...K_KP90(小键盘)…9(小键盘)
K_F1...K_F15F1…F15
K_UP向上箭头(up arrow)
K_DOWN向下箭头(down arrow)
K_RIGHT向右箭头(right arrow)
K_LEFT向左箭头(left arrow)
KMOD_ALT同时按下Alt键

下面通过“图片移动”示例来了解键盘事件的处理过程,如下所示:

import pygame
import sys

# 初始化pygame
pygame.init()
# 定义变量
size = width, height = 600, 400
bg = (255, 255, 255)
# 加载logo图
img = pygame.image.load("./python.png")
# 获取图像的位置
position = img.get_rect()
# 创建一个主窗口
screen = pygame.display.set_mode(size)
# 标题
pygame.display.set_caption("Python自学网")
# 创建游戏主循环
while True:
    # 设置初始值
    site = [0, 0]
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        # 图像移动 KEYDOWN 键盘按下事件
        # 通过 key 属性对应按键
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_UP:
                site[1] -= 8
            if event.key == pygame.K_DOWN:
                site[1] += 8
            if event.key == pygame.K_LEFT:
                site[0] -= 8
            if event.key == pygame.K_RIGHT:
                site[0] += 8
    # 移动图像
    position = position.move(site)
    # 填充背景
    screen.fill(bg)
    # 放置图片
    screen.blit(img, position)
    # 更新显示界面
    pygame.display.flip()

8.4 处理鼠标事件

Pygame 提供了三个鼠标事件,分别是鼠标移动(MOUSEMOTION)、鼠标按下(MOUSEBUTTONDOWN)、鼠标释放(MOUSEBUTTONUP),不同事件类型对应着不同的成员属性。如下所示:

pygame.event.MOUSEMOTION鼠标移动事件

    event.pos 相对于窗口左上角,鼠标的当前坐标值(x,y)
    event.rel 鼠标相对运动距离(X,Y),相对于上次事件
    event.buttons 鼠标按钮初始状态(0,0,0),分别对应(左键,滑轮,右键),移动过程中点击那个键,相应位置变会为1

pygame.event.MOUSEBUTTONUP鼠标键释放事件

    event.pos 相对于窗口左上角,鼠标的当前坐标值(x,y)
    event.button 鼠标释放键编号(整数)左键为1,按下滚动轮2、右键为3

pygame.event.MOUSEBUTTONDOWN 鼠标键按下事件

    event.pos 相对于窗口左上角,鼠标的当前坐标值(x,y)
    event.button 鼠标按下键编号(整数),左键为1,按下滚动轮2、右键为3,向前滚动滑轮4、向后滚动滑轮5
import pygame
from random import randint

# 初始化程序
pygame.init()
screen = pygame.display.set_mode((450, 400))
pygame.display.set_caption("Python自学网")
# 更新显示
pygame.display.flip()
while True:
    # 等待事件发生
    event = pygame.event.wait()
    if event.type == pygame.QUIT:
        exit("成功退出")
    if event.type == pygame.MOUSEBUTTONDOWN:
        # pos 获取鼠标当前位置
        print('鼠标按下', event.pos)
        mx, my = event.pos
        # 调用 pygame.draw 模块画圆
        pygame.draw.circle(screen, (255, 255, 0), (mx, my), 50)
        # 处理完,更新显示
        pygame.display.update()
    if event.type == pygame.MOUSEBUTTONUP:
        print('鼠标弹起')
        pass
    if event.type == pygame.MOUSEMOTION:
        print('鼠标移动')
        mx, my = event.pos
        # 随机生成 RGB 颜色值
        r = randint(0, 255)
        g = randint(0, 255)
        b = randint(0, 255)
        pygame.draw.circle(screen, (r, g, b,), (mx, my), 50)
        # 处理完,更新显示
        pygame.display.update()

Python进阶篇二Pygame的结构

目录

二、Pygame的结构

2.1 初始化程序

在使用 Pygame 编写程序前,要做的第一个步骤是“初始化程序”,代码如下所示:

pygame.init()

作用:自动检测 Pygame 软件包是否正常可用,并检查电脑的硬件调用接口、基础功能是否存在问题,比如音频、光驱、声卡驱动等设备。同时,它会完成 Pygame 中所有模块的初始化操作。

2.2 创建Surface对象

想要掌握 Pygame 的编程逻辑,首先就要理解 surface 对象的概念,它是 Pygame 中最重要的组成部分。

Pygame 中,您可以把 surface 对象理解成一张“白纸”,通过这张纸可以做许多的事情,比如在纸上添加文字、填充颜色、添加图片以及绘制任意形状的图形等。既然是“纸”就有规格尺寸,Pygame 允许您创建任意大小的纸。

Pygame 提供了多种创建 Surface 对象的方法,这里先介绍以下几种方法。

# 也叫screen对象,本质上是一个Surface,大小400*400
screen = pygame.display.set_mode((400,400))

screen 的本质上就是一个 Surface 对象,它是游戏的主窗口,也就是整个游戏中尺寸最大的“纸”,任何其他的 Surface 对象都需要附着在这张最大的“纸”上,比如创建一个包含文本的 Surface 对象,通过以下方法将它绘制在主屏幕上:

# 创建一个包含文字的Surface对象
text = f.render("Python自学网",True,(255,0,0),(0,0,0))
# 通过blit方法将其绘制在主屏幕上,这里的textRect表示位置坐标
screen.blit(text,textRect)

如果想创建一个包含图像的 surface 对象可以使用如下方法:

surface_image =pygame.image.load("图片路径") 

2.3 事件监听

动画保证了玩家的视觉体验,而人机交互则是操作上的体验。通过移动和点击鼠标、按下键盘上的技能键,或是滑动手机屏幕等操作来实现人机交互,这些与游戏程序交互的操作被称为事件(Event)。

Pygame 作为一个游戏开发库,同样具有设置和监听事件的功能。它提供了一个 event 事件模块,这个模块中包含了所有常用到游戏事件。

# 循环获取事件,监听事件状态,使用get()获取事件
for event in pygame.event.get():
    # 判断事件类型,用户是否点了"X"关闭按钮
    # pygame.QUIT 指点击右上角窗口的"X"号
    if event.type == pygame.QUIT:
        #点击后,卸载所有pygame模块
        pygame.quit()

2.4 游戏循环

当打我们游戏时可能会触发游戏中的各种事件,比如鼠标事件、键盘按键事件、摄像拍照事件等等,因此游戏程序需要一直循环监听玩家的操作,只有当用户点击了游戏“关闭”按钮时,监听才会结束。如果想要达到“循环监听”目的,此时就需要设置一个游戏循环(Game Loop)也称为游戏的主循环,这样才能保证人机交互的体验感。代码示例如下:

#游戏主循环(游戏循环)
while True:
    # 循环获取事件,监听事件
    for event in pygame.event.get():
        # 判断用户是否点了关闭按钮
        if event.type == pygame.QUIT:
            # 当用户关闭游戏窗口时执行以下操作
            # 这里必须调用quit()方法,退出游戏
            pygame.quit()
            #终止系统
            sys.exit()
    #更新并绘制屏幕内容
    pygame.display.flip() 

游戏主循环是每个 Pygame 游戏程序中必不可少的一部分,它主要承担着以下三个重要任务:

  • 处理游戏事件
  • 更新游戏状态
  • 把更新后的游戏状态绘制到屏幕上

游戏画面和游戏操作状态会因为动画效果和玩家的操作而改变,因此需要以循环的方式实时地更新主屏幕(screen)的显示内容。把下列代码放入游戏主循环中即可实现实时更新和绘制屏幕内容,如下所示:

#刷新界面显示
pygame.display.flip() 

除了上述方法外,Pygame 还提供了另一个方法。如下所示:

pygame.display.update() 

这两个方法的主要区别是:后者可以根据选定的区域来更新部分内容,而前者则是更新整个待显示的内容。如果后者没有提供区域位置参数时,其作用和 display.flip() 相同。

以上是关于Python进阶篇八Pygame的Event事件模块的主要内容,如果未能解决你的问题,请参考以下文章

Python进阶篇二Pygame的结构

如何在python中运行另一个程序的python中模拟按键事件

为啥 Python 会在 Pygame 中为“事件”变量抛出未绑定的本地错误? [关闭]

python pygame库入门

Python事件没有Key属性

pygame event.get致命的Python错误:PyEval_RestoreThread:NULL tstate