Python 0基礎開發遊戲:打地鼠(詳細教程)VS code版本 一、準備工作 二、創建項目 三、可選操作 遊戲開發的思路 遊戲開發的技術點 打地鼠遊戲

如果你沒有任何編程經驗,而且想嘗試一下學習編程開發,這個系列教程一定適合你,它將帶你學習最基本的Python語法,並讓你掌握小遊戲的開發技巧。你所需要的,就是付出一些時間和耐心來嘗試這些代碼和操作。文中素材以及可執行代碼可以加羣:456926667,獲取,這個是我創建的一個針對0基礎的夥伴一個交流羣,下個文章我會更新關於pycharm版本的打地鼠。

@[top]

一、準備工作

1 下載安裝 python
2 下載安裝VS code編輯器
安裝時,要注意勾選 添加到path


3 安裝pygame模塊

  • 在VisualStudioCode的頂部菜單【Terminal-New Teminal】打開命令行終端,然後輸入命令python -m pip install --upgrade pip,回車,等待完成。
  • 然後同樣輸入命令pip install pygame,等待完成安裝,可能需要幾分鐘


二、創建項目

<meta charset="utf-8">

  1. 在桌面上創建一個文件夾mygame,然後在VSCode中使用菜單【File-Open Folder】,選擇mygame文件夾,VSCode左側將會出現EXPLORER導航欄。

  2. 在左側導航欄中,【右鍵-New File】創建文件main.py

- 將下面的代碼粘貼到右側`main.py`文件中。

import pygame
import sys
pygame.display.set_mode([600,400])
while 1:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()

  1. 運行代碼。
*   仍然【Terminal-New terminal】終端中輸入命令`python main.py`,這將運行我們上面的代碼,看到彈出一個黑色窗口。

三、可選操作

  1. 執行上面的操作的時候,VSCode的右下角會經常彈出一些提示,如果有【Install】字樣,可以放心的點擊它進行安裝更多內容。

  2. 也可以從左側欄點擊圖標打開【EXTENSIONS】,然後搜索@id:ms-python.python,點擊找到的結果,右側再點擊【Install】按鈕進行安裝。安裝之後main.py文件的右上角就會出現三角形運行按鈕,點擊它同樣可以運行代碼,相當於終端中輸入python main.py

  1. pip install ...安裝命令太慢。Windows用戶,可以從上面的網盤中下載pip.ini文件,然後在【C盤-用戶-用戶名】文件夾下面創建pip文件夾,再把下載的pip.ini文件拷貝進去,此後再運行pip install ...安裝速度就會快很多。

  2. 對於蘋果用戶就麻煩很多。先在終端執行cd ~切換到用戶文件夾,然後執行mkdir .pip創建.pip文件夾,它是隱身的,我們打開訪達,從菜單執行【前往-前往文件夾...】,前往~/.test目錄,把下載的pip.conf文件粘貼進去,搞定。

pip.ini或者pip.conf文件是把原來pip默認從國外下載安裝改成了從國內下載,所以速度會變快很多。

  • 其中import是導入我們要使用的外部代碼模塊,pygame當然是必須的,syssystem系統的簡寫,因爲我們的遊戲要運行在系統(windows或者蘋果macOS)上面,所以我們會用到系統的一些命令,比如下面的sys.exit()這個命令。

  • pyagme.display.set_mode([600,400]),這裏的[600,400]是一對數字組合在一起的,叫二元數組,這裏它表示寬600,高400的一個矩形。整句話就是設置要彈出的窗口的大小,display顯示,set設置,mode模式

  • while 1:...當是1的時候,就...,1在代碼裏面表示正確的、真的、存在的,相反,0表示錯誤、假的、不存在的。while 1:do something那麼something就會做,如果while 0: do something那麼就不會做了。

  • for ... sys.exit()這一段暫時可以不深究,只是固定格式。只要知道它表示遊戲程序運行結束的時候系統把窗口也關掉,清理好計算機不要留痕跡,exit退出

遊戲開發的思路

遊戲開發都有固定的套路,無論是打地鼠、憤怒的小鳥,還是西瓜忍者,甚至是王者榮耀這樣的大型遊戲,他們大致都遵循下面幾個思路:

  1. 創建一個地圖場景,上面可能有些道具。

    比如幾個地鼠洞,一些可以放小豬的木盒子,甚至非常複雜的山谷地形,上面還有很多野怪。
    這些地圖上的元素一般都是被動的,就是你不去靠近或招惹野怪的話,它們不會互相打起來自相殘殺,同樣,小鳥還沒發射的時候,木盒子也不會自己倒塌。

  2. 創建至少一個玩家可以控制的元素,它可以和地圖場景發生交互。

    這個可以被控制的元素我們稱爲玩家角色。在打地鼠遊戲中這個角色就是一個錘子,憤怒的小鳥中這個角色其實是彈弓,彈出的小鳥其實是個道具,在王者榮耀遊戲中玩家的角色就是自己的英雄。

  3. 必須要有評判標準,用來衡量輸贏勝敗。

    玩家控制的角色和地圖場景進行交互,發生反應,對應的也必須要有一個評判標準,比如計算3分鐘內擊中地鼠的次數,或者計算砸死的綠豬的數量,或者是打野怪獲得的經驗,這些規則一定要清晰而且不能互相矛盾。
    大多數遊戲都有輸贏勝敗,而勝敗往往本質上只是誰的積分首先達到某個臨界點。可以是某個關鍵道具的變化,比如對戰遊戲中塔被摧毀,也可以是玩家角色的屬性變化,比如格鬥遊戲中被擊殺;也可以只是純粹的某項積分評比,用排行榜代替輸贏。

遊戲開發的技術點

  1. 要能夠在窗口內繪製圖形。

    可以是直接用代碼繪製幾何圖形,也可以是載入圖片顯示內容。

  2. 要能用代碼控制每個元素(道具和角色)的動畫。

    動畫就是一組圖片不停地輪番變化。要能用代碼控制播放和停止每個元素的動畫,還能在不同動畫之間快速切換。

  3. 能夠接收用戶的控制,並藉此影響遊戲中的元素。

    知道用戶什麼時候按了鍵盤,什麼時候點了鼠標,按了哪個按鍵,鼠標左鍵還是右鍵?我們經常把這些操作稱之爲交互事件。

  4. 能夠對遊戲中各種元素產生的有效數據進行計算和管理。

    玩家角色一刀砍下去,怪物的血量減少了100點,這個就是數據,而且是很有用的數據,沒有這個數據的話怪物可能永遠砍不死了。
    有時候這些數據要保存好,讓用戶下一次打開遊戲的時候仍然看到自己的等級和裝備都還存在。有些時候這些數據要及時清理,比如新的一局又開始了,地圖上的道具和角色都要恢復原樣。

