Python寫的彈球小游戲
Python 的功能強大應(yīng)用廣泛,從爬蟲到 Web 開發(fā),從科學(xué)計算到人工智能,都能見到它的身影。當(dāng)然,Python 還可以編寫游戲代碼,雖然不是主流,但卻十分有趣,既能提升代碼能力,又能自娛自樂。敲下幾行代碼,程序就按照你設(shè)定的規(guī)則運動起來,這樣即時的正反饋會讓你更加感受到編程的樂趣。
今天我們就來分享一個非常簡單的彈球小游戲。如果你初學(xué) Python 不久,正在為整天對著命令行的白底黑色而感到枯燥,不妨也跟著來試試自己寫一個“會動”的程序。

我們這個程序要用到 pygame 庫,首先需要安裝。在命令提示符下輸入
pip install pygame即可自動下載安裝。

pygame 的官網(wǎng)是 www.pygame.org,也可以在這里下載 pygame 安裝包。我這里用的是 pygame 1.9.3,python 3.6。你也可以用最新的版本。

安裝好后在代碼中輸入并執(zhí)行:
import pygame如果沒有報錯則表明安裝成功。
開始編寫程序,第一步導(dǎo)入相關(guān)的庫:
import pygame as pg
from pygame.locals import * ? ?#將pygame所有常量導(dǎo)入,如后面的QUIT
from time import sleep
import sys之后設(shè)置基本屏幕參數(shù),如下:
pg.init() ? ? ? ? ? ? ? ? ? ? ? ? ?#初始化,如果沒有的話字體會報錯等等
scr=pg.display.set_mode((600,550)) ? #設(shè)置屏幕大小
pg.display.set_caption(("打乒乓球")) ? #設(shè)置屏幕標(biāo)題
pp=255,140,0 ? ? ? ? ? ? ? ? ? ? #red是一個元組,表示乒乓球的RGB顏色
green=0,255,0
white=255,255,255
cs=225,121,21 ? ? ? ? ? ? ? ? ? ? #橙色現(xiàn)在我們設(shè)計一下乒乓球的運動方式,乒乓球在屏幕內(nèi)運動,因此我們將乒乓球的坐標(biāo)設(shè)置為 (x, y),設(shè)置初速度 vx,vy,當(dāng)乒乓球到達屏幕邊緣的時候速度取反,也就是乒乓球到達左右兩邊緣的時候 vx = -vx,上下邊緣的時候 vy = -vy。再設(shè)置變量 a 記錄乒乓板的 x 坐標(biāo)值,因為乒乓板 y 坐標(biāo)值是固定的,所以無需設(shè)定。
x=120
y=120
vx=1
vy=1
a=200接下來我們設(shè)置字體,以下代碼可設(shè)置為 pygame 默認(rèn)字體,但是這樣就不能顯示出中文。
My_font=pg.font.Font(None,40) ?#40是字的大小要顯示中文我們可借助系統(tǒng)的字體,比如我的電腦里面系統(tǒng)字體如下圖:

