iT邦幫忙

1

【pygame初體驗】學習用角色類別(Sprite),做一個飄雪動畫

嗨嗨,大家好,
pygame是python中適合開發遊戲的模組,
今天又是一個自學pygame的日常

延續上一篇: 【pygame初體驗】學習用pygame來打造自己的遊戲

首先來複習一下基礎架構,
基構架構有點多行,可以多看幾次

一、基礎架構

這樣子就可以得到一個空白視窗,
這邊有個概念是「繪圖視窗」和「畫布」是分開的,
通常不會直接在繪圖視窗畫圖,
而會先畫在「畫布」上,再把畫布貼到「繪圖視窗」上

今天重新想過後,大概更理解它的道理。
假設今天你有一件重要的事情怕忘記,
你可能會想寫在顯眼的地方提醒自己,
於是你抬頭看了一下工作桌前正好有一面牆壁,
寫在牆上非常的顯眼,
但是這樣一來要擦掉牆上的字就相當麻煩

於是你把重要事項寫在容易撕下來的「便利貼」上,
把便利貼貼在牆上,要撕掉或移動都非常簡單。
這邊的「繪圖視窗」就彷彿是你的牆壁,
「畫布」就彷彿是你的便利貼

import pygame
pygame.init()  #pygame初始化

# 設定視窗
width, height = 640, 320
screen = pygame.display.set_mode((width, height))  #建立繪圖視窗
pygame.display.set_caption("基本架構")  #繪圖視窗標題

#建立畫布 (書上說通常不會直接在繪圖視窗畫圖)
background = pygame.Surface(screen.get_size())  
background = background.convert() #為畫布建立副本,加快顯示速度
background.fill((255,255,255))  #畫布為白色(三個參數為RGB)

running = True
while running:  #無窮迴圈
    for event in pygame.event.get():
        if event.type == pygame.QUIT:  #使用者按右上角的關閉鈕
            running = False
    screen.blit(background, (0,0))  #在繪圖視窗繪製畫布
    pygame.display.update()  #更新繪圖視窗
    
pygame.quit()  #關閉繪圖視窗

這邊有個細節是screen.blit(background, (0,0))我覺得可以直接放到while迴圈內,
這樣若背景改變就可以看到效果

二、加入動畫的基本架構

「動畫」指的就是遊戲裡面的物件及角色能夠動起來,
而非靜態的畫上去就不會動了,
主要會用到clock = pygame.time.Clock()clock.tick(次數)指令設定每秒重繪的次數

除了既有的架構外,
我在一開始定義顏色參數,
畢竟只用RGB可能久了根本看不懂是什麼顏色,
直接為常用顏色命名方便日後撰寫程式

這邊寫個自己的版本

import pygame
pygame.init()  #pygame初始化

# 創建顏色(三個參數為RGB)
GREEN = (0,255,0) # 綠色
RED = (255,0,0) # 紅色
BLUE = (0,0,255) # 藍色
WHITE = (255,255,255) # 白色
BLACK = (0,0,0) # 黑色
YELLOW = (255,255,0) #黃色

# 設定視窗
width, height = 640, 70
screen = pygame.display.set_mode((width, height))  #建立繪圖視窗
pygame.display.set_caption("基本架構")  #繪圖視窗標題

# 建立畫布 (書上說通常不會直接在繪圖視窗畫圖)
background = pygame.Surface(screen.get_size())  
background = background.convert() #為畫布建立副本,加快顯示速度
background.fill(WHITE)

# 遊戲主要無窮迴圈
clock = pygame.time.Clock() #重要,計時物件
running = True
while running:  
    clock.tick(30)  #每秒執行30次
    for event in pygame.event.get():
        if event.type == pygame.QUIT:  #使用者按右上角的關閉鈕
            running = False
        
    screen.blit(background, (0,0)) # 在繪圖視窗繪製畫布
    pygame.display.update()  #更新繪圖視窗

pygame.quit()  # 關閉繪圖視窗

