Python+Kivy編寫一個乒乓球游戲
前言
好久沒有寫游戲系列教程了,今天恰好瀏覽到了 Kivy 這個開源跨平臺的Python 框架,它能用于開發(fā)多點觸控的用戶界面程序,允許快速簡單的交互設計,非常方便,于是有了制作本教程的想法。
本教程將教你如何使用 Kivy 編寫一款乒乓球游戲。我們將從一個基本的應用程序開始,描述創(chuàng)建這個游戲的每個步驟。
Kivy 是用 Python 和 Cython 編寫的,基于 OpenGL ES 2,支持各種輸入設備并擁有豐富的部件庫。使用相同的代碼,你可直接實現多平臺應用,包括 Windows、macOS、Linux、Android 和 iOS。所有 Kivy 部件都支持多點觸控。
1.準備
開始之前,你要確保Python和pip已經成功安裝在電腦上,如果沒有,可以訪問這篇文章:超詳細Python安裝指南 進行安裝。
(可選1) 如果你用Python的目的是數據分析,可以直接安裝Anaconda,它內置了Python和pip.
(可選2) 此外,推薦大家用VSCode編輯器,它有許多的優(yōu)點
請選擇以下任一種方式輸入命令安裝依賴:
1. Windows 環(huán)境 打開 Cmd (開始-運行-CMD)。
2. MacOS 環(huán)境 打開 Terminal (command+空格輸入Terminal)。
3. 如果你用的是 VSCode編輯器 或 Pycharm,可以直接使用界面下方的Terminal.
pip install kivy[base]?kivy_examples
2.簡單使用 Kivy
這一節(jié)將簡單介紹Kivy的基本使用,首先為我們游戲創(chuàng)建一個目錄和一個名為main.py的文件:
# main.py from?kivy.app?import?App from?kivy.uix.widget?import?Widget class?PongGame(Widget): ????pass class?PongApp(App): ????def?build(self): ????????return?PongGame() if?__name__ ==?'__main__': ????PongApp().run()
在命令行中輸入 python main.py 運行該應用程序。它應該只顯示一個黑色的窗口。所以我們所做的只是創(chuàng)建一個非常簡單的Kivy應用程序,它創(chuàng)建了一個 PongGame Widget 類的實例,并將其作為應用程序用戶界面的根元素返回。
在這一點上你應該把它想象成一個 Widget 的分層樹。Kivy 將這個 Widget 放在默認的窗口中。在下一步,我們將通過定義 PongGame 小部件的外觀來繪制Pong的背景和游戲分數。
3.Kivy - 添加簡單圖形
我們將使用一個 .kv 文件來定義 PongGame 類的外觀。由于我們的應用程序類被稱為 PongApp,我們可以簡單地在同一目錄下創(chuàng)建一個名為 pong.kv 的文件,當應用程序運行時將會自動加載。
因此,為了定義游戲的外觀,我們創(chuàng)建一個名為 pong.kv 的新文件并添加以下內容:
#:kivy 1.0.9 <PongGame>: ????canvas: ????????Rectangle: ????????????pos: self.center_x - 5, 0 ????????????size: 10, self.height ???????????? ????Label: ????????font_size: 70 ????????center_x: root.width / 4 ????????top: root.top - 50 ????????text: "0" ???????? ????Label: ????????font_size: 70 ????????center_x: root.width * 3 / 4 ????????top: root.top - 50 ????????text: "0"
注意一個常見錯誤:kv文件的名稱,例如 pong.kv,必須與應用程序的名稱一致,例如 PongApp(App結尾之前的部分)。
如果你現在運行這個應用程序,你應該看到中間有一個豎條,還有兩個零,那里將顯示玩家的分數,如下所示:
可以看到,在第一行,我們有:
#:kivy 1.0.9
每個 kv 文件都需要第一行。它應該以 #:kivy 及一個空格開頭,然后是它要使用的 Kivy 版本(因此 Kivy 可以確保您至少擁有所需的版本,或者稍后處理向后兼容性)。
再往下看 kv 文件里定義了三個元素,一個 canvas 和兩個 label。
先說說兩個label,他們代表的是左右兩個數字,設定了 font_size(字體大小), center_x(中心位置), top(離頂部距離), text(文本),此外可以看到 root.width 和 root.top 的使用,這樣寫的好處是能跟跟隨窗口寬度和高度的變化而變化。
另一個元素 canvas,它的下面定義了 Rectangle 參數,意思是我們向畫布添加一個矩形。將矩形的 pos 設置為小部件水平中心左側 5 個像素,y 設置為 0,這就定義了矩形的顯示位置。
矩形的大小 size 設置為寬度為 10 像素,高度為小部件的高度。像這樣定義圖形的好處是,當值表達式中使用的任何小部件的屬性發(fā)生變化時,渲染的矩形將自動更新。
4. Kivy - 增加乒乓球球體
好了,我們有一個基本的乒乓球場(雖然很簡陋),但我們仍然需要球拍和一個球來打球。讓我們從球開始。我們將添加一個新的 PongBall 類來創(chuàng)建一個小部件,它將成為我們的球并使它彈跳起來。
PongBall 類:
class?PongBall(Widget): ????# velocity of the ball on x and y axis ????velocity_x = NumericProperty(0) ????velocity_y = NumericProperty(0) ????# referencelist property so we can use ball.velocity as ????# a shorthand, just like e.g. w.pos for w.x and w.y ????velocity = ReferenceListProperty(velocity_x, velocity_y) ????# ``move`` function will move the ball one step. This ????# will be called in equal intervals to animate the ball ????def?move(self): ????????self.pos = Vector(*self.velocity) + self.pos
白球的 kv 配置如下:
<PongBall>: ????size: 50, 50 ????canvas: ????????Ellipse: ????????????pos: self.pos ????????????size: self.size
為了使這一切順利進行,你還必須為球體增加所用的Property屬性類。下面是這一步更新后的python代碼和kv文件。
from?kivy.app?import?App from?kivy.uix.widget?import?Widget from?kivy.properties?import?NumericProperty, ReferenceListProperty from?kivy.vector?import?Vector class?PongBall(Widget): ????velocity_x = NumericProperty(0) ????velocity_y = NumericProperty(0) ????velocity = ReferenceListProperty(velocity_x, velocity_y) ????def?move(self): ????????self.pos = Vector(*self.velocity) + self.pos class?PongGame(Widget): ????pass class?PongApp(App): ????def?build(self): ????????return?PongGame() if?__name__ ==?'__main__': ????PongApp().run()
kv文件如下:
#:kivy 1.0.9 <PongBall>: ????size: 50, 50 ????canvas: ????????Ellipse: ????????????pos: self.pos ????????????size: self.size <PongGame>: ????canvas: ????????Rectangle: ????????????pos: self.center_x - 5, 0 ????????????size: 10, self.height ???? ????Label: ????????font_size: 70 ????????center_x: root.width / 4 ????????top: root.top - 50 ????????text: "0" ???????? ????Label: ????????font_size: 70 ????????center_x: root.width * 3 / 4 ????????top: root.top - 50 ????????text: "0" ???? ????PongBall: ????????center: self.parent.center
5. kivy - 增加乒乓球體運動
現在我們的目的是讓這個球動起來,因此必須定期調用 move 函數讓他動起來。使用 Kivy 提供的 Clock 函數可以輕易地做到這一點:
Clock.schedule_interval(game.update,?1.0/60.0)
這一行將導致游戲對象的更新函數每秒被調用60次。
不過我們還有一個問題。我們想確保PongBall的移動函數被定期調用,但是在我們的代碼中沒有任何對球對象的引用,因為我們只是通過 kv 文件在 PongGame 類的 kv 規(guī)則中添加了它。
由于我們要做的不僅僅是移動球(比如把球從墻上彈下來,然后再彈到球員的球拍上),我們可能需要為我們的PongGame類建立一個更新方法。
class?PongGame(Widget): ????def?update(self, dt): ????????# call ball.move and other stuff ????????pass class?PongApp(App): ????def?build(self): ????????game = PongGame() ????????Clock.schedule_interval(game.update,?1.0/60.0) ????????return?game
然而,這仍然不能改變我們沒有對kv規(guī)則所創(chuàng)建的 PongBall 進行操作的這一事實。為了解決這個問題,我們可以給PongGame類添加一個ObjectProperty,并將其與kv規(guī)則中創(chuàng)建的widget掛鉤。
一旦這樣做了,我們就可以很容易地在更新方法中引用球的屬性,甚至可以讓它從邊緣彈起。
class?PongGame(Widget): ????ball = ObjectProperty(None) ????def?update(self, dt): ????????self.ball.move() ????????# bounce off top and bottom ????????if?(self.ball.y <?0)?or?(self.ball.top > self.height): ????????????self.ball.velocity_y *=?-1 ????????# bounce off left and right ????????if?(self.ball.x <?0)?or?(self.ball.right > self.width): ????????????self.ball.velocity_x *=?-1
在kv文件中將其與代碼中設定的 id: ball 映射起來:
<PongGame>: ????ball: pong_ball ????# ... (canvas and Labels) ????PongBall: ????????id: pong_ball ????????center: self.parent.center
6. Kivy - 球拍移動事件
現在,我們的球正在彈來彈去。唯一缺少的是可移動的球拍和對分數的跟蹤。我們不會再去討論創(chuàng)建類和kv規(guī)則的所有細節(jié),因為這些概念已經在前面的步驟中涵蓋了。
相反,讓我們把重點放在如何響應用戶的輸入而移動球拍上。你可以在Python實用寶典公眾號后臺回復:乒乓球 獲得全部代碼和kv規(guī)則。
在Kivy中,小部件可以通過實現 on_touch_down、on_touch_move和on_touch_up 方法對輸入做出反應。默認情況下,Widget類實現這些方法時,只是在其子部件上調用相應的方法來傳遞事件,直到其中一個子部件返回True。
乒乓運動是非常簡單的。球拍只需要向上和向下移動。事實上,它是如此簡單,我們甚至不需要讓球員小部件自己處理事件。我們只需為PongGame類實現on_touch_move函數:
def?on_touch_move(self, touch): ????if?touch.x < self.width/3: ????????self.player1.center_y = touch.y ????if?touch.x > self.width - self.width/3: ????????self.player2.center_y = touch.y
我們將在NumericProperty中保留每個球員的分數。PongGame的分數標簽通過改變 NumericProperty score來保持更新,這反過來又會更新PongGame的子標簽文本屬性。
這是如何實現的?因為Kivy屬性會自動綁定到其對應的kv文件中的任何引用。當球從兩側逃出時,我們將通過PongGame類中的更新方法來更新分數并再次發(fā)球。
PongPaddle類也實現了一個 bounce_ball 方法,這樣球就會根據它擊中球拍的位置而產生不同方向的彈跳,非常有意思。下面是PongPaddle類的代碼:
class?PongPaddle(Widget): ????score = NumericProperty(0) ????def?bounce_ball(self, ball): ????????if?self.collide_widget(ball): ????????????speedup =?1.1 ????????????offset =?0.02?* Vector(0, ball.center_y-self.center_y) ????????????ball.velocity = speedup * (offset - ball.velocity)
到這一步我們基本就完成了整個游戲的制作,如何,你心動了嗎?
以上就是Python+Kivy編寫一個乒乓球游戲的詳細內容,更多關于Python Kivy乒乓球游戲的資料請關注腳本之家其它相關文章!
相關文章
python中Requests發(fā)送json格式的post請求方法
這篇文章主要介紹了python中Requests發(fā)送json格式的post請求方法,文章圍繞主題展開詳細的內容介紹,具有一定的參考價值,感興趣的朋友可以參考一下2022-09-09Python中的type與isinstance的區(qū)別詳解
本文主要介紹了Python中的type與isinstance的區(qū)別詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2023-04-04jupyter notebook運行代碼沒反應且in[ ]沒有*
本文主要介紹了jupyter notebook運行代碼沒反應且in[ ]沒有*,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-03-03