Python 0基礎開發遊戲:打地鼠(詳細教程)VS code版本

若是你沒有任何編程經驗,並且想嘗試一下學習編程開發,這個系列教程必定適合你,它將帶你學習最基本的Python語法,並讓你掌握小遊戲的開發技巧。你所須要的,就是付出一些時間和耐心來嘗試這些代碼和操做。
@[top]html

1、準備工做

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

3 安裝pygame模塊python

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

    2、建立項目

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

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

在這裏我仍是要說一下,文中素材以及可執行代碼能夠加羣:456926667,獲取,這個是我建立的一個針對0基礎的夥伴一個交流羣,下個文章我會更新關於pycharm版本的打地鼠。dom

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

3、可選操做

  1. 執行上面的操做的時候,VSCode的右下角會常常彈出一些提示,若是有【Install】字樣,能夠放心的點擊它進行安裝更多內容。編輯器

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

image

image

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

運行上面的代碼獲得一個窗口以下:

image

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

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

image

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

顯示背景圖片

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

image

咱們能夠用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() #刷新畫面

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

image

使用動態圖片

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

image

咱們能夠先把四個圖片都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)

運行以後的樣子以下圖:

image

讓遊戲從新開始

每次顯示最終成績以後,能不能讓遊戲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就會打開一個窗口。

基本設置以下:

image

注意幾個地方:

  • 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點擊這個按鈕進行生成,生成後會變爲兩個藍色按鈕

image

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

image

也能夠把這個MAIN.exe複製而後在桌面上粘貼快捷方式,之後只要點這個快捷方式就能夠了。

image

在網盤文件中包含一個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的時候才播放錘子的聲音,只有在擊中地鼠的時候才播放地鼠的叫聲。

修改以後的代碼以下:

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

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

相關文章
相關標籤/搜索