---
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/>

:::
<br/>
在命令提示字元中輸入以下指令:
```
python -m pip install -U pygame==2.5.2 --user
```
::: spoiler <span class="weak_hint"> 範例畫面 </span>
<br/>
(介面可能會根據版本/設定不同有所變化,大致是如下圖的文字介面)

:::
<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/>

:::
#### 執行方式
打開 `命令提示字元` 或者是 `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/>

:::
<br/>
到這裡就成功下載好作業了,用你喜歡的編輯器開始寫作業吧!
### 防雷區
以下列舉一些過程中你可能會遇到的問題,在遇到困難時不妨來這裡看看,你的問題有沒有在其中。
#### 環境變數問題
如果你在下載 pygame 套件步驟時,發現視窗中顯示以下文字:
```
不是內部或外部命令、可執行的程式或批次檔
```
或者是跳出其他視窗,而沒有在原本的視窗中出現文字的下載進度條。
在確定你的電腦中安裝有 python 的情況下,
那麼問題有可能是來自,沒有設定好 python 的系統環境變數。
你可以用 `[你的作業系統]+python環境變數` 當關鍵字在網路上搜尋相關的處理方式。
使用 Mac/Linux 的同學可以到網路上查詢指令解決。
使用 Windows 的同學可以參考以下簡單的處理方式:
:::spoiler <span class="weak_hint" >Windows 解法參考</span>
##### 確認你常用的python裝在哪個資料夾
為避免"孿生python悖論"(並沒有)導致你接下來設定的,和你實際上常用的不一致。請先確定你常用的 python 執行檔被存在哪個資料夾。
以上課用的VSCode做教學,
隨意點開一個 python 程式後按執行。
> 這是筆者的執行畫面,只是示意,你的路徑不是這個QQ

黃色的字樣就是你常用的 python 執行檔路徑,
其所在資料夾是 python.exe 前面的那串路徑,
將其複製好後進行下一步。
##### 設定環境變數
- 在`命令提示字元`中輸入:
```
rundll32 sysdm.cpl,EditEnvironmentVariables
```
後按 `ENTER` 即可開啟`編輯系統環境變數`。

點選`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>

:::
#### 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/>