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 移动角色)。
    • 特别是:(1)只处理关心的事件,绝大多事件被忽视,(2)只处理关心的键的状态,其它键状态被忽视。

示例:直观对比

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.pswp.cn/web/93116.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/93116.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

TF - IDF算法面试与工作常见问题全解析

在自然语言处理领域&#xff0c;TF - IDF算法是一个基础且重要的概念。无论是在求职面试还是在实际工作中&#xff0c;都经常会遇到与TF - IDF相关的问题。以下是一些常见的问题及其详细解答&#xff1a; 一、基本概念类问题 1. 什么是TF - IDF算法&#xff1f; TF - IDF&#…

Transformer网络结构解析

博主会经常分享自己在人工智能阶段的学习笔记&#xff0c;欢迎大家访问我滴个人博客&#xff01;&#xff08;都不白来&#xff01;&#xff09; 小牛壮士 - 个人博客https://kukudelin.top/ 前言 Transformer 广泛应用于自然语言处理&#xff08;如机器翻译、文本生成&…

gateway进行接口日志打印

打印需求&#xff1a;对所有的接口打印&#xff1a;请求方式&#xff0c;请求路径&#xff0c;请求参数&#xff0c;用户id&#xff0c;访问IP&#xff0c;访问时间对增删改操作的接口打印&#xff1a;接口响应打印方案&#xff1a;给GET设置一个白名单&#xff08;因为get请求…

MATLAB实现图像增强(直方图均衡化)

直方图均衡化是一种常用的图像增强技术&#xff0c;它通过重新分布图像的像素强度值来增强图像的对比度。以下是MATLAB中实现直方图均衡化的详细方法。%% 直方图均衡变换 clc;close all;clear all;warning off;%清除变量 rand(seed, 100); randn(seed, 100); format long g;%% …

java15学习笔记-密封类

360:Sealed Classes (Preview) 封闭类&#xff08;预览&#xff09; 总结 使用密封类和接口增强Java编程语言。密封类和接口限制了哪些其他类或接口可以扩展或实现它们。这是JDK 15中的预览语言功能。 目标 允许类或接口的作者控制负责实现它的代码。 提供一种比访问…

西门子PLC通过稳联技术EtherCAT转Profinet网关连接baumuller伺服器的配置案例

西门子PLC用稳联技术的EtherCAT转Profinet网关&#xff0c;连上baumuller伺服器的配置例子本案例实现西门子S71200 PLC通过EtherCAT转Profinet网关对baumuller&#xff08;Baumller&#xff09;伺服器的实时控制&#xff0c;适用于高精度运动控制场景&#xff08;如精密机床、自…

Ansible 详细笔记

Ansible 详细笔记 一、Ansible 基础概述 1.1 定义与定位 Ansible 是由 Red Hat 主导开发的开源自动化运维工具&#xff0c;基于 Python 语言实现&#xff0c;专注于简化 IT 基础设施的配置管理、应用部署、任务编排等操作。它采用无代理架构&#xff0c;通过 SSH 协议与被控节点…

【Java 后端】Spring Boot 集成 JPA 全攻略

Spring Boot 集成 JPA 全攻略 一、前言 在 Java Web 开发中&#xff0c;数据库访问是绕不开的话题。 传统方式使用 JDBC 编写 SQL&#xff0c;维护困难、可读性差。后来有了 MyBatis 这种半自动 ORM 框架&#xff0c;再到 JPA&#xff08;Java Persistence API&#xff09;这…

pytorch学习笔记-加载现有的网络模型(VGG16)、增加/修改其中的网络层(修改为10分类)

写在前面&#xff1a;有些地方和视频里不一样的是因为官方文档更新了&#xff0c;一些参数用法不一样也很正常&#xff0c;包括我现在的也是我这个时间节点最新的&#xff0c;谁知道过段时间会不会更新呢 建议大家不要一味看视频/博客&#xff0c;多看看官方文档才是正道&#…

RocketMQ 4.9.3源码解读-NameServer组件启动流程分析

作者源码阅读笔记主要采用金山云文档记录的,所有的交互图和代码阅读笔记都是记录在云文档里面,本平台的文档编辑实在不方便,会导致我梳理的交互图和文档失去原来的格式,所以整理在文档里面,供大家阅读交流 【金山文档 | WPS云文档】 namesrv 启动流程 相关重要类介绍说明…

