--- tags: 資訊之芽 --- <style type="text/css"> @keyframes polish { 0% { color: #7a7a7a; } 100% { color: #3a3a3a; } } .warning { color: #ff0000; } #nav-bar { width: 100%; height: 5vh; background-color: #f7f7f7; display: flex; border-radius: 5px; } #nav-item { color: #3a3a3a; font-weight: bold; font-size: 2vh; line-height: 5vh; width: 25%; text-align: center; } #inner-link { text-decoration: none; color: #7a7a7a; } #inner-link:hover { animation: polish .1s linear forwards; } .weak_hint { color: #7a7a7a; } .weak_hint:hover { animation: polish .1s linear forwards; } .logo { display: none; } @media (min-width: 1200px) { .logo { display: block; position: fixed; right: 10vw; bottom: 20px; } } </style> <image src="https://hackmd.io/_uploads/B1aUPQoAT.png" width="110" class="logo"> # 2024 資訊之芽 Python 語法班第一階段大作業 - Flappy Bird ###### tags: `資訊之芽` `大作業` <div id="nav-bar"> <div id="nav-item"> 電梯 </div> <div id="nav-item"> <a href="#安裝-pygame" id="inner-link">開始作業</a> </div> <div id="nav-item"> <a href="#Tasks" id="inner-link">Tasks</a> </div> <div id="nav-item"> <a href="#問答amp後續公告" id="inner-link">問答&公告</a> </div> </div> --- ## <span class="warning">DEADLINE: 4/21</span> --- ## Links - [作業程式連結](https://drive.google.com/file/d/1vHjSzBMjklYl3JSryV9pwnvKUp-jxPoU/view?usp=sharing) - [作業繳交表單連結](https://docs.google.com/forms/d/e/1FAIpQLSeVunz4qI8zLCaR4iOT4NDNoKcIxHG5LwIarByynI0nFzIsYw/viewform?usp=sf_link) - [作業程式 config.py 更新連結](https://drive.google.com/file/d/1lI-GHYyddC8mk_RHsDaN5QGntXQ2gd7Z/view?usp=sharing) - [作業程式 number.py 更新連結](https://drive.google.com/file/d/1hMq6RBUU_mVWB2zYQUu4d5G_apAyt0iU/view?usp=sharing) - [投影片連結](https://www.canva.com/design/DAFzpVtnHFY/3cAeQmeAO31-h6FbVXdmyA/view?utm_content=DAFzpVtnHFY&utm_campaign=designshare&utm_medium=link&utm_source=editor) - [課程網頁連結](https://tw-csie-sprout.github.io/py2024/) --- ## 事前準備 ### 安裝 python3 相信大家都安裝好了。 如果有需要,可以再到 [課程網站Week1簡報](https://tw-csie-sprout.github.io/py2024/slides) 去看教學~ ### 安裝 [pygame](https://www.pygame.org/news) 依據自己電腦使用的作業系統進行安裝。 遇到任何問題請洽講師們,我們會盡快提供協助。 #### Windows 在鍵盤上按下 `Win`+`R` 快捷鍵開啟`執行`的視窗, 輸入 `cmd` 後按 `確定` 打開 `命令提示字元`。 ::: spoiler <span class="weak_hint"> 範例畫面 </span> <br/> ![螢幕擷取畫面 2024-03-01 231317](https://hackmd.io/_uploads/Bky3lu1pp.png) ::: <br/> 在命令提示字元中輸入以下指令: ``` python -m pip install -U pygame==2.5.2 --user ``` ::: spoiler <span class="weak_hint"> 範例畫面 </span> <br/> (介面可能會根據版本/設定不同有所變化,大致是如下圖的文字介面) ![螢幕擷取畫面 2024-03-01 231657](https://hackmd.io/_uploads/HkUK-dyTp.png) ::: <br/> 輸入後按 `ENTER` 就會開始安裝。 #### MacOS/Linux 打開 `terminal` 輸入以下指令: ``` python3 -m pip install -U pygame==2.5.2 --user ``` 輸入後按 `ENTER` 就會開始安裝。 ### TODO Tree VSCode Extension(非必要) 為了方便定位大作業中,每一項任務分別要修改程式碼中的哪一部分,你可以下載和 TODO關鍵字 相關的插件在自己的編輯器中。大作業的任務們都有用 `# TODO` 做上標記及編號,透過插件你可以很快速的定位該任務你所需要修改的地方。 對於使用VSCode的同學,這裡推薦一個第一週就有講師推薦過的插件 [TODO Tree](https://marketplace.visualstudio.com/items?itemName=Gruntfuggly.todo-tree) ,使用它讓你的大作業更順利。 ### 獲取作業 #### 下載作業 到 <a href="#Links" smoothhashscroll>Links</a> 作業程式連結裡下載作業,檔案為壓縮檔,解壓縮後可在資料夾裡看到以下檔案: ::: spoiler <span class="weak_hint"> 資料夾檔案圖片 </span> <br/> ![螢幕擷取畫面 2024-03-17 202702](https://hackmd.io/_uploads/rJ2h-vECa.png) ::: #### 執行方式 打開 `命令提示字元` 或者是 `terminal`,輸入以下指令: ``` cd <上面檔案存放的母資料夾路徑> ``` 接下來輸入: ``` python main.py ``` 或者是: ``` python3 main.py ``` 來執行作業程式。 :::spoiler <span class="weak_hint"> 執行範例 </span> <br/> 這些檔案被存放在 C:\Users\anonymous\Desktop\Flappy_Bird 中,則輸入以下指令後`ENTER` ``` cd C:\Users\anonymous\Desktop\Flappy_Bird ``` 再輸入以下指令後`ENTER`, ``` python main.py ``` ::: <br/> 執行成功後,會看到的遊戲視窗如下: ::: spoiler <span class="weak_hint"> 遊戲視窗畫面 </span> <br/> ![螢幕擷取畫面 2024-03-17 204547](https://hackmd.io/_uploads/BkIfLPE06.png) ::: <br/> 到這裡就成功下載好作業了,用你喜歡的編輯器開始寫作業吧! ### 防雷區 以下列舉一些過程中你可能會遇到的問題,在遇到困難時不妨來這裡看看,你的問題有沒有在其中。 #### 環境變數問題 如果你在下載 pygame 套件步驟時,發現視窗中顯示以下文字: ``` 不是內部或外部命令、可執行的程式或批次檔 ``` 或者是跳出其他視窗,而沒有在原本的視窗中出現文字的下載進度條。 在確定你的電腦中安裝有 python 的情況下, 那麼問題有可能是來自,沒有設定好 python 的系統環境變數。 你可以用 `[你的作業系統]+python環境變數` 當關鍵字在網路上搜尋相關的處理方式。 使用 Mac/Linux 的同學可以到網路上查詢指令解決。 使用 Windows 的同學可以參考以下簡單的處理方式: :::spoiler <span class="weak_hint" >Windows 解法參考</span> ##### 確認你常用的python裝在哪個資料夾 為避免"孿生python悖論"(並沒有)導致你接下來設定的,和你實際上常用的不一致。請先確定你常用的 python 執行檔被存在哪個資料夾。 以上課用的VSCode做教學, 隨意點開一個 python 程式後按執行。 > 這是筆者的執行畫面,只是示意,你的路徑不是這個QQ ![螢幕擷取畫面 2024-03-17 212547](https://hackmd.io/_uploads/r1Su1ONCp.png) 黃色的字樣就是你常用的 python 執行檔路徑, 其所在資料夾是 python.exe 前面的那串路徑, 將其複製好後進行下一步。 ##### 設定環境變數 - 在`命令提示字元`中輸入: ``` rundll32 sysdm.cpl,EditEnvironmentVariables ``` 後按 `ENTER` 即可開啟`編輯系統環境變數`。 ![螢幕擷取畫面 2024-03-17 214538](https://hackmd.io/_uploads/SJ_ONONA6.png) 點選`Path`使其反白後按`編輯`, 按`新增`並貼上你從VSCode中複製過來的路徑: ``` C:\Users\anonymous\...\ ``` 再`新增`一個: ``` C:\Users\anonymous\...\Scripts\ ``` 設定完成後按確認,重開`命令提示字元`後即可排除問題。 ::: #### 視窗大小問題 如果你成功打開了上方的遊戲視窗,卻發現視窗過大/過小,那麼意味著你可以直接開始著手作業程式的部分進行修改了! 打開作業程式中的 `config.py` ,此檔案中定義了許多你可能會用到的常數。 找到 `BACKGROUND_SCALE` 變數,此變數用來表示背景的縮放值常數,調整它讓視窗呈現令你舒適的大小。 --- ## 作業說明 > 小芽是一位富有創造力的軟體工程師,他對於技術的探索和創新充滿了無限的熱情。儘管工作繁忙,但在閒暇時間,他喜歡探索各種新奇的事物,其中包括刷 YouTube Shorts 來放鬆心情。 > > 一天,小芽無意間刷到一個引人入勝的影片,這是一款名為 [Flappy Bird](https://zh.wikipedia.org/zh-tw/Flappy_Bird) 的遊戲,他被畫面中那簡單無腦卻極具挑戰性的遊戲內容所吸引。盡管營銷號笨如菜雞的操作讓他差點昏厥,卻並不減少他對這款遊戲的興趣。 > > 小芽迫不及待地上網搜索了Flappy Bird 網頁版,迅速投入到了遊戲的世界中。儘管是第一次嘗試,他單身50年的手速也讓他輕鬆破台了這款遊戲,這讓他感到悵然若失。 > > 然而,小芽並不是個輕言放棄的人。他想,為何不自己動手製作一個屬於自己的 Flappy Bird 呢?這個想法在他心中生根,像是一顆資訊之芽迅速成長,充滿了他整個思緒。 > > 於是,小芽展開了他的創作之旅。但故事迎來了轉折,因為長時間使用電腦,小芽得到了腕隧道症候群,在醫生的建議下他中止了遊戲的開發,甚是遺憾。 > > 熱心的你決定冒著得到腕隧道症候群的風險,幫助可憐的小芽完成他夢想中的Flappy Bird。 ### 遊戲內容 - 透過點擊滑鼠左鍵讓Flappy Bird獲得向上的動力,往上飛。 - 在未點擊時,Flappy Bird會因重力而自由下墜。 - 場上會出現兩兩成對的水管對,當Flappy Bird撞到水管則遊戲結束。 - 這些水管很皮(?),它們會移動。 - 玩家控制Flappy Bird避開盡可能多的水管以賺取分數。 ### 檔案內容 - `config.py` 中定義了許多你可能會用到的常數,在開始上手程式前,不妨先翻翻看,了解有哪些常數你可以不用自己找。 - `main.py` 是程式的進入點,執行這支程式可以開啟你的遊戲。 - `helper.py` 是放置一些幫手的地方,你可以把關係上較為獨立,或者是多處可用的一些函式、物件放置在這裡。 - `game.py` 放置遊戲物件,控制遊戲流程、遊戲中的物件、及管理遊戲物件間彼此互動的物件。 - `base.py` 放置地基物件,定義遊戲中最下方的地基的物件。 - `bird.py` 放置鳥(玩家)物件,定義遊戲中鳥(玩家)的物件。 - `pipe.py` 放置水管物件,定義了遊戲中和水管相關的物件。 - `number.py` 放置記分板中,單一位數數字的數字物件。 - `scoreboard.py` 放置記分板物件,定義遊戲中最上方所顯示的記分板。 ### 小內容提醒 Pygame中的座標位置和我們在數學中用的不太一樣, 數學上 x 軸向右為正 y 軸向上為正, (0,0)在左下角 Pygame中 x 軸向右為正 y 軸向下為正, (0,0)在左上角 遊戲中各物件的座標定位略有不同,詳細都說明在檔案中 ### Tasks 以下列舉了你需要完成的任務,任務編排為推薦完成的順序,當然也可以依據個人偏好順序完成。 你從小芽完成一半的程式接續製作,但小芽的程式內容僅為 支援某些已完成的內容,及提供未來“可能“的實作便利性 而存在。你可以依照小芽留下的線索完成任務。但某些時候,你也可以**任意**對小芽的程式進行想要的調整。 Optional系列最高只會得到15pts (也就是可以四選二或三),Extra系列最高只會得到10pts。 一般得分(包括Optional)每一筆的得分都會有: - 45% 功能完成 - 50% 功能穩定(能重複不斷成功發生) - 5% code乾淨程度(不要太髒即可) Extra 得分則是有完成功能即可拿滿。 #### 01. 讓世界動起來 (10pts) 完成 `base.py` 中的 TODO 0 - [ ] (10pts) 讓下方的地基動起來 #### 02. 讓鳥鳥飛起來 (20pts) 完成 `bird.py` 中的 TODO 1, 2 - [ ] (5pts) 讓鳥(玩家)能夠垂直移動 - [ ] (5pts) 讓鳥(玩家)在接收到滑鼠點擊的訊號時,能向上移動 並讓鳥(玩家)在未接受到滑鼠點擊的訊號時,能向下移動 - [ ] (10pts) 讓鳥(玩家)在接收到單一次滑鼠點擊的訊號後,能"自然"移動 (note: 看起來像受到重力影響,像是有向上初速垂直拋起的拋體) #### 03. 把水管加進來 (15pts) 完成 `pipe.py` 中的 TODO 3 - [ ] (15pts) 讓水管能以合理的速率加到遊戲中 #### 休息一下 :::info 恭喜你,到這裡你應該完成了基本能夠運行的遊戲 後面任務出現的順序比較沒有先後關係,可以依照自己喜歡的順序完成 :::spoiler <span style="display: none;">_</span> ![1280](https://hackmd.io/_uploads/HJD405N06.png) ::: #### 04. 讓鳥鳥更生動 (10pts) 完成 `bird.py` 中的 TODO 4 - [ ] (5pts) 讓鳥(玩家)以合理的速率持續拍動翅膀 - [ ] (5pts) 讓鳥(玩家)向上飛時略往上仰,向下墜時略往下看 #### 05. 有個性的水管 (10pts) 完成 `pipe.py` 中的 TODO 5 - [ ] (5pts) 讓每次新出現的上下水管間隙及開口位置略有不同 - [ ] (5pts) 讓遊戲的"難度"能隨著時間推進漸漸增加 #### 06. 記分板 (10pts) 完成 `scoreboard.py` 中的 TODO 6 - [ ] (5pts) 在視窗中間偏上的位置顯示出數字表示得分 - [ ] (5pts) 在玩家(鳥)每經過一對水管時,往上加一分 #### 07. 更多遊戲流程 (5pts+10pts) 完成 `game.py` 中的 TODO 7 - [ ] (5pts) 等待玩家第一次點擊才開始遊戲 - [ ] (Option 1 5pts) 結束時顯示 Game Over 提示語並顯示得分 (參考pygame docs與圖片、文字在視窗中顯示相關的功能) - [ ] (Option 2 5pts) 遊戲結束後,讓玩家能按任意鍵重新開始遊戲 - [ ] (Extra 5pts) 其他豐富遊戲的功能(暫停功能、歷史分數紀錄 etc) #### 08. 過動的水管 (+10pts) 完成 `pipe.py` 中的 TODO 8 - [ ] (Option 3 5pts) 讓每一對水管對能朝固定目標移動,不同對間彼此需朝自己(不同)的目標移動 (note: 為維持遊戲的可玩性,水管的移動僅為擾亂玩家視線,而非限制玩家移動, 需在合理的時間內變回固定位置) - [ ] (Option 4 5pts) 讓每一對水管對能朝>1種移動方向移動 - [ ] (Extra 5pts) 以"繼承"的方式實作帶有移動模式的水管、水管對 - [ ] (Extra 5pts) 做出其他種移動模式的水管、水管對 #### 其他 (Extra 0~5pts) 任何自己做出來的新功能,或是在此作業中用到額外學習的內容,都可能可以爭取到額外的分數。 請在這些內容的前方加上 `#TODO` 的註解,並簡單描述你實做的東西,以方便批改。 --- ## 繳交作業 到 <a href="#Links">Links</a> 作業繳交表單連結中繳交作業 繳交檔案需為壓縮檔,將你整個專案資料夾底下的所有檔案放在同一個名為 `[姓名]_資芽py班大作業` 的資料夾底下,壓縮此資料夾成.zip檔後繳交 e.g. 王小明應該會繳交 `王小明_資芽py班大作業.zip` 表單會設為可修改,期間內不滿意/發現有bug都可以修改回覆的內容 --- ## 問答&後續公告 ### Announcement :::info 3/24 更 1: 程式連結進去的程式是好的,請安心服用。 3/24 更 2: 有一些上課來不及說,但有點重要的放在FAQ 02. 大家記得看。 3/24 更 3: 這次作業會隨著大家的提問,解鎖更多的hint,希望大家踴躍提問。 3/29 更 1: 更新`config.py`裡的圖片路徑設定,可以到 <a href="#Links">Links</a> 去下載新的`config.py`下來更換。 3/29 更 2: 作業程式連結裡的`config.py`也更新成新版了,3/29後下載的不需要另外再更新。 4/14 更 1: 更新`number.py`裡的`draw`方法不存在的問題,可以到 <a href="#Links">Links</a> 去下載新的`number.py`下來更換。 4/17 更 1: `pipe.py`中,`class Pipe`的建構子`__init__`參數註解誤植,`direction`為水管開口的方向,應為`"UP"`或`"DOWN"`,表示此水管開口朝上(下面那根)或者朝下(上面那根)。 ::: ### FAQ :::spoiler <span class="weak_hint"> 00. 如何提問 </span> <br/> > Ans: 你可以透過 Discord群組 或者使用 HackMD 的留言功能 進行反饋/問問題/投訴(?),被解決過的問題就會像這裡的形式,精選後留下,供大家查詢、參考。 ::: <br/> :::spoiler <span class="weak_hint"> 01. 不會寫怎麼辦 </span> <br/> > Ans: 你可以利用 Discord群組 和學員們、講師們進行交流、討論,也可以在 課堂下課時 向左右鄰居、後面的講師們面對面聊聊,相信大家都非常樂意幫助你解決問題、提供想法給你。 ::: <br/> ::: spoiler <span class="weak_hint"> 02. 我不知道到底要寫什麼 </span> <br/> > Ans: 你可以把這次作業看成 I/O 形式和平常不同的作業。 Input來自每一個class裡存著的屬性及可用的方法,或者說是,上一個時刻的遊戲狀態。 Output就是要更改這些遊戲狀態成下一個時刻該有的狀態。 由於我們會在每一新時刻開始前呼叫每個物件的 `.update()`,因此 `.update()` (你要寫的內容)需要維護好這個class裡,會因為時間或其他因素產生改變的屬性,讓他們變成新的狀態。 也就是,在`.update()`中完成 Output 的要求。 (你會發現有的任務請你修改的不在`.update()`中,但它們都會在`.update()`中被呼叫) 至於詳細要完成些什麼,就是每個不同的任務了。 e.g. TODO 0 在`base.py`中的`Base`物件紀錄有`.scroll`的屬性代表地板圖片的滑動(平移),我們希望這個地板圖片有不斷捲動的效果。 你可以先解讀這段話成平常寫judge時會有的樣子: Input: 給定`.scroll`屬性代表上一刻地板圖片與其原本位置的平移量。 Output: 請將`.scroll`屬性更新成下一刻地板圖片與其原本位置的平移量。讓下一刻與這一刻的地板圖片,看起來有捲動的效果。 我們要做的會是 將 `Output: 下一刻的.scroll` 設定成 `Input: 上一刻的.scroll` 加一點點變動量,看起來就會有不斷平移的效果(你可以用物理課學到過的 $x = x_0 + vt$ 來理解,其中 $v (單位長/次更新)* 1(次更新)$ 就會是變動量 $v (單位長)$)。 但單純只有位移的邏輯是不夠的。因為圖片是有限長度,當你將圖片不斷往左移,最終會露出破綻(`圖片起始位置+圖片長度` 落在視窗中,破綻是在視窗中看到圖片結束的斷點)。 因此我們加上`當更新完會露出破綻時,讓平移量歸0`的邏輯,來達成會不斷不斷重複平移的效果(可以將它想像成,當他抵達終點時,再把他拉回起點開始跑),透過這樣的邏輯去取得我們的 Output ,便可達成任務。 ::: <br/> :::spoiler <span class="weak_hint"> 03. 運行程式沒有跳出視窗怎麼辦 </span> <br/> > Ans: 首先先檢查你是否是運行 `main.py` 以開啟你的程式。若你遇到的是`No file found in working directory`的情況,記得下載新版本的`config.py`取代原本的`config.py`來快速解決此問題。 若還是無法開啟,可以在 Discord 中詢問,我們會盡快提供協助。 ::: <br/> :::spoiler <span class="weak_hint"> 04. 如何在計分板的更新函式中獲得水管數量相關的資訊 </span> <br/> > Ans: 要如何在函式中獲得外面的資訊,你可以透過參數傳遞的方式來達成。 所以要達成這個目的,你需要改 > 1. scoreboard的update方法,讓他可以接受一個水管數量的參數 > 2. 找到同時控制pipe和scoreboard的地方,就是game這個管理所有實體的物件啦。找到呼叫pipe.update()的地方,把你需要的水管數量參數傳遞進去。 > 3. 至於水管數量在哪裡,你就需要看pipe中有沒有相關的屬性供你使用。 ::: <br/>