当前位置: 首页 > news >正文

pygame的帧处理中,涉及键盘的有`pg.event.get()`与`pg.key.get_pressed()` ,二者有什么区别与联系?

一、pg.event.get() 返回的是一组事件

pg.event.get() 返回的是一组事件(一个包含多个事件对象的列表)。这是因为在游戏的“一帧”时间内(通常1/60秒左右),用户可能会触发多个事件(比如同时按下多个键、快速移动鼠标并点击等),这些事件会被 Pygame 暂时存储在“事件队列”中,而 pg.event.get() 的作用就是一次性取出队列中所有未处理的事件,形成一个列表(即“一组事件”)。

为什么是“一组”事件?

Pygame 内部维护了一个事件队列(event queue),所有用户交互(如键盘、鼠标操作)和系统事件(如窗口大小变化)都会按发生顺序被加入队列。
在游戏主循环中,每帧(while running 循环的一次迭代)会调用 pg.event.get(),此时可能有多个事件堆积在队列中(例如:用户在这一帧内既按了方向键,又点击了鼠标)。因此,pg.event.get() 会将这些事件全部取出,返回一个包含所有事件的列表(“一组事件”),供程序遍历处理。

举例:一帧内的多个事件

假设在刚过去的一帧时间内(或上次处理事件之后),用户做了三个操作:

  1. 按下键盘的 键;
  2. 点击鼠标左键;
  3. 松开键盘的 键。

此时 pg.event.get() 会返回一个包含3个事件的列表,结构类似:

[<Event(KEYDOWN, key=K_UP, ...)>,  # 按下↑键<Event(MOUSEBUTTONDOWN, button=1, pos=(x,y), ...)>,  # 鼠标左键点击<Event(KEYUP, key=K_UP, ...)>  # 松开↑键
]

通过 for event in pg.event.get(): 循环,程序可以逐个处理这三个事件,确保没有遗漏。

说明

  • pg.event.get() 返回的是列表类型list),每个元素是一个 Event 对象(代表一个具体事件)。
  • 调用 pg.event.get() 后,事件队列会被清空(取出的事件不会再被重复处理),避免事件堆积导致程序响应延迟。
  • 如果一帧内没有任何事件,pg.event.get() 会返回一个空列表,循环不会执行任何操作。

pg.event.get() 之所以返回“一组事件”,是因为在一帧时间内可能发生多个用户操作或系统事件,Pygame 通过事件队列暂存这些事件,再通过 pg.event.get() 一次性取出,确保所有事件都能被及时处理,避免遗漏。这也是游戏能流畅响应复杂用户交互的基础。

处理用户输入和系统事件的核心逻辑

  • pg.event.get():获取当前 Pygame 事件队列中所有未处理的事件(如按键、鼠标点击、窗口关闭等),并清空队列(避免事件堆积)。
  • for event in ...:遍历这些事件,逐个处理(如判断是“关闭窗口”还是“按下键盘”,并执行对应逻辑)。

即:

  • Pygame 中所有用户交互(如点击鼠标、按键盘)和系统通知(如窗口大小变化、程序被暂停)都会被包装成“事件”,暂时存储在“事件队列”中。
  • 代码for event in pg.event.get():的作用就是**“取出”这些事件并逐一处理**,否则队列会堆积事件,导致程序无响应(比如用户点击关闭窗口,程序却收不到事件,无法退出)。

常见事件处理示例

在循环中,通常用 if 判断事件类型(event.type),并执行对应逻辑:

import pygame as pg
pg.init()screen = pg.display.set_mode((800, 600))
running = True# 游戏主循环
while running:# 核心:遍历所有事件并处理for event in pg.event.get():# 1. 处理窗口关闭事件(点击右上角X)if event.type == pg.QUIT:running = False  # 退出主循环# 2. 处理键盘按下事件elif event.type == pg.KEYDOWN:if event.key == pg.K_ESCAPE:  # 按ESC键running = Falseelif event.key == pg.K_SPACE:  # 按空格键print("空格键被按下")# 3. 处理鼠标点击事件elif event.type == pg.MOUSEBUTTONDOWN:if event.button == 1:  # 左键点击print(f"鼠标左键在坐标 {event.pos} 被点击")# 其他逻辑(绘制、更新等)screen.fill((255, 255, 255))pg.display.flip()pg.quit()

程序说明

  1. 事件类型event.type 表示事件的种类,Pygame 定义了多种常量(如 pg.QUITpg.KEYDOWNpg.MOUSEBUTTONDOWN 等)。
  2. 事件属性:不同事件有不同属性,例如:
    • 键盘事件 KEYDOWNevent.key(按下的键);
    • 鼠标事件 MOUSEBUTTONDOWNevent.pos(点击位置坐标)和 event.button(哪个键被点击,1=左键,3=右键)。
  3. 必须在主循环中(即按“帧”节奏):这行代码通常放在游戏主循环(while running:)中,确保每帧都能处理新事件,保证程序响应及时。

二、pg.key.get_pressed() 返回的是整个键盘当前的实时状态

