運用 Python 程式語言自行設計一款單人遊戲 —火輪手槍,介紹 Python 程式語言與 Scratch 的不同,並說明如何利用幾何、三角函數等數學原理解決遊戲中的實際問題,再以程式語言實踐。
本系列之目標讀者為無程式基礎的人。
遊戲專案連結
目錄
碰撞檢測:
三角函數:
- 讓我朝向60度移動吧!
- 叫那隻殭屍…給我滾開!!
- 不~~為什麼它的槍一直瞄準我啦!
- 把手槍變成三角形
FireWheel火輪手槍
FireWheel火輪手槍是我在寒假時製作的一個遊戲專案,當時是將它作為一個休閒來做。在寒假的時候我們在進行科展,當一天研究結束後,我就拿這個專案出來做,一做就又是好幾個小時。
這個遊戲對我的特別意義在於,這不是我第一次設計它,其實在我國一,還在使用Scratch時,我就曾經製作過。
遊戲說明
火輪手槍是一個戰鬥遊戲,玩家在一個迷宮中,四面八方會出現怪物來攻擊你,你只能靠著身邊的一把手槍來生存下去。
這個遊戲最特別的就在於我獨創的「火輪」,這把火輪手槍會繞在你身邊,當你按下發射鍵時會停下,開始左右搖擺,鬆開後就會發射出子彈。
新手遇到這樣的操作多半是很不習慣,因為這很難瞄準,必須花很多心思在看那把槍的旋轉;但是當你操作順手之後,你就會愛上它,因為這很有挑戰性,相較於普通的滑鼠瞄準或者是朝向正前方,火輪更能突顯出玩家的技巧,因此更有成就感。
操作說明:
- 使用WSAD移動
- 使用空白鍵發射
- 使用JKL選取道具 (道具功能僅Beta版)
成果預覽
淺談遊戲設計
這個遊戲是使用Python製作,Python是一門優秀的程式語言,很好學、語法簡單,我在去年暑假時接觸它,花了許多時間學習,到了今年寒假時,已經可以熟練的用它來開發專案。當時寒假無聊,沒事時就做火輪手槍當娛樂。
那在後續的文章中,我會逐步介紹碰撞檢測、三角函數這兩個主題
從scratch 到 Python
我的程式生涯是Scratch起家的,或許有人不承認Scratch是一門程式語言,但對我而言,是啟發我電腦研究生涯的重要推手。
在前面提到過,我曾經用Scratch開發過火輪手槍,但後期因為效能低落與程式架構維護不彰而停止開發。
Scratch 的優缺點
簡單。使用Scratch開發真的是簡單到不行,老實說在我用Scratch開發的時期,我根本很少去查資料,為什麼?
所有資料都在裡面了,還要查什麼?
中文界面的Scratch編輯器,讓小學的我也能輕易理解,再加上一點的嘗試,很快就能完成一點皮毛。
以下列舉一些Scratch的優缺點
優點
- 簡單好用的碰撞檢測
- 將常用的幾何數學(如三角函數、畢氏定理)處理好
- 可一邊修改程式一邊執行
- 容易學
缺點
- 糟糕的自訂函數功能(可輸入參數,但沒辦法得到回傳值)
- 分身一建立就回不來了(無法存取分身)
- 沒有物件導向
- 效能低落(當你的分身數到幾百個時,你就知道)
- 無法掌控的異步處理
雖然對我而言,Scratch非常的不便,但是它的設計初衷本來就是為了小朋友而設計,我所需要的那些功能已經不是它應該提供的了。因此在一年級的下學期,我就非常的積極想要學習更專業的程式語言,最後便選中了簡單易學的Python。
那今天,我會將開發火輪手槍的過程中遇到的兩個問題挑出來講,分別是 碰撞檢測,及 三角函數。
Python 不「歹算」
Python是我第一門真正學會的程式語言。對我而言,Python是非常平易近人的,在學習Python之前,我其實想要學習的是 Java ,Java應該算是平常人比較常聽到的東西,因為打遊戲常常要裝。(誤)
當時曾經為了學Java買了一本書,很認真的讀,只是都沒有乖乖的做練習,只想要知道更多東西,後來沒學成,又繼續寫Scratch一個學期。
後來到了升二年級暑假前,剛好聽朋友提到Python,於是上網去試試看,一試不得了,整個開發環境、語法都非常的平易近人,花了兩天的時間就弄出了GUI來,(當然那時候根本只是照抄)。
所以在二年級,我幾乎寫的都是Python,我也強力推薦對程式有興趣的朋友以Python開始,Python 真的 不 「歹算」。
物件導向基礎
電腦程式設計有許多種專家在研究多年所產生「編程範式」,你的程式符合編程範式,可以讓你的專案用更好的方式開發、或者讓日後容易維護、以及程式碼更容易閱讀。
有名的編程範式有:函數式程式設計、物件導向程式設計等等。在當代,物件導向程式設計最受推崇,不少資訊課程一定會教到,出去工作參與他人專案也幾乎都會遇到。
物件導向程式設計的核心概念是:物件是程式的基本單位,將程式的執行過程視為一群物件的交流過程。
使用物件導向來開發專案的好處是易於維護,物件導向的特性可以將代碼重用,事後修改也較輕鬆。那在我這個專案也不例外。
接下來我會介紹物件導向中的「類與物件」,這只是物件導向的基礎,至於物件導向的詳細知識由於相當複雜,而且我也不敢保證自己完全理解,所以我就不在這次說明。
Class (類) 以及 Object (物件)
在剛剛提到,物件導向中的程式是由一群物件建構起來的,那該如何創造一個「物件」呢?
答案是定義Class。Class,也就是類別,你可以將它視為物件的模板,在Class中你定義每個物件有著什麼屬性,會做什麼行為,然後你再建立此Class的實例,根據你給予的資料,就會產生不一樣的物件。
舉例我們要建立一群殭屍,那這些殭屍或許每一隻的顏色不一樣,座標不一樣,但是它們的行為模式是一致的,這些殭屍就是我們產生的「物件」,而定義我們殭屍物件該如何行動的則是殭屍「類別」。
屬性 與 行為
屬性是一個物件所帶有的資料,以殭屍為例會有座標、顏色、移動速度、血量等屬性,這些屬性有些是數字,有些是字串,有些甚至是別的物件;行為則是一個物件的行為,多半是一個函數,例如殭屍會移動、會死掉。
屬性和行為的區分大多是明顯的,且在定義方式就有所不同。但是在某些語言例如Javascript,就直接將行為作為屬性。
一個殭屍物件可能包含的屬性有:x, y座標、顏色、移動速度、血量等等,那它可能包含的行為有:靠近玩家、…抱歉殭屍這個類別它的行為真的很少。
要存取物件的屬性或方法就是使用 . ,沒錯就是英文的句點,假如說你有一個Zombie的物件名叫my_zombie,你要讓它向玩家靠近,就使用 my_zombie.near(),如果你想存取它的座標,你就使用 my_zombie.x my_zombie.y
參考自己 —self
當我們在定義類別時,需要取得自己的屬性或方法,這時候無須再傳一個參數到函數中,在Python中,只要用 self 就可以存取自己的屬性了。
假如今天這個函數是殭屍的物件方法,那self就會是存取殭屍的屬性;如果今天是玩家呼叫這個函數,那self就會存取玩家的屬性。有了self,我們就可以操作自己的屬性,而無須再多傳送自己進去。
而呼叫自己的函數,在函數的最前面需要加上self參數。例如:殭屍要讓自己靠近玩家,self.near()
1 | class Zombie: |
而透過此類別產生物件則是:1
2
3
4
zombie = Zombie()
zombie.near()
在以下的介紹,有部份的參數是物件,例如碰撞檢測中的 circle, rect,或是會有一些程式實做在物件方法中,例如三角函數中的 near, move方法。