2020年10月4日 星期日

pygame玩遊戲系列(5)~偵測按鍵動作讓物件持續移動

 前面介紹了如何透過鍵盤按鍵的操作讓物件進行移動的操作!

透過上述操作的方式,透過偵測是否有按鍵被「按下去」來進行移動,這樣的方式讓物件移動時,移動模式是按一次指定的按鍵,車子移動一次(也就是設定的2單位),若要讓車子一直移動就需要不斷的重複按指定按鍵。

即使你一直按住指定按鍵時,系統只會偵測到一次「按鍵被按下去」的訊號,車子依舊只會移動一次,不會一直跑!(這就是上一篇我們留下要思考的點之一)

這次,我們就來看看如何設計讓使用者「按住」指定按鍵時,遊戲中的物件(小車)可以持續移動吧!

在實作貼出程式碼前,我們先來思考一下設計的注意事項:

有關如何讓遊戲中物件(小車)移動的概念,就請參考前一篇相關的介紹及說明,這裡就不重複敘述了!

一、首先先談一下:在pygame中,按鍵被「按下去(KEYDOWN)」和被「按住不放(PRESSED)」是不同的二種事件,要仔細分清楚~不能混為一談喔!

二、我們希望使用者「按住」鍵盤「L」或是「向左(←)」按鍵時,小車會持續向左移動,但當小車移動到遊戲視窗左邊界時,就停住不會再移動了(以免小車跑出遊戲視窗外)!

三、我們希望使用者「按住」鍵盤「R」或是「向右(→)」按鍵時,小車會持續向右移動,但當小車移動到遊戲視窗右邊界時,就停住不會再移動了(同樣是避免小車跑出遊戲視窗外)!

好囉~~那為了達成以上的設計目標,主要的核心就是如何偵測遊戲過程是否有按鍵被「按住」又是那些按鍵被「按住」了!是吧~~?!

一樣先貼出完整程式碼直接觀看囉~~~

import pygame, sys
from pygame.locals import *

pygame.init()
bg = pygame.image.load("./imgs/bg-02.jpg")     #設定背景圖來源
car_img = pygame.image.load("./imgs/car6.png")    #設定要被控制的小車圖檔來源
screen = pygame.display.set_mode((500, 380))    #設定視窗資訊
pygame.display.set_caption('騎車春遊趣')       #設定視窗標題

car_x = 240 #設定腳踏車圖檔起始x座標位置

while True:   #主視窗循環
    screen.blit(bg, (0, 0))  # 設定視窗的背景圖片及相對位置
    for event in pygame.event.get():   #偵測視窗中獲取的事件資訊
        if event.type == QUIT:      #如果出現[關閉]事件(按了關閉視窗的按鈕)時
            pygame.quit()      #離開pygame
            sys.exit()      #離開系統

    key_p = pygame.key.get_pressed()  #偵測是否有按鍵被按住的狀態
    # 若是L鍵或是向左(←)鍵被按住而且車子的x座標大於0(視窗左邊邊界位置,避免車子跑出視窗左邊界)
    if (key_p[pygame.K_l] or key_p[pygame.K_LEFT]) and car_x >= 0:
        car_x -= 2  #車子向左移動2單位
    if (key_p[pygame.K_r] or key_p[pygame.K_RIGHT]) and car_x <= 436:
    #若是R鍵或是向右(→)鍵被按住而且車子的x座標小於436(視窗寬度500-車子圖檔的寬度64,避免車子跑出視窗右邊)
        car_x += 2  #車子向右移動2單位

    screen.blit(car_img, (car_x, 270))  # 在指定的位置繪製出車子
    pygame.display.update()    #更新視窗

大家可以對照前一篇的按下按鍵的移動方式一起比較其中差異!

主要核心自然是偵測按鍵被「按住」的方法為:

key_p = pygame.key.get_pressed()

pygame.key.get_pressed會獲取「被按住」的按鍵,成為一組列表:key_p

而後再針對key_p這組列表進行判斷是否有指定的按鍵,再針對指定的按鍵分別設定相對應的動作。

而這次也加入了在移動前,同步偵測小車物件是否已經移動到遊戲視窗左右邊界的判斷式(car_x小車x座標是否在遊戲視窗範圍內)。

============有待改進及思考之處==============

目前因為重點仍是如何讓物件移動,尚未談到pygame物件中的surface rect參數獲取及應用,所以在範例中可以看到遊戲邊界的設定及操作都是直接使用計算後的結果寫入。

這種自行計算、直接寫入參數的方式,對於日益龐大的系統及日後維護、修改都相當不便!後續將就這部分參數的獲取及操作作介紹。

沒有留言:

張貼留言