《嵌入式 C 语言编码规范与工程实践个人笔记》参考华为C语言规范标准

《嵌入式 C 语言编码规范与工程实践个人笔记》参考华为C语言规范标准 前言 在电子系统开发领域&#xff0c;C 语言作为底层开发的核心语言&#xff0c;其代码质量直接关系到系统的稳定性、可维护性和扩展性。良好的编码规范不仅是团队协作的基础&#xff0c;更是降低生命周期成…

纯半精度模型和全精度模型的耗时分别为248微秒和1400微秒。混合精度模型371微秒比原始模型快大约四倍!

不过有一点需要注意:在上下文管理器内部生成的任何输出,必然会采用该上下文管理器的数据类型。因此,之后我们必须将这些输出转换回FP32(例如,使用float()函数)。 with torch.autocast(device_type="cuda", dtype=torch.float16): res16 = mixed32(torch.randn…

一款开源的远程桌面软件,旨在为用户提供流畅的游戏体验,支持 2K 分辨率、60 FPS,延迟仅为 40ms。

软件介绍 CloudPlayPlus&#xff08;云玩加&#xff09;是一款令人惊艳的开源远程桌面、串流软件&#xff0c;云玩加由个人开发者开发者&#xff0c;具有四大特征&#xff1a;开源、免费、低延迟、安全。 软件使用 客户端支持多个平台&#xff0c;包括 Windows、Mac OS、安卓…

MySql——binlog和redolog的区别

目录一、binlog和redolog的区别一、binlog和redolog的区别 binlog和redolog都是存储修改的新数据&#xff0c;是否保留binlog和redolog中的一个即可。 binlog属于整个mysql&#xff0c;是所有引擎共用的&#xff0c;不是只属于innoDB引擎。而redolog属于InnoDB存储引擎。binlo…

软件著作权产生与登记关键点

知识讲解一、 软件著作权的核心特征与权利内容自动产生原则&#xff1a; 这是软件著作权最核心、最重要的特征。产生时间&#xff1a; 软件著作权自软件开发完成之日起自动产生。法律依据&#xff1a; 《中华人民共和国著作权法》第二条及《计算机软件保护条例》第五条明确规定…

什么是主成分分析(PCA)和数据降维

主成分分析&#xff08;PCA&#xff09;和数据降维是机器学习和统计学中处理高维数据的核心工具。下面用清晰的结构解释其概念、原理和应用&#xff1a; 一、数据降维&#xff08;Dimensionality Reduction&#xff09; 1. 是什么&#xff1f; 目标&#xff1a;将高维数据&…

图论(4)单源赋权最短路径算法实现(BFS实现)

目录 1. 什么是赋权最短路径 2. 赋权最短路径中的关键概念 3. Dijkstra 算法的基本思想 4. Dijkstra 算法实现&#xff08;Java&#xff09; 1. 什么是赋权最短路径 在图论中&#xff0c;最短路径问题是指在图中寻找两点之间路径总权重最小的路径问题。如果图的每条边都带…

【Lua】题目小练9

题目&#xff1a;实现一个简单的“银行账户”类要求&#xff1a;使用 元表 模拟面向对象。支持以下功能&#xff1a;Account:new(owner, balance) 创建账户&#xff08;初始余额可选&#xff0c;默认为 0&#xff09;。deposit(amount) 存款&#xff08;不能为负数&#xff09;…

【二分图】染色问题

核心思想&#xff1a;为每一个未染色的&#xff0c;对它自己和它的邻居进行染色&#xff0c;看是否会出现冲突时间复杂度O&#xff08;nm&#xff09;#include<bits/stdc.h> using namespace std; using lllong long; const int N200010; int n,m; vector<int>edge…

报数游戏(我将每文更新tips)

今日tips&#xff1a;报数游戏题目描述报数游戏的游戏规则如下&#xff1a;对一个区间内的整数进行报数&#xff0c;若遇到的数字是质数或个位数是 1&#xff0c;则不报数&#xff0c;输出 pass。 给定开始游戏的第一个整数 a&#xff0c;及结束游戏时的最后一个整数 b&#xf…