他吃過苦,他什麼也不說,最好是做出幸福的樣子。
——-加繆《反與正》
咱們今天的遊戲,主角是眉(shuang)開(chong)眼(ren)笑(ge)的小丑先生。
無數的藝術作品以他為主角,他以快樂的表情、滑稽的動作為大家帶來了歡樂,但在那副笑逐顏開的面具下,究竟隱藏著什麼樣的秘密呢?
在這一期中,我們把前面所學的知識融合起來,編寫一個小丑頂小球的小遊戲~
這是我們本期的材料,各位看官請收好~
連結:
https://
pan。baidu。com/s/1ia70Ld
Z3nV41KM3VA2XYgg
提取碼:oh1v
以下是遊戲的基本設定:
【1】一個在視窗內來回反彈的小球
【2】 一個頂球的小丑
【3】小丑的頭頂球后,球反彈到視窗頂部,得分
【4】在視窗內顯示得分情況
【5】每次遊戲有三次機會
【6】 遊戲結束後,顯示最終得分
【7】不同的遊戲事件,有不同的配樂
一、類
根據以上的設定,我們需要分別建立小球和小丑的例項。其中,小球需要在視窗內運動、一定的速度、碰壁後反彈等。而小丑的精靈類則是需要載入一張圖片,這個小丑可以左右移動:
class MyBallClass(pygame。sprite。Sprite):
def __init__(self, image_file, speed, location):
pygame。sprite。Sprite。__init__(self)
self。image = pygame。image。load(image_file)
self。rect = self。image。get_rect()
self。rect。left, self。rect。top = location
self。speed = speed
def move(self):
global score, score_surf, score_font
self。rect = self。rect。move(self。speed)
if self。rect。left < 0 or self。rect。right > screen。get_width():
self。speed[0] = -self。speed[0]
if self。rect。top <= 0 :
self。speed[1] = -self。speed[1]
score = score + 1
score_surf = score_font。render(str(score), 1, THECOLORS[‘white’])
小球
class ClownClass(pygame。sprite。Sprite):
def __init__(self):
pygame。sprite。Sprite。__init__(self)
self。image = pygame。image。load(‘clownFace_right。png’)
self。rect = self。image。get_rect()
self。rect。center = [40,460]
小丑
二、用滑鼠控制小丑運動
我們使用使用 MOUSEMOTION 事件來控制小丑移動。由於滑鼠在 Pygame 視窗內時移動時 Pygame 才能“看到”滑鼠,所以小丑會自動限制在視窗的邊界以內。我們讓小丑的中心跟隨滑鼠移動:
elif event。type == pygame。MOUSEMOTION:
clown。rect。centerx = event。pos[0]
在以上程式碼中,event。pos 是一個列表,包含滑鼠位置的 [x, y] 值。event。pos[0] 會提供滑鼠移動時的水平位置。
三、小丑頂球
要想實現小丑頂球,需要對小球和小丑之間的進行碰撞檢測,接著利用這種“碰撞”實現小丑將球“頂”起。出現碰撞時,只需讓小球的豎直速度反向,程式碼如下:
if pygame。sprite。spritecollide(clown, ballGroup, False):
myBall。speed[1] = -myBall。speed[1]
四、記錄分數:
我們記錄分數分為兩個方面:得分情況以及剩餘機會的次數。為了力求簡單,每次小球碰到視窗頂邊時,我們會得一分,每位玩家在一次遊戲中有三次機會。
還記得上期阿呆的那張盲僧鎮樓圖嘛?我們提及了文字插入的方法:
4。1 建立一個font物件,告訴 Pygame我們需要的字型樣式和大小
4。2 渲染文字(render),向字型物件傳入一個字串(得分情況),它會返回一個繪製有這個文字的新的表面
4。3 把這個表面塊移到顯示錶面
根據以上的過程,我們的程式碼如下:
score = 0
score_font = pygame。font。Font(None, 30)
score_surf = score_font。render(str(score), 1, THECOLORS[‘white’])
score_pos = [20, 20]
先建立一個分數(score)變數,None表示預設字型,接著設定渲染文字到表面塊的顏色以及文字的位置。每次頂球成功後,玩家得一分:
if self。rect。top <= 0 :
self。speed[1] = -self。speed[1]
score = score + 1
score_surf = score_font。render(str(score), 1, THECOLORS[‘white’])
接著我們設定玩家有三次機會,建立一個名為lives的變數:
lives = 3
每次小丑沒有頂到小球,lives的值都要減一,等待幾秒後,新的小球重新開始彈跳:
if myBall。rect。top >= screen。get_rect()。bottom:
lives = lives - 1
else:
pygame。time。delay(2000)
myBall。rect。topleft = [50, 50]
分數與機會次數記錄
遊戲結束後,顯示最終得分:
if lives == 0:
final_text1 = “遊戲結束”
final_text2 = “您最後的分數是: ” + str(score)
ft1_font = pygame。font。Font(‘C:\Windows\Fonts\simhei。ttf’,80)
ft1_surf = ft1_font。render(final_text1, 1, THECOLORS[‘white’])
ft2_font = pygame。font。Font(‘C:\Windows\Fonts\simkai。ttf’,50)
ft2_surf = ft2_font。render(final_text2, 1, THECOLORS[‘white’])
遊戲結束
五、音樂
對於不同的遊戲事件,我們需要搭配不同的音樂。總體分為兩類:背景音樂與單個事件的音樂。
5。1 背景音樂:載入音樂,設定音量後,我們希望在玩遊戲期間,背景音樂一直在重複,所以需要使用特殊值 -1:
pygame。mixer。music。load(‘bgm。ogg’)
pygame。mixer。music。set_volume(0。2)
pygame。mixer。music。play(-1)
5。2 單個事件的音樂:只有事件發生,音樂才播放。此類音樂需要緊跟在它所對應的事件之後。如小球碰到視窗兩側的聲音:
if self。rect。top < screen。get_height():
hit_wall。play()
六、完整程式碼
來看看我們最終的學習成果吧~
#引入
import pygame
from pygame。color import THECOLORS
#小球類定義
class MyBallClass(pygame。sprite。Sprite):
def __init__(self, image_file, speed, location):
pygame。sprite。Sprite。__init__(self)
self。image = pygame。image。load(image_file)
self。rect = self。image。get_rect()
self。rect。left, self。rect。top = location
self。speed = speed
#動畫函式
def move(self):
global score, score_surf, score_font
self。rect = self。rect。move(self。speed)
#視窗兩側反彈
if self。rect。left < 0 or self。rect。right > screen。get_width():
self。speed[0] = -self。speed[0]
#小球撞到視窗兩側的聲音
if self。rect。top < screen。get_height():
hit_wall。play()
#小球碰到頂部視窗後,玩家得一分
if self。rect。top <= 0 :
self。speed[1] = -self。speed[1]
score = score + 1
score_surf = score_font。render(str(score), 1, THECOLORS[‘white’])
#得分的聲音
get_point。play()
#小丑類定義
class ClownClass(pygame。sprite。Sprite):
def __init__(self):
pygame。sprite。Sprite。__init__(self)
self。image = pygame。image。load(‘clownFace_right。png’)
self。rect = self。image。get_rect()
self。rect。center = [40,460]
#初始化
pygame。init()
pygame。mixer。init()
#載入音樂檔案、設定音量
pygame。mixer。music。load(‘bgm。ogg’)
pygame。mixer。music。set_volume(0。2)
pygame。mixer。music。play(-1)
hit = pygame。mixer。Sound(‘hit_clown。wav’)
hit。set_volume(0。4)
new_life = pygame。mixer。Sound(‘new_life。wav’)
new_life。set_volume(0。5)
die = pygame。mixer。Sound(‘die。wav’)
die。set_volume(0。6)
hit_wall = pygame。mixer。Sound(‘hit_wall。wav’)
hit_wall。set_volume(0。2)
get_point = pygame。mixer。Sound(‘get_point。wav’)
get_point。set_volume(0。2)
bye = pygame。mixer。Sound(‘game_over。wav’)
bye。set_volume(0。6)
#設定視窗大小、遊戲名稱
screen = pygame。display。set_mode([600,500])
pygame。display。set_caption(‘小丑與小球’)
#建立Clock的例項顏色
clock = pygame。time。Clock()
#載入小球圖片
myBall = MyBallClass(‘orangeBall。png’, [10,5], [50, 50])
ballGroup = pygame。sprite。Group(myBall)
clown = ClownClass()
lives = 3
#建立分數變數
score = 0
#建立分數字體物件
score_font = pygame。font。Font(None, 50)
#渲染文字到表面塊Score_surf
score_surf = score_font。render(str(score), 1, THECOLORS[‘white’])
#文字的位置
score_pos = [10, 10]
done = False
#主迴圈
running = True
while running:
clock。tick(30)
screen。fill(THECOLORS[‘black’])
for event in pygame。event。get():
if event。type == pygame。QUIT:
running = False
#如果滑鼠移動,小丑就移動
elif event。type == pygame。MOUSEMOTION:
clown。rect。centerx = event。pos[0]
#檢查小丑是否碰到小球,若碰到,速度反向,並播放聲音
if pygame。sprite。spritecollide(clown, ballGroup, False):
hit。play()
myBall。speed[1] = -myBall。speed[1]
myBall。move()
#完全重繪螢幕
if not done:
screen。blit(myBall。image, myBall。rect)
screen。blit(clown。image, clown。rect)
screen。blit(score_surf, score_pos)
#記錄玩家所剩下的機會
for i in range (lives):
width = screen。get_width()
screen。blit(myBall。image, [width - 40 * i, 20])
pygame。display。flip()
#如果球碰到底邊,就減少一次機會,並播放音樂
if myBall。rect。top >= screen。get_rect()。bottom:
if not done:
die。play()
lives = lives - 1
#當三次機會都用完時,遊戲結束,顯示玩家最後分數
if lives <= 0:
if not done:
pygame。time。delay(1000)
bye。play()
final_text1 = “遊戲結束”
final_text2 = “您最後的分數是: ” + str(score)
ft1_font = pygame。font。Font(‘C:\Windows\Fonts\simhei。ttf’,80)
ft1_surf = ft1_font。render(final_text1, 1, THECOLORS[‘white’])
ft2_font = pygame。font。Font(‘C:\Windows\Fonts\simkai。ttf’,50)
ft2_surf = ft2_font。render(final_text2, 1, THECOLORS[‘white’])
#重繪螢幕
screen。blit(ft1_surf, [screen。get_width()/2 - \
ft1_surf。get_width()/2, 100])
screen。blit(ft2_surf, [screen。get_width()/2 - \
ft2_surf。get_width()/2, 200])
pygame。display。flip()
done = True
pygame。mixer。music。fadeout(2000)
#還有機會,小球重新 開始彈跳
else:
pygame。time。delay(1000)
new_life。play()
myBall。rect。topleft = [50, 50]
screen。blit(myBall。image, myBall。rect)
pygame。display。flip()
pygame。time。delay(1000)
pygame。quit()
不知不覺,我們的旅程已接近尾聲,阿呆在此感謝大家一路的陪伴~
一切的結束,只是一個新的開始。在此別過,各位大俠,江湖再見~