圖中有很多的“方塊”,是不支持相關(guān)字符所導(dǎo)致。在其中仔細找下,可以發(fā)現(xiàn)支持中文的相關(guān)字體,比如 kaiti,stfangson 等等,你也可以用以下方法獲得系統(tǒng)自帶的字體。
>>> a=pg.font.get_fonts()我設(shè)置的字體如下:
zt1=pg.font.SysFont('stkaiti',24) ?#楷體
zt2=pg.font.SysFont('stkaiti',20)注意:如果通過設(shè)置 SysFont 仍無法顯示中文(一般是非windows平臺),可選擇手動下載中文字體后設(shè)定 font.Font('字體文件完整路徑', 字號) 的方式進行字體設(shè)定。
設(shè)計一個函數(shù),在游戲屏幕上打印文本。代碼表示先把文本轉(zhuǎn)換成一個位圖然后打印在屏幕上,打印文本需要打印的具體坐標(biāo)和文本顏色,字體等參數(shù)。
def printtext(font,text,x,y,color):
? ?img=font.render(text,True,color) ? #轉(zhuǎn)換為位圖
? ?scr.blit(img,(x,y))然后設(shè)置得分,基礎(chǔ)記分量。為什么設(shè)置基礎(chǔ)記分量?我想的是經(jīng)過一段時間后乒乓球會加速,從而逐漸增加游戲難度,所以基礎(chǔ)記分量也要翻倍。
c=0 ? #c是加速量,如果接了3次,那么加速
fs=0 ? #fs是分?jǐn)?shù),接到一次乒乓球就加分
k=1 ?#基礎(chǔ)加分量接下來是游戲的主要代碼了,pygame 采用幀和輪詢的方式。幀是指會不斷刷新,其實就是一個 while True 循環(huán);輪詢則是不斷的詢問用戶的輸入。在下面代碼中,會不斷獲取鼠標(biāo)具體坐標(biāo)和判斷 QUIT 事件是否發(fā)生。scr.fill 會用 RGB 值為 (199, 21, 133) 的顏色刷新屏幕,以后畫圓寫字都在這個背景之上,下一次循環(huán)后又刷新。因此在屏幕中乒乓球和乒乓板就會動態(tài)呈現(xiàn)出來。
while True:
? ?scr.fill((199,21,133))
? ?for eve in pg.event.get():
? ? ? ?if eve.type == QUIT: ? ?#點擊左上角的×
? ? ? ? ? ?sys.exit() ? ? ? ? #如果無效,可以試試exit()函數(shù) ? ? ? ?
? ?mx,my=pg.mouse.get_pos() ? ? #獲得鼠標(biāo)的x,y坐標(biāo)
? ?a=mx ? ? ?#鼠標(biāo)x坐標(biāo)就是乒乓板的坐標(biāo),因此移動鼠標(biāo)乒乓板也移動接下來是畫乒乓球和畫乒乓板了,我們可以簡化為圓形和矩形
pg.draw.circle(scr,pp,(x,y),40,0) ? #厚度為0 ,表示實心
pg.draw.rect(scr,green,(a,530,100,20),0) ? #矩形的長和寬是100和20考慮乒乓球的運動,如果乒乓球碰到左右屏幕邊緣,vx 取負,碰到上邊緣或者碰到乒乓板的時候,vy取負。如果 y 碰到下邊緣但未碰到乒乓板,則跳出循環(huán),游戲結(jié)束。以下代碼均在 while True 主循環(huán)內(nèi)。
? ?x=x+vx
? ?y=y+vy
? ?if x>550 or x<40:
? ? ? ?vx=-vx
? ?if ?y<40:
? ? ? ?vy=-vy
? ?if y>510 and abs(a-x+50)<50:
? ? ? ?if vy>0:
? ? ? ? ? ?vy=-vy
? ? ? ?else:pass
? ? ? ?c=c+1 ? ? #每接到3次后乒乓球加速
? ? ? ?fs=fs+k ? ?#加分
? ? ? ?if c>=3:
? ? ? ? ? ?c=0
? ? ? ? ? ?k=k+k ?#乒乓球加速后記分量雙倍
? ? ? ? ? ?if vx>0: ?#加速
? ? ? ? ? ? ? ?vx=vx+1
? ? ? ? ? ?else:
? ? ? ? ? ? ? ?vx=vx-1
? ? ? ?else:pass
? ?elif y>510 andabs(a-x+50)>50:
? ? ? ?break在 while 循環(huán)最后,輸出一下得分。別忘了刷新,刷新很重要!
sleep(0.005) ? #休眠一定時間,不然乒乓球速度依然很快
printtext(zt1,"移動鼠標(biāo)控制乒乓板左右移動",300,30,white)
printtext(zt2,"得分",550,12,cs)
printtext(zt2,str(fs),560,32,cs)
pg.display.update()在循環(huán)結(jié)束后就是游戲結(jié)束的代碼:
scr.fill((211,21,33)) ? #游戲結(jié)束后全屏改變顏色
zt3=pg.font.SysFont('stkaiti',120)
zt4=pg.font.SysFont('stkaiti',60)
printtext(zt3,"游戲結(jié)束",60,120,white)
printtext(zt4,'得分: '+str(fs),120,400,white)
pg.display.update()最后保存,運行。游戲雖然很簡(nan)單(kan),但如果是自己寫的,玩起來也有不一樣的感受。你也可以嘗試改變顏色,或者改變小球的速度等等,下圖是部分常用的 RGB 值。

