2020年10月22日 星期四

pygame玩遊戲系列(9)~在遊戲中隨機出現指定數量的物件

 之前已經介紹過如何在遊戲視窗中隨機出現物件(禮物)並自動落下的操作

但之前因為一些觀念尚未介紹,且考慮到初學者需按部就班了解各個遊戲中(程式)元素的操控及設計核心,所以只設計了產生一組禮物從天而降的設計。

這樣的操作,當然沒有辦法滿足設計遊戲元素的需求,通常遊戲中的元素會有數量及個別「屬性」設定的操作需求,而這也是遊戲設計中最重要、最精采也是最燒腦的核心。

而對於這樣一種既有共同特性(例如:從天而降的禮物),又需要有個別化的「屬性(參數)」或「行為」(例如:降落的速度,顯示的位置...等等),有經驗的設計者自然會想到使用所謂的「物件導向模式」(OOP)中的類別(Class)設計模式,來為每個遊戲中的物件元素進行「屬性」及「行為」的設定。

但是同樣的,我們現階段依然採用「土法煉鋼」方式進行遊戲中物件元素的設計方式進行操作及說明,為的依然是讓學習者及自己能夠更為精確的理解「物件」設計的核心思維及關鍵概念,為日後的「函式(Function)」及Class(類別)學習及操作建立良好的基礎知能。

好囉~~~現在正式進入主題!

本次的目標有二:

一、可以在遊戲中設定出現指定數量的物件(禮物),這次我們預設遊戲視窗中保持有五個從天而降的禮物物件。

二、上述各物件(禮物)會隨機出現在遊戲視窗中,並各自落下。

為了達成以上的目標,我們必須先從前面的各篇文章取思考以下的設計關鍵點:

1.遊戲中的物件(禮物、小車等)是如何藉由(rect)矩形座標物件將圖形繪製(顯示)在視窗中的!

   範例語法:  screen.blit(gift_img, gift_rect)    # 在視窗中的gift_rect座標繪製gift_img圖形

2.如何能夠隨機設定禮物(物件)的矩形座標(rect),讓物件隨機出現在視窗中。

    範例語法: gift_rect.centerx = random.randrange(0, screen_rect.width)

3.如何偵測視窗中的物件數量,並讓這些物件能夠保持在設定的數量並出現在視窗中並落下?

    (也就是保持有五個禮物物件並讓這些禮物自動落下)

    ---關鍵來了~~(個人習慣)若發現有「一批」物件要做同樣的事

    (例如:隨機產生五個禮物的出現位置、五個禮物都要自動落下...等),

    就可以考慮使用串列(list)+for(條件式迴圈)來進行思考及設計。

~~~串列(list)可以將一組物件加以組合,並透過for迴圈進行同樣的行為(動作)設計

好囉~~所以,我們在之前隨機出現單一物件並自動落下的設計基礎上,持續強化程式如下,達成上述的目標及設計理念。

同樣先上完整程式碼如下:

import pygame
import sys
import random
from pygame.locals import *
pygame.init()

screen_width, screen_height = 500, 380  # 設定遊戲視窗寬、高參數
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption('騎車春遊趣')
clock = pygame.time.Clock()

car_img = pygame.image.load("./imgs/car6.png")
gift = pygame.image.load("./imgs/gift320.png")
screen_rect = screen.get_rect()  # 獲取遊戲視窗矩形座標參數儲存於參數:screen_rect
car_rect = car_img.get_rect()    # 獲取小車矩形座標參數儲存於參數:car_rect
# 將小車的中心底部座標設定與視窗的中心底部座標貼齊
car_rect.midbottom = screen_rect.midbottom

gift_rects = []     # 設定一組用於儲放禮物矩形座標物件(rect)的串列(list)變數

while True:
    screen.fill((255, 255, 0))   # 將遊戲視窗背景塗成黃色
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()

    key_p = pygame.key.get_pressed()
    if (key_p[pygame.K_l] or key_p[pygame.K_LEFT]) and car_rect.left >= screen_rect.left:
        car_rect.x -= 4
    if (key_p[pygame.K_r] or key_p[pygame.K_RIGHT]) and car_rect.right <= screen_rect.right:
        car_rect.x += 4

    # 透過小車矩形參數:car_rec於指定位置繪製小車(car_img)
    screen.blit(car_img, car_rect)

    # 設定禮物出現數量並讓每次新增的禮物出現位置以隨機方式產生
    while len(gift_rects) < 5:
        grect = gift.get_rect()  # 重新獲取禮物圖檔之矩形座標參數
        grect.centerx = random.randrange(10, screen_width - 10)   # 隨機設定新的禮物中心點x座標位置
        grect.centery = random.randrange(5, 100)   # 隨機設定新的禮物中心點y座標位置
        gift_rects.append(grect)    # 將新增的禮物矩形座標物件儲放進座標串列(list)中,供後續操作呼叫使用

	 # 透過for迴圈,將串列gift_rects中的grect元素陸續取出進行繪製及落下設定
    for g in gift_rects:
        if g.centery < screen_rect.bottom:
            screen.blit(gift, g)
            g.centery += 1
        else:
            gift_rects.remove(g)  # 禮物落下超過視窗下方,就將該元素(g)從串列中移除

    clock.tick(60)
    pygame.display.update()    # 更新視窗


程式碼中最主要的核心在以下幾個部分:

1.第38~42行:有關while迴圈產生五組gift 矩形座標物件(grect)並加入gift_rects串列中的操作

2.第45~50行:透過for迴圈將串列中元素個別取出進行操作及設定

其他重要的補充說明及成果展示,可參考以下影片:


後續結合之前介紹過的物件「碰撞」偵測等應用,就可以陸續加入進行計分、扣分等各式遊戲元素的設計,開心可期啊~~呵!

沒有留言:

張貼留言