<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          太好玩了!用Python寫一個乒乓球游戲!

          共 10877字,需瀏覽 22分鐘

           ·

          2022-06-18 14:18


          好久沒有寫游戲系列教程了,今天恰好瀏覽到了 Kivy 這個開源跨平臺的Python 框架,它能用于開發(fā)多點(diǎn)觸控的用戶界面程序,允許快速簡單的交互設(shè)計,非常方便,于是有了制作本教程的想法。

          本教程將教你如何使用 Kivy 編寫一款乒乓球游戲。我們將從一個基本的應(yīng)用程序開始,描述創(chuàng)建這個游戲的每個步驟。

          Kivy 是用 Python 和 Cython 編寫的,基于 OpenGL ES 2,支持各種輸入設(shè)備并擁有豐富的部件庫。使用相同的代碼,你可直接實現(xiàn)多平臺應(yīng)用,包括 Windows、macOS、Linux、Android 和 iOS。所有 Kivy 部件都支持多點(diǎn)觸控。

          1.準(zhǔn)備


          請選擇以下任一種方式輸入命令安裝依賴
          1. Windows 環(huán)境 打開 Cmd (開始-運(yùn)行-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 運(yùn)行該應(yīng)用程序。它應(yīng)該只顯示一個黑色的窗口。所以我們所做的只是創(chuàng)建一個非常簡單的Kivy應(yīng)用程序,它創(chuàng)建了一個 PongGame Widget 類的實例,并將其作為應(yīng)用程序用戶界面的根元素返回。

          在這一點(diǎn)上你應(yīng)該把它想象成一個 Widget 的分層樹。Kivy 將這個 Widget 放在默認(rèn)的窗口中。在下一步,我們將通過定義 PongGame 小部件的外觀來繪制Pong的背景和游戲分?jǐn)?shù)。

          3.Kivy - 添加簡單圖形



          我們將使用一個 .kv 文件來定義 PongGame 類的外觀。由于我們的應(yīng)用程序類被稱為 PongApp,我們可以簡單地在同一目錄下創(chuàng)建一個名為 pong.kv 的文件,當(dāng)應(yīng)用程序運(yùn)行時將會自動加載。

          因此,為了定義游戲的外觀,我們創(chuàng)建一個名為 pong.kv 的新文件并添加以下內(nèi)容:

          #: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,必須與應(yīng)用程序的名稱一致,例如 PongApp(App結(jié)尾之前的部分)。

          如果你現(xiàn)在運(yùn)行這個應(yīng)用程序,你應(yīng)該看到中間有一個豎條,還有兩個零,那里將顯示玩家的分?jǐn)?shù),如下所示:

          可以看到,在第一行,我們有:

          #:kivy 1.0.9


          每個 kv 文件都需要第一行。它應(yīng)該以 #:kivy 及一個空格開頭,然后是它要使用的 Kivy 版本(因此 Kivy 可以確保您至少擁有所需的版本,或者稍后處理向后兼容性)。

          再往下看 kv 文件里定義了三個元素,一個 canvas 和兩個 label。

          先說說兩個label,他們代表的是左右兩個數(shù)字,設(shè)定了 font_size(字體大小), center_x(中心位置), top(離頂部距離), text(文本),此外可以看到 root.width 和 root.top 的使用,這樣寫的好處是能跟跟隨窗口寬度和高度的變化而變化。

          另一個元素 canvas,它的下面定義了 Rectangle 參數(shù),意思是我們向畫布添加一個矩形。將矩形的 pos 設(shè)置為小部件水平中心左側(cè) 5 個像素,y 設(shè)置為 0,這就定義了矩形的顯示位置。

          矩形的大小 size 設(shè)置為寬度為 10 像素,高度為小部件的高度。像這樣定義圖形的好處是,當(dāng)值表達(dá)式中使用的任何小部件的屬性發(fā)生變化時,渲染的矩形將自動更新

          4. Kivy - 增加乒乓球球體


          好了,我們有一個基本的乒乓球場(雖然很簡陋),但我們?nèi)匀恍枰蚺暮鸵粋€球來打球。讓我們從球開始。我們將添加一個新的 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

          為了使這一切順利進(jìn)行,你還必須為球體增加所用的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 - 增加乒乓球體運(yùn)動


          現(xiàn)在我們的目的是讓這個球動起來,因此必須定期調(diào)用 move 函數(shù)讓他動起來。使用 Kivy 提供的 Clock 函數(shù)可以輕易地做到這一點(diǎn):

          Clock.schedule_interval(game.update, 1.0/60.0)

          這一行將導(dǎo)致游戲?qū)ο蟮母潞瘮?shù)每秒被調(diào)用60次。

          不過我們還有一個問題。我們想確保PongBall的移動函數(shù)被定期調(diào)用,但是在我們的代碼中沒有任何對球?qū)ο蟮囊茫驗槲覀冎皇峭ㄟ^ 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 進(jìn)行操作的這一事實。為了解決這個問題,我們可以給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文件中將其與代碼中設(shè)定的 id: ball 映射起來:

          <PongGame>:
              ball: pong_ball

              # ... (canvas and Labels)

              PongBall:
                  id: pong_ball
                  center: self.parent.center


          6. Kivy - 球拍移動事件


          現(xiàn)在,我們的球正在彈來彈去。唯一缺少的是可移動的球拍和對分?jǐn)?shù)的跟蹤。我們不會再去討論創(chuàng)建類和kv規(guī)則的所有細(xì)節(jié),因為這些概念已經(jīng)在前面的步驟中涵蓋了。

          在Kivy中,小部件可以通過實現(xiàn) on_touch_down、on_touch_move和on_touch_up 方法對輸入做出反應(yīng)。默認(rèn)情況下,Widget類實現(xiàn)這些方法時,只是在其子部件上調(diào)用相應(yīng)的方法來傳遞事件,直到其中一個子部件返回True。

          乒乓運(yùn)動是非常簡單的。球拍只需要向上和向下移動。事實上,它是如此簡單,我們甚至不需要讓球員小部件自己處理事件。我們只需為PongGame類實現(xiàn)on_touch_move函數(shù):

          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中保留每個球員的分?jǐn)?shù)。PongGame的分?jǐn)?shù)標(biāo)簽通過改變 NumericProperty score來保持更新,這反過來又會更新PongGame的子標(biāo)簽文本屬性。

          這是如何實現(xiàn)的?因為Kivy屬性會自動綁定到其對應(yīng)的kv文件中的任何引用。當(dāng)球從兩側(cè)逃出時,我們將通過PongGame類中的更新方法來更新分?jǐn)?shù)并再次發(fā)球。

          PongPaddle類也實現(xiàn)了一個 bounce_ball 方法,這樣球就會根據(jù)它擊中球拍的位置而產(chǎn)生不同方向的彈跳,非常有意思。下面是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)



          如何獲取源碼

          到這一步我們基本就完成了整個游戲的制作,如何,你心動了嗎?如果你想體驗一下這個游戲,可以公眾號后臺回復(fù):小助手,找他獲取,暗號乒乓球 獲得全部代碼和 kv 規(guī)則!



          推薦閱讀:

          入門: 最全的零基礎(chǔ)學(xué)Python的問題  | 零基礎(chǔ)學(xué)了8個月的Python  | 實戰(zhàn)項目 |學(xué)Python就是這條捷徑


          干貨:爬取豆瓣短評,電影《后來的我們》 | 38年NBA最佳球員分析 |   從萬眾期待到口碑撲街!唐探3令人失望  | 笑看新倚天屠龍記 | 燈謎答題王 |用Python做個海量小姐姐素描圖 |碟中諜這么火,我用機(jī)器學(xué)習(xí)做個迷你推薦系統(tǒng)電影


          趣味:彈球游戲  | 九宮格  | 漂亮的花 | 兩百行Python《天天酷跑》游戲!


          AI: 會做詩的機(jī)器人 | 給圖片上色 | 預(yù)測收入 | 碟中諜這么火,我用機(jī)器學(xué)習(xí)做個迷你推薦系統(tǒng)電影


          小工具: Pdf轉(zhuǎn)Word,輕松搞定表格和水印! | 一鍵把html網(wǎng)頁保存為pdf!|  再見PDF提取收費(fèi)! | 用90行代碼打造最強(qiáng)PDF轉(zhuǎn)換器,word、PPT、excel、markdown、html一鍵轉(zhuǎn)換 | 制作一款釘釘?shù)蛢r機(jī)票提示器! |60行代碼做了一個語音壁紙切換器天天看小姐姐!



          年度爆款文案

          點(diǎn)閱讀原文,看B站我的20個視頻!

          瀏覽 68
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧美不卡一区 | 中国一区二区在线观看 | 五月色婷婷国产 | 影音先锋av黄色 影音先锋成人网址 | 麻豆成人在线 |