三、角色類別(Sprite)

要寫一個角色類別,需繼承pygame.sprite.Sprite這個類別,
好處是可以很方便的幫助我們創建大量相同的物件

語法大致上會這樣寫:

class someSprite(pygame.sprite.Sprite):  
 
    def __init__(self, 參數1, 參數2, ...):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface([…, …])  #建立畫布
        self.rect = self.image.get_rect()  #取得畫布區塊
        self.rect.center = (x座標, y座標)  # 設定初始位置
 
    # 可以在主程式呼叫,用來移動角色
    def update(self):
        pass

基於前述提到不會直接在繪圖視窗畫圖,
而會先畫在「畫布」上,再把畫布貼到「繪圖視窗」上

通常角色也會有自己的畫布,
移動角色相當於移動畫布的概念

角色類別的繪製方式與一般畫布不太一樣,
首先需要將角色物件加入角色群組中,
語法:角色群組名稱 = pygame.sprite.Group()可以創建角色群組,
再用角色群組名稱.add(角色物件)可以將角色加入群組中,
角色群組名稱.draw(繪圖視窗)將所有角色畫出來

完整範例- 飄雪動畫

首先,我創建一個黑色的背景畫布,
再創建球的角色類別,
隨機創建多個白色小球(當作雪球),
小球更新時會往螢幕下方走,
即可製作類似飄雪的動畫效果

import pygame, random
pygame.init()  #pygame初始化

# 創建顏色(三個參數為RGB)
GREEN = (0,255,0) # 綠色
RED = (255,0,0) # 紅色
BLUE = (0,0,255) # 藍色
WHITE = (255,255,255) # 白色
BLACK = (0,0,0) # 黑色
YELLOW = (255,255,0) #黃色

class Ball(pygame.sprite.Sprite):  #球體角色
 
    # 參數為「球速」、「球x,y座標」、「半徑」、「球顏色」
    def __init__(self, sp, srx, sry, radium, color):
        pygame.sprite.Sprite.__init__(self)
        self.speed = sp
        self.image = pygame.Surface([radium*2, radium*2])  #繪製球體
        self.image.fill(BLACK) # 畫布背景同背景色
        pygame.draw.circle(self.image, color, (radium,radium), radium, 0)
        self.rect = self.image.get_rect()  #取得球體區域
        self.rect.center = (srx,sry)  #初始位置
 
    def update(self):  #球體移動
        self.rect.y += self.speed # 改變球的位置

# 設定視窗
width, height = 640, 320
screen = pygame.display.set_mode((width, height))  #建立繪圖視窗
pygame.display.set_caption("基本架構")  #繪圖視窗標題

#建立畫布 (書上說通常不會直接在繪圖視窗畫圖)
background = pygame.Surface(screen.get_size())  
background = background.convert() #為畫布建立副本,加快顯示速度
background.fill(BLACK)  #畫布為黑色(三個參數為RGB)

#建立全部角色群組
allsprite = pygame.sprite.Group()  

# 遊戲主要無窮迴圈
clock = pygame.time.Clock() #重要,計時物件
running = True
while running:  #無窮迴圈
    clock.tick(30)  #每秒執行30次
    for event in pygame.event.get():
        if event.type == pygame.QUIT:  #使用者按右上角的關閉鈕
            running = False
    
    # 隨機添加雪球
    ball = Ball(2, random.randint(0,screen.get_width()), 0, 5, WHITE)  #建立白色球物件
    allsprite.add(ball)  #加入全部角色群組
    
    screen.blit(background, (0,0))  #在繪圖視窗繪製畫布
    # 更新所有角色的狀態
    for spr in allsprite:
        spr.update()
    allsprite.draw(screen)  #繪製所有角色
    pygame.display.update()  #更新繪圖視窗
    
pygame.quit()  #關閉繪圖視窗

效果:
https://ithelp.ithome.com.tw/upload/images/20200709/20117114RDzSk6jAOb.png


尚未有邦友留言

立即登入留言