他吃過苦,他什麼也不說,最好是做出幸福的樣子。

——-加繆《反與正》

咱們今天的遊戲,主角是眉(shuang)開(chong)眼(ren)笑(ge)的小丑先生。

無數的藝術作品以他為主角,他以快樂的表情、滑稽的動作為大家帶來了歡樂,但在那副笑逐顏開的面具下,究竟隱藏著什麼樣的秘密呢?

Pygame(四)---風景無限好

在這一期中,我們把前面所學的知識融合起來,編寫一個小丑頂小球的小遊戲~

這是我們本期的材料,各位看官請收好~

連結:

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’])

Pygame(四)---風景無限好

小球

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(四)---風景無限好

小丑

二、用滑鼠控制小丑運動

我們使用使用 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]

Pygame(四)---風景無限好

分數與機會次數記錄

遊戲結束後,顯示最終得分:

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’])

Pygame(四)---風景無限好

遊戲結束

五、音樂

對於不同的遊戲事件,我們需要搭配不同的音樂。總體分為兩類:背景音樂與單個事件的音樂。

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()

不知不覺,我們的旅程已接近尾聲,阿呆在此感謝大家一路的陪伴~

Pygame(四)---風景無限好

一切的結束,只是一個新的開始。在此別過,各位大俠,江湖再見~

Pygame(四)---風景無限好