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
英文地址,請注明出處:http://en.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…