以下是游戲運行的效果:


完整源代碼:
import pygame as pg
from pygame.locals import * ? ?#將pygame所有常量導(dǎo)入,如后面的QUIT
from time import sleep
import sys
pg.init() ? ? ? ? ? ? ? ? ? ? ? ? ?#初始化,如果沒有的話字體會報錯等等
scr=pg.display.set_mode((600,550)) ? #設(shè)置屏幕大小
pg.display.set_caption(("打乒乓球")) ? #設(shè)置屏幕標(biāo)題
pp=255,140,0 ? ? ? ? ? ? ? ? ? ? #red是一個元組,表示乒乓球的RGB顏色
green=0,255,0
white=255,255,255
cs=225,121,21 ? ? ? ? ? ? ? #橙色
x=120
y=120
vx=1
vy=1
a=200
zt1=pg.font.SysFont('stkaiti',24)
zt2=pg.font.SysFont('stkaiti',20)
def printtext(font,text,x,y,color):
? img=font.render(text,True,color)
? scr.blit(img,(x,y))
c=0 ? #c是加速器,如果接了10次,那么加速
fs=0 ? #fs是分?jǐn)?shù),接到一次乒乓球就加分
k=1 ?#基礎(chǔ)加分量
while True:
? ?scr.fill((199,21,133))
? ?for eve in pg.event.get():
? ? ? ?if eve.type == QUIT: ? ?#點擊左上角的×
? ? ? ? ? ?sys.exit() ? ? ? ? #如果無效,可以試試exit()函數(shù)
? ?mx,my=pg.mouse.get_pos() ? ? #獲得鼠標(biāo)的x,y坐標(biāo)
? ?a=mx ? #鼠標(biāo)x坐標(biāo)就是乒乓板的坐標(biāo),因此移動鼠標(biāo)乒乓板也移動
? ?pg.draw.circle(scr,pp,(x,y),40,0)
? ?pg.draw.rect(scr,green,(a,530,100,20),0)
? ?x=x+vx
? ?y=y+vy
? ?if x>550 or x<40:
? ? ? ?vx=-vx
? ?if ?y<40:
? ? ? ?vy=-vy
? ?if y>510 andabs(a-x+50)<50:
? ? ? ?if vy>0:
? ? ? ? ? ?vy=-vy
? ? ? ?else:pass
? ? ? ?c=c+1 ? ? #每接到3次后乒乓球加速
? ? ? ?fs=fs+k ? ?#加分
? ? ? ?if c>=3:
? ? ? ? ? ?c=0
? ? ? ? ? ?k=k+k ?#乒乓球加速后記分量雙倍
? ? ? ? ? ?if vx>0: ?#加速
? ? ? ? ? ? ? ?vx=vx+1
? ? ? ? ? ?else:
? ? ? ? ? ? ? ?vx=vx-1
? ? ? ?else:pass
? ?elif y>510 and abs(a-x+50)>50:
? ? ? ?break
? ?sleep(0.005) ?#休眠一定時間,不然乒乓球速度依然很快
? ?printtext(zt1,"移動鼠標(biāo)控制乒乓板左右移動",20,30,white)
? ?printtext(zt2,"得分",550,12,cs)
? ?printtext(zt2,str(fs),560,32,cs)
? ?pg.display.update()
scr.fill((211,21,33)) ? #游戲結(jié)束后全屏改變顏色
zt3=pg.font.SysFont('stkaiti',120)
zt4=pg.font.SysFont('stkaiti',60)
printtext(zt3,"游戲結(jié)束",60,120,white)
printtext(zt4,'得分: '+str(fs),120,400,white)
pg.display.update()復(fù)制粘貼到你的代碼編輯器中,保存,運行,就可以體驗。如果你對游戲中的顏色、形狀、速度,甚至是玩法有自己的想法,歡迎在代碼上進行修改,也實現(xiàn)一個屬于你自己的游戲。
作者:少年阿澤?
來源:Python那些事