pg.key.get_pressed() 返回的是整个键盘当前的实时状态——它会返回一个包含所有按键(包括字母、数字、方向键、功能键等)当前是否被按下的布尔值数组。

具体说明:

  1. 覆盖范围
    该数组包含了键盘上所有按键的状态,包括但不限于:

    • 字母键(A-Z)、数字键(0-9);
    • 方向键(↑↓←→);
    • 功能键(F1-F12)、特殊键(ShiftCtrlAltSpaceEsc 等)。
  2. 返回值结构
    返回的是一个布尔值数组pygame.key.ScancodeWrapper,可视为列表),其中:

    • 每个索引对应一个按键(通过 Pygame 定义的常量标识,如 pg.K_a 对应 A 键,pg.K_SPACE 对应空格键);
    • 数组元素为 True 表示该按键当前正被按下False 表示未被按下
  3. 时效性
    它反映的是调用该函数瞬间的键盘状态(实时的),而不是历史事件。例如:

    • 按住 W 键时,keystate[pg.K_w] 会持续返回 True(只要没松开);
    • 松开瞬间,会立即返回 False

示例:查看多个按键的状态

import pygame as pg
pg.init()screen = pg.display.set_mode((200, 200))
clock = pg.time.Clock()running = True
while running:for event in pg.event.get():if event.type == pg.QUIT:running = False# 获取整个键盘的当前状态keystate = pg.key.get_pressed()# 检查几个按键的状态print("A键是否按下:", keystate[pg.K_a])print("右方向键是否按下:", keystate[pg.K_RIGHT])print("空格键是否按下:", keystate[pg.K_SPACE])print("-------------------")screen.fill((255, 255, 255))pg.display.flip()clock.tick(1)  # 降低帧率,方便观察输出pg.quit()

运行后,当你按下不同的键,会看到对应的布尔值实时变化,证明它确实能获取整个键盘的当前状态。

pg.key.get_pressed() 的核心作用就是实时查询整个键盘上所有按键的“按下/未按下”状态,这使得它非常适合处理“持续按住按键”的场景(如角色移动、加速等),与事件队列(处理“按下/松开瞬间”)形成互补。

三、pg.key.get_pressed() 和事件队列(pg.event.get() 处理的)是完全独立的两套机制

pg.key.get_pressed() 和事件队列(pg.event.get() 处理的)是完全独立的两套机制,前者处理按键的“实时状态”,后者记录按键的“状态变化事件”(KEYDOWN/KEYUP),两者互不影响。

具体来说:
当你按住一个键时:

  • pg.key.get_pressed() 会持续返回该键的“按下状态”(True),直到松开;
  • 事件队列会正常记录一次 KEYDOWN 事件(按下瞬间),松开时再记录一次 KEYUP 事件(松开瞬间)。

即使你用 pg.key.get_pressed() 处理了该键的持续状态,这些 KEYDOWN/KEYUP 事件依然会被存入事件队列,直到被 pg.event.get() 取出处理。

举例说明

假设你按住 A 键移动角色(用 pg.key.get_pressed() 处理持续移动),同时按 B 键触发技能(用 pg.event.get() 处理 KEYDOWN 事件):

  • 按住 A 时,keystate[pg.K_a] 持续为 True(角色移动),事件队列会记录一次 KEYDOWN 事件(A 按下);
  • B 时,事件队列会新增 KEYDOWN 事件(B 按下),你可以通过 pg.event.get() 捕捉这个事件并触发技能;
  • 松开 A 时,事件队列会记录 KEYUP 事件(A 松开),keystate[pg.K_a] 变为 False(角色停止移动)。

pg.key.get_pressed() 仅负责查询“当前按键是否按下”,不会影响事件队列的记录;事件队列会独立记录所有按键的按下/松开瞬间,无论是否用 pg.key.get_pressed() 处理过该键的状态。

因此,即使某个按键被 pg.key.get_pressed() 处理,其对应的 KEYDOWN/KEYUP 事件依然会存在于事件队列中,等待 pg.event.get() 取出处理。

四、pg.key.get_pressed()pg.event.get()区别与联系

pg.key.get_pressed()pg.event.get() 处理的“事件组”都是 Pygame 中获取键盘输入的方式,但两者的机制、用途和时效性完全不同,互为补充而非替代关系。

核心区别:“状态” vs “事件”