打地鼠遊戲

我們可以把經典的打地鼠遊戲簡化概括爲:

  • 地圖和道具:隨機位置出現地鼠圖形
  • 交互角色:控制錘子圖形,點擊地鼠圖形使其消失
  • 積分輸贏:限定時間內擊中地鼠圖形的次數

核心玩法簡化成一句話就是:點擊隨機出現圖形。

繪製地鼠

我們用一個藍色的圓形代表地鼠。那怎麼在窗口中繪製一個圓形呢?

可以百度【pygame 畫圓圈】類似的關鍵字,可以查到要使用pygame.draw.circle語句,它的具體語法可以從官方說明文檔中找到,英文版詳細說明點這裏。

我們查到它的語法是:

pygame.draw.circle()
circle(surface, color, center, radius) -> Rect

這表示draw.circle()需要四個參數,分別是surface表面,color顏色,center中心點,radius半徑

我們繼續看surface參數的說明:

surface (Surface) -- surface to draw on

聽上去像是畫布,——先要有個畫布才能在上面畫圓。
點擊Surface鏈接,找到更進一步說明:

Surface((width, height), flags=0, depth=0, masks=None) -> Surface

結尾的->Surface表示Surface((width....)這句話可以生成一個Surface表面,我們可以用下面的語句捕捉到這個生成的表面:

sur=pygame.Surface((600, 400)

這樣,sur就是我們生成的表面了。

顏色和位置

再返回來看color參數:

color (Color or int or tuple(int, int, int, [int])) 
-- color to draw with, 
the alpha value is optional if using a tuple (RGB[A])

很明顯它是表示畫什麼顏色的圓。tuple(int, int, int, [int])表示這裏需要三個整數int一起表示顏色,RGB是指red紅,green綠,blue藍,alpha透明度

clr=(0,0,255) #藍色

對於center中心位置我們也可以用同樣的方法得到,這裏的Vector2表示二元向量,及橫向x和豎向y的位置:

pos=pygame.vector2(300,200) #窗口中央

繪製圓形

參數都具備了,那麼就可以開始畫圓了。運行下面的代碼:

import pygame
import sys

pygame.init()  # 初始化
window = pygame.display.set_mode([600, 400])  # 設定窗口

sur = pygame.Surface([600, 400])  # 繪製背景容器
clr = (0, 0, 255)
pos = (300,200)
rad = 100

while 1:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()

    # 每幀循環執行的代碼
    pygame.draw.circle(sur, clr, pos, 100# 繪製圓

    # 刷新畫面
    window.blit(sur, (0, 0))
    pygame.display.flip()

注意這裏最底部刷新畫面的兩行,其中window.blit(sur, (0, 0))表示把我們繪製好的表面sur刷新到window窗口中;pygame.display.flip()表示進行窗口刷新。

隨機出現

隨機出現就是隨機位置,我們必須確保每一次花圓的pos位置都不同,而且應該是固定的幾個地鼠洞位置。——別忘了我們要做打地鼠遊戲。

假設有6個地鼠位置pos分別是[200,200],[300,200],[400,200],[200,300],[300,300],[400,300],那麼如何隨機取到6箇中一個呢?也就是如何隨機取到1~6其中的一個數字即可。

我們可以百度【python 隨機數】查到需要使用random模塊,這是python自帶的模塊,不需要再重新pip install
如果搜索【python random document】可以查找到官方的語法說明,如下:

random.randint(a, b)
Return a random integer N such that a <= N <= b. 
Alias for randrange(a, b+1).

這是說可以隨機生成ab之間的一個數字。也可以從中文的菜鳥教程網
學習到這個知識。

新建一個test.py文件,我們進行測試:

import random
a = random.randint(0, 5)
print(a)

每次運行都能生成不同的數字。

繼續測試:

import random
a = random.randint(0, 6)
pos6=[[200,200],[300,200],[400,200],[200,300],[300,300],[400,300]]
print(pos6[a])

這裏的pos6[a]表示pos6的六個位置中的第a個。運行這個代碼就會每次生成不同的位置。

測試成功之後我們把它拷貝到剛纔的畫圓代碼中,得到:

import pygame
import sys
import random

pygame.init()  # 初始化
window = pygame.display.set_mode([600, 400])  # 設定窗口

sur = pygame.Surface([600, 400])  # 繪製背景容器
clr = (0, 0, 255)
pos6 = [[200, 200], [300, 200], [400, 200], [
    200, 300], [300, 300], [400, 300]]  # !!六個位置
rad = 100

while 1:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()

    # 每幀循環執行的代碼
    sur.fill((0, 0, 0))  # !!用黑色覆蓋前一幀的畫面,實現刷新
    a = random.randint(0, 5)  # !!隨機0到5
    pygame.draw.circle(sur, clr, pos6[a], 100)  # !!使用隨機位置

    # 刷新畫面
    window.blit(sur, (0, 0))
    pygame.display.flip()

注意新增了sur.fill...一行,這是用黑色(0,0,0)來清理掉上一幀的內容,避免出現多個圓。

隔n幀刷新

上面的代碼運行之後會看到藍色的圓四處亂跳,太快了,我們希望改變位置之後能停一下,等我們錘它。

我們需要畫面的圓每隔n幀再隨機變換一次,而不是現在的每幀都隨機變。思路是這樣的:我們設定一個計數器,開始是0,每幀都給它增加1,就是0,1,2,3,4...直到它增到到超過50,這時候我們就改變圓的位置並同時把計數器重置爲0。

代碼如下:

import pygame
import sys
import random

pygame.init()  # 初始化
window = pygame.display.set_mode([600, 400])  # 設定窗口

sur = pygame.Surface([600, 400])  # 繪製背景容器
clr = (0, 0, 255)
pos6 = [[200, 200], [300, 200], [400, 200], [
    200, 300], [300, 300], [400, 300]]  # 六個位置
rad = 100
tick=0 #!!計數器

while 1:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()

    # 每幀循環執行的代碼
    if tick>50: #每50次刷新變換一次
        sur.fill((0, 0, 0))  # 用黑色覆蓋前一幀的畫面,實現刷新
        a = random.randint(0, 5)  # 隨機0到5
        pygame.draw.circle(sur, clr, pos6[a], 100)  # 使用隨機位置
        tick=0
    else: #!!不刷新變換的時候
        tick=tick+1 #!!增加計數器

    # 刷新畫面
    window.blit(sur, (0, 0))
    pygame.display.flip()

增加交互點擊

當用戶點擊畫面的時候,我們要知道它點擊了哪裏,是否點擊到了我們畫的圓上面。

百度搜索【pygame 點擊】可以找到相關資源,也可以直接在官方說明文檔中找到

思路是我們添加對event.type事件類型的實時監測,一旦發現點擊事件就獲取位置座標。代碼如下:

import pygame
import sys
import random
from pygame.locals import *  # 引入鼠標事件類型

pygame.init()  # 初始化
window = pygame.display.set_mode([600, 400])  # 設定窗口

sur = pygame.Surface([600, 400])  # 繪製背景容器
clr = (0, 0, 255)
pos6 = [[200, 200], [300, 200], [400, 200], [
    200, 300], [300, 300], [400, 300]]  # 六個位置
rad = 100
tick = 0  # !!計數器
pos = pos6[0]  # !!在外面記錄圓的位置

while 1:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == MOUSEBUTTONDOWN:  # !!如果是鼠標按下事件
            mpos = pygame.mouse.get_pos()  # !!獲取鼠標位置
            print(mpos)

    # 每幀循環執行的代碼
    if tick > 50:  # 每50次刷新變換一次
        sur.fill((0, 0, 0))  # 用黑色覆蓋前一幀的畫面,實現刷新
        a = random.randint(0, 5)  # 隨機0到5
        pos = pos6[a]  # !!更新外部記錄的圓的位置
        pygame.draw.circle(sur, clr, pos, 100)  # !!使用隨機位置
        tick = 0  # 重置計數器
    else:  # !!不刷新變換的時候
        tick = tick+1  # !!增加計數器

    # 刷新畫面
    window.blit(sur, (0, 0))
    pygame.display.flip()

運行這個代碼,任意點擊屏幕上的時候就會打印出檔期鼠標點擊的位置。

距離測量

知道當前圓的位置pos,也知道當前點擊的位置mpos,這樣我們就可以計算出兩點之間的距離,距離大於圓半徑的就是沒有點到地鼠,距離小於半徑的就是點到地鼠了。

百度搜索【pygame 兩點距離】可以搜到一些計算距離的方法,我們這裏使用pygame官方提供的方法,測試下面代碼:

import pygame
a=pygame.math.Vector2.length(pygame.math.Vector2(3,4))
print(a)

它會輸出5(勾三股四玄五)。這裏的(3,4)posmpos相減得到的差。
把這個思路帶入原來的代碼,得到:

import pygame
import sys
import random
from pygame.locals import *  # 引入鼠標事件類型

pygame.init()  # 初始化
window = pygame.display.set_mode([600, 400])  # 設定窗口

sur = pygame.Surface([600, 400])  # 繪製背景容器
clr = (0, 0, 255)
pos6 = [[200, 200], [300, 200], [400, 200], [
    200, 300], [300, 300], [400, 300]]  # 六個位置
rad = 50
tick = 0  # 計數器
pos = pos6[0]  # 外面記錄圓的位置

while 1:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == MOUSEBUTTONDOWN:  # 如果是鼠標按下事件
            mpos = pygame.mouse.get_pos()  # 獲取鼠標位置
            dis = pygame.math.Vector2(
                mpos[0]-pos[0], mpos[1]-pos[1])  # !!計算座標差
            len = pygame.math.Vector2.length(dis)  # !!計算距離
            if len < rad:
                tick = 51  # !!立即變換位置

    # 每幀循環執行的代碼
    if tick > 50:  # 每50次刷新變換一次
        sur.fill((0, 0, 0))  # 用黑色覆蓋前一幀的畫面,實現刷新
        a = random.randint(0, 5)  # 隨機0到5
        pos = pos6[a]  # 更新外部記錄的圓的位置
        pygame.draw.circle(sur, clr, pos, 100)  # 使用隨機位置
        tick = 0  # 重置計數器
    else:  # 不刷新變換的時候
        tick = tick+1  # 增加計數器

    # 刷新畫面
    window.blit(sur, (0, 0))
    pygame.display.flip()

在這裏我們設定如果距離長度len小於圓半徑rad,那麼就立即設置tick=51使它大於50,立即進行隨機位置變換。

截止到這裏運行上面的代碼,可以實現隨機出現地鼠(圓)並能夠點擊使它消失,這也實現了遊戲的最基本邏輯功能。後續我們將進一步編寫更多內容,讓它更完善一些。

記錄分數

計算數字增加很容易,設定一個score=0,然後擊中地鼠的時候增加1就可以了。但是,如何把它顯示到屏幕上呢?

可以百度搜索【pygame 顯示文字】然後就可以找到大致方法,我們先進行一些測試:

import pygame

pygame.init()  # 初始化
window = pygame.display.set_mode([600, 400])  # 設定窗口

# 顯示文字
pygame.font.init()  # !!初始化文字
font = pygame.font.SysFont('微軟雅黑', 30)  # !!設定字體和字號
sur = font.render("Hello World!!{}".format(999), False, (255, 0, 0))  # !!生成w文字表面

while 1:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()

    window.blit(sur, (200, 10))  # !!增加分數表面
    pygame.display.flip()

這段代碼中可以看到pygame繪製文字分三步:

  • pygame.font.init()先要初始化
  • pygame.font.SysFont('微軟雅黑', 30)設定字體和字號大小
  • font.render("Hello World!!{}".format(999), False, (255, 0, 0))生成一個Surface表面
    當然,最後別忘了把表面放到窗口裏window.blit(sur, (200, 10))

運行上面的代碼得到一個窗口如下:

我們根據這個經驗改進的代碼:

import pygame
import sys
import random
from pygame.locals import *  # 引入鼠標事件類型

pygame.init()  # 初始化
window = pygame.display.set_mode([600, 400])  # 設定窗口

sur = pygame.Surface([600, 400])  # 繪製背景容器
clr = (0, 0, 255)
pos6 = [[200, 200], [300, 200], [400, 200], [
    200, 300], [300, 300], [400, 300]]  # 六個位置
rad = 50
tick = 0  # 計數器
pos = pos6[0]  # 外面記錄圓的位置

# 分數
score = 0  # !!分數計數
pygame.font.init()  # !!初始化文字
score_font = pygame.font.SysFont('微軟雅黑', 30)  # !!設定字體和字號
score_sur = score_font.render(str(score), False, (255, 0, 0))  # !!生成計數表面

while 1:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == MOUSEBUTTONDOWN:  # 如果是鼠標按下事件
            mpos = pygame.mouse.get_pos()  # 獲取鼠標位置
            dis = pygame.math.Vector2(
                mpos[0]-pos[0], mpos[1]-pos[1])  # 計算座標差
            len = pygame.math.Vector2.length(dis)  # 計算距離
            if len < rad:
                tick = 1000  # 立即變換位置
                score = score+1  # 計分增加

    # 每幀循環執行的代碼
    if tick > 50:  # 每50次刷新變換一次
        score_sur = score_font.render(
            str(score), False, (255, 0, 0))  # !!重新生成分數文字表面
        sur.fill((0, 0, 0))  # 用黑色覆蓋前一幀的畫面,實現刷新
        a = random.randint(0, 5)  # 隨機0到5
        pos = pos6[a]  # 更新外部記錄的圓的位置
        pygame.draw.circle(sur, clr, pos, 50)  # 使用隨機位置
        tick = 0  # 重置計數器
    else:  # 不刷新變換的時候
        tick = tick+1  # 增加計數器

    # 刷新畫面
    window.blit(sur, (0, 0))
    window.blit(score_sur, (200, 10))  # !!增加分數表面
    pygame.display.flip()

運行上面的代碼,可以用鼠標點擊跳動的藍色圓,每次擊中就能獲得1分,實時顯示在頂部。

關於文字的更多內容可以參考官方文檔說明

鼠標指針變錘子

現在窗口中顯示的仍然是鼠標,而不是錘子,下面我們來看如何把鼠標變爲一個特定的圖形。

pygame關於鼠標控制的模塊是pygame.mouse官方說明文檔看這裏。

我們可以用pygame.mouse.set_visible(False)來隱藏鼠標,但這樣一來我們就看不到鼠標無法操作了。

不過不要緊,我們之前還記得當鼠標點擊的時候有一個mpos = pygame.mouse.get_pos()可以獲取當前鼠標的位置,同樣我們可以在鼠標移動的時候獲取鼠標的位置,然後在這個位置上畫一個紅色圓圈代表鼠標。

測試下面的代碼:

import pygame
from pygame.locals import *

pygame.init()
window = pygame.display.set_mode([600, 400])

pygame.mouse.set_visible(False)  # 隱藏鼠標
sur = pygame.Surface([600, 400])
mpos = [300, 200]  # 記錄鼠標位置

while 1:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == MOUSEMOTION:  # 當鼠標移動的時候
            mpos = pygame.mouse.get_pos()  # 更新鼠標位置

    sur.fill((0, 0, 0))  # 填充黑色
    pygame.draw.circle(sur, (255, 0, 0), mpos, 10)  # 在鼠標位置畫紅色圓
    window.blit(sur, (0, 0))
    pygame.display.flip()

運行這個代碼將,當鼠標劃到窗口上面的時候就會有一個紅點跟着鼠標移動,紅點代替了原來的指針。

我們把這個紅點鼠標代碼放入到遊戲中,得到下面的代碼:

import pygame
import sys
import random
from pygame.locals import *  # 引入鼠標事件類型

pygame.init()  # 初始化
window = pygame.display.set_mode([600, 400])  # 設定窗口

sur = pygame.Surface([600, 400])  # 繪製背景容器
clr = (0, 0, 255)
pos6 = [[200, 200], [300, 200], [400, 200], [
    200, 300], [300, 300], [400, 300]]  # 六個位置
rad = 50
tick = 0  # 計數器
pos = pos6[0]  # 外面記錄圓的位置

# 分數
score = 0  # 分數計數
pygame.font.init()  # 初始化文字
score_font = pygame.font.SysFont('微軟雅黑', 30)  # !!設定字體和字號
score_sur = score_font.render(str(score), False, (255, 0, 0))  # !!生成計數表面

# 鼠標
pygame.mouse.set_visible(False)  # !!隱藏鼠標
mpos = [300, 200]  # !!記錄鼠標位置

while 1:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == MOUSEBUTTONDOWN:  # 如果是鼠標按下事件
            mpos = pygame.mouse.get_pos()  # 獲取鼠標位置
            dis = pygame.math.Vector2(
                mpos[0]-pos[0], mpos[1]-pos[1])  # 計算座標差
            len = pygame.math.Vector2.length(dis)  # 計算距離
            if len < rad:
                tick = 1000  # 立即變換位置
                score = score+1  # 計分增加
        elif event.type == MOUSEMOTION:  # !!當鼠標移動的時候
            mpos = pygame.mouse.get_pos()  # !!更新鼠標位置

    # 每幀循環執行的代碼
    if tick > 50:  # 每50次刷新變換一次
        score_sur = score_font.render(
            str(score), False, (255, 0, 0))  # 重新生成分數文字表面        
        a = random.randint(0, 5)  # 隨機0到5
        pos = pos6[a]  # 更新外部記錄的圓的位置        
        tick = 0  # 重置計數器
    else:  # 不刷新變換的時候
        tick = tick+1  # 增加計數器

    # 繪製鼠標
    sur.fill((0, 0, 0))  # !用黑色覆蓋前一幀的畫面,實現刷新
    pygame.draw.circle(sur, clr, pos, 50)  # !使用隨機位置畫地鼠
    pygame.draw.circle(sur, (255, 0, 0), mpos, 10)  # !!在鼠標位置畫紅色圓

    # 刷新畫面
    window.blit(sur, (0, 0))
    window.blit(score_sur, (200, 10))  # 增加分數表面
    pygame.display.flip()

主義者了把sur.fill和原來畫地鼠藍圓的代碼移到了下面,和畫鼠標紅點的代碼放在了一起,這樣把繪圖內容放在一起更加合理。

限定每局時間

我們有很多辦法限定每局的長度,比如計時限定1分鐘,或者限定地鼠跳出總計100次。我們這裏使用第二種限制,跳出100次就結束並統計分數。

添加一個計數器times=0,然後每次隨機位置都給它增加1,當times>100的時候,我們就結束遊戲並顯示結束畫面統計戰果。

具體的代碼沒有新的內容,不多解釋,直接上結果:

import pygame
import sys
import random
from pygame.locals import *  # 引入鼠標事件類型

pygame.init()  # 初始化
window = pygame.display.set_mode([600, 400])  # 設定窗口

sur = pygame.Surface([600, 400])  # 繪製背景容器
clr = (0, 0, 255)
pos6 = [[200, 200], [300, 200], [400, 200], [
    200, 300], [300, 300], [400, 300]]  # 六個位置
rad = 50
tick = 0  # 計數器
pos = pos6[0]  # 外面記錄圓的位置

# 分數
score = 0  # 分數計數
pygame.font.init()  # 初始化文字
score_font = pygame.font.SysFont('微軟雅黑', 30)  # !!設定字體和字號
score_sur = score_font.render(str(score), False, (255, 0, 0))  # !!生成計數表面

# 鼠標
pygame.mouse.set_visible(False)  # !!隱藏鼠標
mpos = [300, 200]  # !!記錄鼠標位置

times = 0  # 地鼠跳出的次數
times_max=10 #最多次數
tick_max=15 #地鼠每次跳多少幀

while 1:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == MOUSEBUTTONDOWN:  # 如果是鼠標按下事件
            mpos = pygame.mouse.get_pos()  # 獲取鼠標位置
            dis = pygame.math.Vector2(
                mpos[0]-pos[0], mpos[1]-pos[1])  # 計算座標差
            len = pygame.math.Vector2.length(dis)  # 計算距離
            if len < rad:
                tick = 1000  # 立即變換位置
                score = score+1  # 計分增加
        elif event.type == MOUSEMOTION:  # !!當鼠標移動的時候
            mpos = pygame.mouse.get_pos()  # !!更新鼠標位置

        if times > times_max:
            # 顯示結束畫面
            sur.fill((0, 0, 0))
            pygame.mouse.set_visible(True) 
            sur.fill((0, 0, 0)) 
            end_font = pygame.font.SysFont('微軟雅黑', 80)  # !!設定字體和字號
            end_sur = score_font.render("Your Score is:{}/{}!".format(score,times_max), False, (255, 0, 0))  # !!生成計數表面
            window.blit(sur, (0, 0))
            window.blit(end_sur, (100, 100))  # 增加分數表面
            pygame.display.flip()
        else:
            # 每幀循環執行的代碼
            if tick > tick_max:  # 每50次刷新變換一次
                times=times+1 #增加計次
                score_sur = score_font.render(
                    str(score), False, (255, 0, 0))  # 重新生成分數文字表面        
                a = random.randint(0, 5)  # 隨機0到5
                pos = pos6[a]  # 更新外部記錄的圓的位置        
                tick = 0  # 重置計數器
            else:  # 不刷新變換的時候
                tick = tick+1  # 增加計數器

            # 繪製鼠標
            sur.fill((0, 0, 0))  # !用黑色覆蓋前一幀的畫面,實現刷新
            pygame.draw.circle(sur, clr, pos, 50)  # !使用隨機位置畫地鼠
            pygame.draw.circle(sur, (255, 0, 0), mpos, 10)  # !!在鼠標位置畫紅色圓

            # 刷新畫面
            window.blit(sur, (0, 0))
            window.blit(score_sur, (200, 10))  # 增加分數表面
            pygame.display.flip()

運行這個代碼,用鼠標點擊藍圓,藍圓跳動10次之後結束,然後顯示擊中的次數。你可以通過調整tick_max的數字讓圓跳動的更快或更慢,調整times_max=100來讓地鼠跳動100次後再結束。

現在我們的地鼠遊戲已經有些模樣了,但還都是藍色紅色的圓圈和圓點,下一篇我們來改變成爲圖片。

中文字體

在上一節中我們只使用了英文字體,怎麼顯示中文字體呢?

直接下載網盤裏面的文件,放在你的main.py一起,將原來的

score_font = pygame.font.SysFont('微軟雅黑', 30)

修改爲:

score_font = pygame.font.Font('MicrosoftYaqiHeiLight-2.ttf', 30) 

然後在render裏面使用中文就可以正常顯示了:

end_sur = score_font.render("你的得分:{}/{}!".format(score,times_max), False, (255, 0, 0))

另外,也可以使用系統的中文字體,但是我們不清楚系統裏面到底裝了哪些字體,可以用print(pygame.font.get_fonts())將所有系統字體都打印出來,然後只能從名字猜出哪些是中文字體了,注意系統字體還是要用font.SysFont而不只是font.Font

顯示背景圖片

這是我們的背景圖片dds-map.jpg

我們可以用map=pygame.image.load('dds-map.jpg')把圖片讀取到代碼裏面。
更多官方關於圖片的操作說明看這裏
注意pygame.image.load()得到的是一個表面surface,我們可以直接把它blit到窗口wind,也可以把它blit到。

這裏是完整代碼:

import pygame
import sys
import random
from pygame.locals import *  # 引入鼠標事件類型

pygame.init()  # 初始化
window = pygame.display.set_mode([600, 400])  # 設定窗口

sur = pygame.Surface([600, 400])  # 繪製背景容器
clr = (0, 0, 255)
posAll = [[100, 150], [300, 150], [500, 150], [
    200, 300], [400, 300]]  # 六個位置
rad = 50
tick = 0  # 計數器
pos = posAll[0]  # 外面記錄圓的位置

# 分數
score = 0  # 分數計數
pygame.font.init()  # 初始化文字
score_font = pygame.font.Font('MicrosoftYaqiHeiLight-2.ttf', 30)  # !!設定字體和字號
score_sur = score_font.render(str(score), False, (255, 0, 0))  # !!生成計數表面

# 鼠標
pygame.mouse.set_visible(False)  # !!隱藏鼠標
mpos = [300, 200]  # !!記錄鼠標位置

times = 0  # 地鼠跳出的次數
times_max=10 #最多次數
tick_max=30 #地鼠每次跳多少幀
map=pygame.image.load('dds-map.jpg')#!!讀取圖片

while 1:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == MOUSEBUTTONDOWN:  # 如果是鼠標按下事件
            dis = pygame.math.Vector2(
                mpos[0]-pos[0], mpos[1]-pos[1])  # 計算座標差
            len = pygame.math.Vector2.length(dis)  # 計算距離
            if len < rad:
                tick = 1000  # 立即變換位置
                score = score+1  # 計分增加
        elif event.type == MOUSEMOTION:  # 當鼠標移動的時候
            mpos = pygame.mouse.get_pos()  # 更新鼠標位置        

    if times >= times_max:
        # 顯示結束畫面
        sur.fill((0, 0, 0)) #!!結束時候仍然用黑色清空畫面
        pygame.mouse.set_visible(True) 
        end_font = pygame.font.Font('MicrosoftYaqiHeiLight-2.ttf',48) # !!設定字體和字號
        end_sur = score_font.render("你的分數是:{}/{}!".format(score,times_max), True, (255, 0, 0))  # !!生成計數表面
        window.blit(sur, (0, 0))
        window.blit(end_sur, (100, 100))  # 增加分數表面
    else:
        sur.blit(map, (0, 0)) #!!添加背景圖片
        # 每幀循環執行的代碼
        if tick > tick_max:  # 每50次刷新變換一次
            times=times+1 #增加計次
            score_sur = score_font.render(
                "分數:{}/{}!".format(score,times), False, (255, 0, 0))  # 重新生成分數文字表面        
            a = random.randint(0, 4)  # 隨機0到4
            pos = posAll[a]  # 更新外部記錄的圓的位置        
            tick = 0  # 重置計數器
        else:  # 不刷新變換的時候
            tick = tick+1  # 增加計數器      

        # 繪製鼠標
        pygame.draw.circle(sur, clr, pos, 50)  # 使用隨機位置畫地鼠            
        pygame.draw.circle(sur, (255, 0, 0), mpos, 10)  # !在鼠標位置畫紅色圓

    # 刷新畫面            
    window.blit(sur, (0, 0))
    window.blit(score_sur, (200, 10))  # 增加分數表面
    pygame.display.flip() #刷新畫面

注意我們先把圖片讀取,然後在每幀裏面決定是否使用。運行後如下圖:

使用動態圖片

地鼠和錘子各有兩個狀態,正常的地鼠和被擊打的地鼠,正常的錘子和砸下的錘子,如下圖所示(下圖無法直接使用,請從網盤下載):

我們可以先把四個圖片都load讀取進來成爲rat1,rat2,ham1,ham2,然後我們使用ratsurhamsur表示真正要使用的表面,當鼠標按下的時候我們設定hamsur=ham2是砸下圖片,當鼠標點擊位置距離地鼠小於地鼠半徑的時候我們使用ratsur=rat2被砸中的圖片。最後我們再分別把地鼠和錘頭blitsur上面。

改造後的代碼如下:

import pygame
import sys
import random
from pygame.locals import *  # 引入鼠標事件類型
import time

pygame.init()  # 初始化
window = pygame.display.set_mode([600, 400])  # 設定窗口

sur = pygame.Surface([600, 400])  # 繪製背景容器
clr = (0, 0, 255)
posAll = [[100, 150], [300, 150], [500, 150], [
    200, 300], [400, 300]]  # 六個位置
rad = 50
tick = 0  # 計數器
pos = posAll[0]  # 外面記錄圓的位置

# 分數
score = 0  # 分數計數
pygame.font.init()  # 初始化文字
score_font = pygame.font.Font('MicrosoftYaqiHeiLight-2.ttf', 30)  # !!設定字體和字號
score_sur = score_font.render(str(score), False, (255, 0, 0))  # !!生成計數表面

# 鼠標
pygame.mouse.set_visible(False)  # !!隱藏鼠標
mpos = [300, 200]  # !!記錄鼠標位置

times = 0  # 地鼠跳出的次數
times_max=10 #最多次數
tick_max=30 #地鼠每次跳多少幀
map=pygame.image.load('dds-map.jpg')#!!讀取圖片
rat1=pygame.image.load('rat1.png')#!!讀取地鼠圖片
rat2=pygame.image.load('rat2.png')#!!讀取被砸地鼠圖片
ham1=pygame.image.load('hammer1.png')#!!讀取錘子圖片
ham2=pygame.image.load('hammer2.png')#!!讀取砸下錘子圖片

while 1:
    hamsur=ham1
    ratsur=rat1
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == MOUSEBUTTONDOWN:  # 如果是鼠標按下事件
            hamsur=ham2 #!!使用下落錘子
            mpos = pygame.mouse.get_pos()  # 獲取鼠標位置
            dis = pygame.math.Vector2(
                mpos[0]-pos[0], mpos[1]-pos[1])  # 計算座標差
            len = pygame.math.Vector2.length(dis)  # 計算距離
            if len < rad:
                tick = 1000  # 立即變換位置
                score = score+1  # 計分增加
                ratsur=rat2 #!!使用被砸地鼠
        elif event.type == MOUSEMOTION:  # 當鼠標移動的時候
            mpos = pygame.mouse.get_pos()  # 更新鼠標位置        

    if times >= times_max:
        # 顯示結束畫面
        sur.fill((0, 0, 0)) #結束時候仍然用黑色清空畫面
        pygame.mouse.set_visible(True) 
        end_font = pygame.font.Font('MicrosoftYaqiHeiLight-2.ttf',48) # !!設定字體和字號
        end_sur = score_font.render("你的分數是:{}/{}!".format(score,times_max), True, (255, 0, 0))  # !!生成計數表面
        window.blit(sur, (0, 0))
        window.blit(end_sur, (100, 100))  # 增加分數表面
    else:
        sur.blit(map, (0, 0)) #添加背景圖片
        # 每幀循環執行的代碼
        if tick > tick_max:  # 每50次刷新變換一次
            times=times+1 #增加計次
            score_sur = score_font.render(
                "分數:{}/{}!".format(score,times), False, (255, 0, 0))  # 重新生成分數文字表面        
            a = random.randint(0, 4)  # 隨機0到4
            pos = posAll[a]  # 更新外部記錄的圓的位置        
            tick = 0  # 重置計數器
        else:  # 不刷新變換的時候
            tick = tick+1  # 增加計數器

        sur.blit(ratsur,(pos[0]-50,pos[1]-70)) #繪製地鼠
        sur.blit(hamsur,(mpos[0]-50,mpos[1]-100)) #繪製錘頭

    # 刷新畫面            
    window.blit(sur, (0, 0))
    window.blit(score_sur, (200, 10))  # 增加分數表面
    pygame.display.flip() #刷新畫面
    time.sleep(0.04) #!!保持畫面一點時間

注意這裏的import timetime.sleep(0.04)這是讓每一幀停留一點點時間,0.04秒,每秒25幀(假設每幀畫圖不需要時間的話)。
另外我們再blit的時候使用了(pos[0]-50,pos[1]-50)這樣的偏移,因爲圖片總是用左上角作爲位置的起點,這樣偏移之後就變到了圖片中心,實際上我們又故意讓地鼠和錘子更高一些,就使用了(pos[0]-50,pos[1]-70)

運行之後的樣子如下圖:

讓遊戲重新開始

每次顯示最終成績之後,能不能讓遊戲3秒後重新開始呢?

我們設定一個gameover=0,遊戲結束後每幀都增加這個數字,如果gameover>100,就是過了100幀,那麼我們就重新開始。
重新開始必須意味着各種數據(分數,計時什麼的)和畫面都要重置到原來的狀態。
修改後的整體代碼如下:

import pygame
import sys
import random
from pygame.locals import *  # 引入鼠標事件類型
import time

pygame.init()  # 初始化
window = pygame.display.set_mode([600, 400])  # 設定窗口

sur = pygame.Surface([600, 400])  # 繪製背景容器
clr = (0, 0, 255)
posAll = [[100, 150], [300, 150], [500, 150], [200, 300], [400, 300]]  # 六個位置
rad = 50
tick = 0  # 計數器
pos = posAll[0]  # 外面記錄圓的位置

# 分數
score = 0  # 分數計數
pygame.font.init()  # 初始化文字
score_font = pygame.font.Font("MicrosoftYaqiHeiLight-2.ttf", 30)  # !!設定字體和字號
score_sur = score_font.render(str(score), False, (255, 0, 0))  # !!生成計數表面

# 鼠標
pygame.mouse.set_visible(False)  # !!隱藏鼠標
mpos = [300, 200]  # !!記錄鼠標位置

times = 0  # 地鼠跳出的次數
times_max = 10  # 最多次數
tick_max = 30  # 地鼠每次跳多少幀
map = pygame.image.load("dds-map.jpg")  # !!讀取圖片
rat1 = pygame.image.load("rat1.png")  # !!讀取地鼠圖片
rat2 = pygame.image.load("rat2.png")  # !!讀取被砸地鼠圖片
ham1 = pygame.image.load("hammer1.png")  # !!讀取錘子圖片
ham2 = pygame.image.load("hammer2.png")  # !!讀取砸下錘子圖片

gameover = 0 #!!結束計時
gameover_max = 100 #!!結束計時最大值,超過這個值就重新開始

while 1:
    hamsur = ham1
    ratsur = rat1
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == MOUSEBUTTONDOWN:  # 如果是鼠標按下事件
            hamsur = ham2  # !!使用下落錘子
            mpos = pygame.mouse.get_pos()  # 獲取鼠標位置
            dis = pygame.math.Vector2(mpos[0] - pos[0], mpos[1] - pos[1])  # 計算座標差
            len = pygame.math.Vector2.length(dis)  # 計算距離
            if len < rad:
                tick = 1000  # 立即變換位置
                score = score + 1  # 計分增加
                ratsur = rat2  # !!使用被砸地鼠
        elif event.type == MOUSEMOTION:  # 當鼠標移動的時候
            mpos = pygame.mouse.get_pos()  # 更新鼠標位置

    if times >= times_max:
        # 顯示結束畫面
        sur.fill((0, 0, 0))  # 結束時候仍然用黑色清空畫面
        pygame.mouse.set_visible(True)
        end_font = pygame.font.Font("MicrosoftYaqiHeiLight-2.ttf", 48)  # !!設定字體和字號
        end_sur = score_font.render(
            "你的分數是:{}/{}!".format(score, times_max), True, (255, 0, 0)
        )  # !!生成計數表面
        sur.blit(end_sur, (100, 150))
        cd = int((gameover_max - gameover) / 10)
        cd_sur = score_font.render(
            "重新開始倒計時{}".format(cd), True, (255, 0, 0)
        )  # !!生成計數表面
        sur.blit(cd_sur, (100, 200))  # 增加分數表面
        gameover = gameover + 1 #!!增加結束計時
    else:
        sur.blit(map, (0, 0))  # 添加背景圖片
        score_sur = score_font.render(
            "分數:{}/{}!".format(score, times + 1), False, (255, 0, 0)
        )  # 重新生成分數文字表面
        sur.blit(score_sur, (200, 10))  # 增加分數表面
        if tick > tick_max:  # 每50次刷新變換一次
            times = times + 1  # 增加計次
            a = random.randint(0, 4)  # 隨機0到4
            pos = posAll[a]  # 更新外部記錄的圓的位置
            tick = 0  # 重置計數器
        else:  # 不刷新變換的時候
            tick = tick + 1  # 增加計數器
        if tick > 5:  # 開始幾幀不顯示地鼠
            sur.blit(ratsur, (pos[0] - 50, pos[1] - 70))  # 繪製地鼠
        sur.blit(hamsur, (mpos[0] - 50, mpos[1] - 100))  # 繪製錘頭

    # 刷新畫面
    window.blit(sur, (0, 0))
    pygame.display.flip()  # 刷新畫面
    time.sleep(0.04)  # !!保持畫面一點時間

    # !!重置遊戲
    if gameover > gameover_max:
        pygame.mouse.set_visible(False)
        times = 0
        score = 0
        gameover = 0

運行這個代碼就能反覆玩遊戲了。
到這裏遊戲看上去好了很多,但是還沒有背景音樂,打地鼠的時候也沒有音效,下一節我們繼續添加聲音。

添加音效

遊戲裏面的聲音分爲兩種,一種叫音樂music,另一種叫音效sound。背景音樂是music,遊戲裏面的擊打聲點擊聲都是音效。同一時間播放的音樂一般只有一個,但音效可以有很多個同時播放。

pygame可以使用pygame.mixer.music.load('bg.mp3')來載入foo.mp3音樂,然後pygame.mixer.music.play(0)就可以播放,這裏0表示播放1次,如果要無限次的播放則要改爲-1.

但是如果要播放音效sound,那麼pygame裏面只能使用wav格式(並且不支持32位深,只支持16位深)。載入音效的方法是sd=pygame.mixer.Sound("hit.wav"),播放是sd.play(0),這裏0也是1次,一般音效不需要連續播放。

我們在遊戲一開始就可以播放背景音樂了,但只有在點擊鼠標event.type == MOUSEBUTTONDOWN的時候才播放錘子的聲音,只有在擊中地鼠的時候才播放地鼠的叫聲。

修改之後的代碼如下:

import pygame
import sys
import random
from pygame.locals import *  # 引入鼠標事件類型
import time

pygame.init()  # 初始化
window = pygame.display.set_mode([600, 400])  # 設定窗口

sur = pygame.Surface([600, 400])  # 繪製背景容器
clr = (0, 0, 255)
posAll = [[100, 150], [300, 150], [500, 150], [200, 300], [400, 300]]  # 六個位置
rad = 50
tick = 0  # 計數器
pos = posAll[0]  # 外面記錄圓的位置

# 分數
score = 0  # 分數計數
pygame.font.init()  # 初始化文字
score_font = pygame.font.Font("MicrosoftYaqiHeiLight-2.ttf", 30)  # !!設定字體和字號
score_sur = score_font.render(str(score), False, (255, 0, 0))  # !!生成計數表面

# 鼠標
pygame.mouse.set_visible(False)  # !!隱藏鼠標
mpos = [300, 200]  # !!記錄鼠標位置

times = 0  # 地鼠跳出的次數
times_max = 10  # 最多次數
tick_max = 30  # 地鼠每次跳多少幀
map = pygame.image.load("dds-map.jpg")  # !!讀取圖片
rat1 = pygame.image.load("rat1.png")  # !!讀取地鼠圖片
rat2 = pygame.image.load("rat2.png")  # !!讀取被砸地鼠圖片
ham1 = pygame.image.load("hammer1.png")  # !!讀取錘子圖片
ham2 = pygame.image.load("hammer2.png")  # !!讀取砸下錘子圖片

gameover = 0  # !!結束計時
gameover_max = 100  # !!結束計時最大值,超過這個值就重新開始

# 音樂和音效
pygame.mixer.music.load("bg.mp3")  # !!載入背景音樂
pygame.mixer.music.play(-1)  # !!無限播放背景音樂
hitsound = pygame.mixer.Sound("hit.wav")  # !!載入擊打聲音
hurtsound = pygame.mixer.Sound("aiyo2.wav")  # !!載入地鼠叫聲

while 1:
    hamsur = ham1
    ratsur = rat1
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == MOUSEBUTTONDOWN:  # 如果是鼠標按下事件
            hamsur = ham2  # 使用下落錘子
            hitsound.play()  # !!播放擊打聲音
            mpos = pygame.mouse.get_pos()  # 獲取鼠標位置
            dis = pygame.math.Vector2(mpos[0] - pos[0], mpos[1] - pos[1])  # 計算座標差
            len = pygame.math.Vector2.length(dis)  # 計算距離
            if len < rad:
                tick = 1000  # 立即變換位置
                score = score + 1  # 計分增加
                ratsur = rat2  # 使用被砸地鼠
                hurtsound.play()  # !!播放地鼠聲音
        elif event.type == MOUSEMOTION:  # 當鼠標移動的時候
            mpos = pygame.mouse.get_pos()  # 更新鼠標位置

    if times >= times_max:
        # 顯示結束畫面
        sur.fill((0, 0, 0))  # 結束時候仍然用黑色清空畫面
        pygame.mouse.set_visible(True)
        end_font = pygame.font.Font("MicrosoftYaqiHeiLight-2.ttf", 48)  # 設定字體和字號
        end_sur = score_font.render(
            "你的分數是:{}/{}!".format(score, times_max), True, (255, 0, 0)
        )  # 生成計數表面
        sur.blit(end_sur, (100, 150))
        cd = int((gameover_max - gameover) / 10)
        cd_sur = score_font.render(
            "重新開始倒計時{}".format(cd), True, (255, 0, 0)
        )  # 生成計數表面
        sur.blit(cd_sur, (100, 200))  # 增加分數表面
        gameover = gameover + 1  # !!增加結束計時
    else:
        sur.blit(map, (0, 0))  # 添加背景圖片
        score_sur = score_font.render(
            "分數:{}/{}!".format(score, times + 1), False, (255, 0, 0)
        )  # 重新生成分數文字表面
        sur.blit(score_sur, (200, 10))  # 增加分數表面
        if tick > tick_max:  # 每50次刷新變換一次
            times = times + 1  # 增加計次
            a = random.randint(0, 4)  # 隨機0到4
            pos = posAll[a]  # 更新外部記錄的圓的位置
            tick = 0  # 重置計數器
        else:  # 不刷新變換的時候
            tick = tick + 1  # 增加計數器
        if tick > 5:  # 開始幾幀不顯示地鼠
            sur.blit(ratsur, (pos[0] - 50, pos[1] - 70))  # 繪製地鼠
        sur.blit(hamsur, (mpos[0] - 50, mpos[1] - 100))  # 繪製錘頭

    # 刷新畫面
    window.blit(sur, (0, 0))
    pygame.display.flip()  # 刷新畫面
    time.sleep(0.04)  # 保持畫面一點時間

    # 重置遊戲
    if gameover > gameover_max:
        pygame.mouse.set_visible(False)
        times = 0
        score = 0
        gameover = 0

運行上面的代碼,可以聽到歡快的背景音樂,點擊鼠標時候會有捶地聲音,打中地鼠會有哎呦的叫聲。

發佈軟件

我們寫的代碼目前只能在自己的電腦上運行,因爲我們先要安裝python,然後還要安裝pygame纔行,這和我們平常下載的軟件不同,下載的軟件可以直接運行(或者安裝自身後運行)。

Python給我們提供了自動把代碼打包成軟件的工具,Windows下推薦使用auto-py-to-exe工具。同樣先安裝pip install auto-py-to-exe,然後只要執行auto-py-to-exe就會打開一個窗口。

基本設置如下:

注意幾個地方:

  • Script Location要指向你的主要.py文件,這裏是main.py
  • Onefile選One Directory,這會把生產的所有文件放在一個文件夾中
  • Console Window選Console Based,因爲我們的pygame是基於控制檯的
  • Icon圖標,你可以在網上下載.ico文件,比如easyicon有很多,網盤裏面有一個地鼠圖標icon.ico
  • Additional Files附加文件,點擊Add Files按鈕要把全部用到的字體、圖片、聲音都選擇
  • CONVERT .PY TO .EXE點擊這個按鈕進行生成,生成後會變爲兩個藍色按鈕

點擊OPEN OUTPUT FOLDER打開生產的軟件目錄(默認在你的代碼文件夾下面的output文件夾內),找到那個和你的Script Location同名的文件,點擊它就可以運行遊戲了。

也可以把這個MAIN.exe複製然後在桌面上粘貼快捷方式,以後只要點這個快捷方式就可以了。

在網盤文件中包含一個main.rar文件,下載它然後解壓就可以得到我打包生成的軟件了。

關於Mac蘋果電腦下面生成軟件的方法暫時遇到一點麻煩,搞定之後再更新,敬請關注。

第一個小遊戲似乎開發完成了,但是還有很多內容,我們的代碼也有很多不合理的地方,下一篇我們一起來回顧和整理,並且繼續介紹更多小遊戲的開發方法。

添加音效

遊戲裏面的聲音分爲兩種,一種叫音樂music,另一種叫音效sound。背景音樂是music,遊戲裏面的擊打聲點擊聲都是音效。同一時間播放的音樂一般只有一個,但音效可以有很多個同時播放。

pygame可以使用pygame.mixer.music.load('bg.mp3')來載入foo.mp3音樂,然後pygame.mixer.music.play(0)就可以播放,這裏0表示播放1次,如果要無限次的播放則要改爲-1.

但是如果要播放音效sound,那麼pygame裏面只能使用wav格式(並且不支持32位深,只支持16位深)。載入音效的方法是sd=pygame.mixer.Sound("hit.wav"),播放是sd.play(0),這裏0也是1次,一般音效不需要連續播放。

我們在遊戲一開始就可以播放背景音樂了,但只有在點擊鼠標event.type == MOUSEBUTTONDOWN的時候才播放錘子的聲音,只有在擊中地鼠的時候才播放地鼠的叫聲。

Python源碼、可執行文件以及文中素材可以添加羣456926667,獲取

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章