特性pg.key.get_pressed()pg.event.get() 中的键盘事件(KEYDOWN/KEYUP
本质获取当前所有按键的实时状态(按下/未按下)获取按键状态变化的瞬间事件(按下/松开的动作)
返回值一个布尔值数组(索引对应按键,True 表示按下)包含 KEYDOWN(按下)/KEYUP(松开)对象的列表
时效性反映“调用瞬间”的按键状态(持续更新)反映“过去一帧内”发生的按键动作(离散事件)
适用场景持续操作(如按住方向键移动角色)单次操作(如按空格跳跃、按ESC打开菜单)

具体关系与分工

  1. pg.event.get() 处理“离散事件”
    键盘事件(KEYDOWN/KEYUP)是“瞬间动作”,属于 pg.event.get() 处理的事件组的一部分。例如:

    • 按下 空格 键时,事件队列会新增一个 KEYDOWN 事件;
    • 松开 空格 键时,会新增一个 KEYUP 事件。
      这些事件是“一次性的”,适合处理需要单次响应的逻辑(如跳跃、触发技能、打开菜单)。
  2. pg.key.get_pressed() 获取“持续状态”
    它不依赖事件队列,而是直接查询系统当前的键盘状态。例如:

    • 按住 右方向键 时,keystate[pg.K_RIGHT] 会持续返回 True(只要没松开);
    • 松开后,会立即返回 False
      这适合处理需要持续响应的逻辑(如角色移动——按住键时持续移动,松开后停止)。
  3. 两者的配合使用
    实际开发中,两者常结合使用,覆盖不同输入需求:

    • pg.event.get() 处理单次触发的操作(如按 P 暂停游戏);
    • pg.key.get_pressed() 处理持续触发的操作(如按 WASD 移动角色)。

示例:直观对比

import pygame as pg
pg.init()screen = pg.display.set_mode((400, 300))
clock = pg.time.Clock()
x, y = 200, 150  # 角色位置running = True
while running:# 1. 处理事件组(离散事件)for event in pg.event.get():if event.type == pg.QUIT:running = False# 处理单次按键(按空格打印信息)elif event.type == pg.KEYDOWN:if event.key == pg.K_SPACE:print("空格被按下(单次事件)")# 2. 获取实时按键状态(持续状态)keystate = pg.key.get_pressed()# 处理持续按键(按住方向键移动角色)if keystate[pg.K_LEFT]:x -= 3if keystate[pg.K_RIGHT]:x += 3if keystate[pg.K_UP]:y -= 3if keystate[pg.K_DOWN]:y += 3# 绘制角色screen.fill((255, 255, 255))pg.draw.circle(screen, (0, 0, 255), (x, y), 20)pg.display.flip()clock.tick(60)pg.quit()
  • 按住 方向键 时,角色会持续移动(依赖 keystate 的实时状态);
  • 按一次 空格 时,只会打印一次信息(依赖 KEYDOWN 事件的单次触发)。

记住:

  • pg.event.get() 中的键盘事件(KEYDOWN/KEYUP):处理按键动作的瞬间,适合单次操作;
  • pg.key.get_pressed():获取按键的当前状态,适合持续操作。

两者机制不同,但在游戏的帧循环中同时使用(如上例),是 Pygame 中处理键盘交互的核心工具。

http://www.dtcms.com/a/330709.html

相关文章:

  • LT3045EDD#TRPBF ADI亚德诺 超低噪声LDO稳压器 电子元器件IC
  • Trae x Figma MCP一键将设计稿转化为精美网页
  • Docker build创建镜像命令入门教程
  • Redis (REmote DIctionary Server) 高性能数据库
  • 【cmake】编译cpp文件,安装MinGW
  • 《Leetcode》-面试题-hot100-动态规划
  • 《嵌入式 C 语言编码规范个人笔记》参考华为C语言规范标准
  • 标贝科技「十万音色·自然语音数据集」 重构AI语音训练基础设施
  • 机器视觉之图像处理篇
  • OpenCV Python——报错AttributeError: module ‘cv2‘ has no attribute ‘bgsegm‘,解决办法
  • 63w+有小程序注册的企业汇总数据(2024.2)
  • 阿里云TranslateGeneral - 机器翻译SDK-自己封账单文件版本—仙盟创梦IDE
  • CSS中实现一个三角形
  • 哪些对会交由SpringBoot容器管理?
  • Unity中的神经网络遗传算法实战
  • 【数据可视化-89】基孔肯雅热病例数据分析与可视化:Python + pyecharts洞察疫情动态
  • UE小:编辑器模式下「窗口/鼠标不在焦点」时仍保持高帧率
  • Flask中ORM的使用
  • 论郑和下西洋元素融入课件编辑器的意义与影响​
  • docker使用指定的MAC地址启动podman使用指定的MAC地址启动
  • 同创永益 IStorM CNBR云原生业务韧性管理平台 v3.3.0重磅发布:告别备份烦恼,云原生数据保护再升级!
  • 深度学习——03 神经网络(4)-正则化方法价格分类案例
  • MacOS 系统计算机专业好用工具安装
  • Nginx学习笔记(九)—— Nginx Rewrite深度解析
  • C++ STL学习 之 泛型编程
  • Unity Shader unity文档学习笔记(十九):粘土效果,任意网格转化成一个球(顶点动画,曲面着色器)
  • 算法提升之树上问题-(LCA)
  • vue3使用leaflet地图
  • **超融合架构中的发散创新:探索现代编程语言的挑战与机遇**一、引言随着数字化时代的快速发展,超融合架构已成为IT领域的一种重要趋势
  • 【入门级-算法-2、入门算法:枚举法】