更新於 2022/06/18閱讀時間約 11 分鐘

【Python】那些年我們一起玩過的遊戲(一)-太空侵略者

可能是初老症發作的的原因,最近玩到這類懷舊遊戲就很容易陷入某種懷舊時光的情緒中,一不小心就會玩到忘了時間,所以就興起了何不自己動手把童年那些有印象的街機遊戲全部實作一遍的念頭呢?不囉嗦以下就是這系列的第一款,我會先從提案企劃→執行企劃→製作日誌一一作紀錄,希望對想學作遊戲的同好有所幫助, 另外,我也不確定能堅持幾款,只希望不要一款就沒後續就好,以下開始正文。
在開始之前我們先來看看完成後的遊玩影片:

A、提案企劃書

一句話形容這個遊戲
  • 勾起老遊戲人復古情懷的小品遊戲

遊戲類型
  • 射擊類

遊戲特色
  • 懷舊復古風
  • 點陣圖

發想概念
  • 致敬1978年由Taito在日本製造和銷售的太空侵略者(Space Invaders)
  • 藉以重製太空侵略者(Space Invaders)遊戲學習Python語言

遊戲玩法
  • 玩家控制飛機左右移動,發射子彈射擊上方的飛機,示意圖如下:
示意圖

目標族群
  • 想用Python學做遊戲的人
  • 勾起老玩家回憶,發現往事不堪回首的人

發行平台
  • Windows
  • MAC
  • Linux

預計製作期
  • 10天

美術風格
  • 2D點陣圖風格

技術特色
  • 實現將圖像編碼成字串並內崁在程式碼內,以取代讀外部圖檔的功能

遊戲周邊
  • 手機吊飾
  • LINE貼圖

製作人員需求
  • 企劃 x 1
  • 美術 x 1
  • 程式 x 1

收費方式
  • 佛系遊戲緣分到了自動有收入

製作預算
  • 不要問你會怕

參考資料

B、執行企劃書

前言
  • 本遊戲玩法大致上與Taito在1978年發行的太空侵略者(Space Invaders)相同,只是在玩法上作了一些簡化,其調整內容後續會在陸續說明。

遊戲流程
遊戲流程圖

遊戲玩法說明
  • 遊戲畫面示意圖

玩家相關說明
  • 玩家操作飛機左右移動,一邊閃躲敵人發射下來子彈一邊發射子彈射擊敵人
  • 玩家飛機一次只能發射一發子彈,要等子彈擊中敵機或超出畫面消失後才能再發射下一發子彈
  • 玩家飛機死亡條件
  1. 被敵人子彈打中
  2. 被任一隻敵人碰到
  • 遊戲一開始玩家一共有三條命,全部死亡後即遊戲結束

敵人相關說明
  • 敵人會有五列,每列11隻敵人,排列方式如下:
  1. 敵人1 x 11
  2. 敵人2 x 11
  3. 敵人2 x 11
  4. 敵人3 x 11
  5. 敵人3 x 11
  • 敵人移動方式
  1. 畫面上的敵人會從最後一排整列往右移動8像素,移動完後換最後第二排往右移動8像素,接下來陸續最後第三排、第四排、第五排,然後在回到最後一排如此重複移動,直到畫面上的所有敵人移動到離右邊界100像素後,全部敵人往下移動20像素,然後在依上面規則開始往左移動,直到移動到離左邊界100像素後,全部敵人往下移動20像素,然後就重複以上規則在開始右移,如此反覆移動
  2. 每下降一次速度就變快一點
  • 飛碟每隔10秒會從左邊慢慢往右邊移動
  • 擊中敵人加分表如下:
  1. 敵人1 加30分
  2. 敵人2 加20分
  3. 敵人3 加10分
  4. 飛碟 加60分
  • 分數每增加2000分會增加一台玩家飛機生命,上限為5台
  • 敵人發射子彈機率
  1. 每隔1秒從场景中挑出一位敵人發射子彈
  2. 全部敵人每下降一次發射時間就縮短一點

過關條件
  • 將畫面上所有敵機摧毀後就會進入下一關
  • 下一關只是復原原本生出的敵機並繼續讓玩家射擊,如此循環直到玩家飛機全部死亡為止

遊戲結束條件
  • 玩家飛機隻數全部死亡
  • 敵機下降到底線

遊戲操作
滑鼠
  • 遊戲中
  1. 左右移動操作 玩家飛機
  2. 點擊滑鼠左鍵發射子彈
  • GameOver畫面
  1. 點擊滑鼠左鍵重新開始遊戲
鍵盤
  • F鍵:開關遊戲FPS顯示
  • Esc 鍵:離開遊戲

遊戲系統
點陣動畫系統
  • 本專案使用的圖形都是一些較簡單的單色點陣圖,所以希望能研發一工具可將圖檔傳換成字串,然後將此圖檔以字串方式內崁入到程式碼內,也就是說不以讀外部圖檔的方式來讀圖檔
  • 圖檔編碼方式說明如下:
  • 以下為將格子填上數字的圖檔,我們先挑出填滿黑色格子內的數字:
  • 依照規則第一張圖挑出填滿黑色格子內的數字號碼為:
  • (3,4,10,11,12,13,17,18,19,20,21,22,24,25,27,28,30,31,32,33,34,35,36,37,38 ,39,42,45,49,51,52,54,56,58,61,63)
  • 依照規則第二張圖挑出填滿黑色格子內的數字號碼為:
  • (3,4,10,11,12,13,17,18,19,20,21,22,24,25,27,28,30,31,32,33,34,35,36,37,38 ,39,41,43,44,46,48,55,57,62)
  • 程式讀入以上數字編碼字串後,在依照數字編碼位置畫出黑色Box就可以重現圖案內容的圖像了
  • 程式提供播放動畫功能
  • 程式提供移動功能
  • 程式提供改變顏色功能
  • 程式提供判斷碰撞功能
計分系統
  • 玩家操作飛機擊中敵人後會累積分數
  • 擊中敵人分數計算方式如下:
  1. 敵人1–30分
  2. 敵人2–20分
  3. 敵人3–10分
  4. 飛碟 — 60分
  • 最高分數紀錄
  • GameOver後系統會將這局玩的分數與最高分數作比較,如果大於最高分數,就會更新為本局分數,並顯示在畫面上。

遊戲介面

美術風格

美術元件列表
敵人1
  • 像素:8 x 8
  • 格數:2 frame
敵人2
  • 像素:11 x 8
  • 格數:2 frame
敵人3
  • 像素:12 x 8
  • 格數:2 frame
敵人子彈
  • 像素:3 x 7
  • 格數:2 frame
飛碟
  • 像素:16 x 7
  • 格數:1 frame
主角飛機
  • 像素:15 x 8
  • 格數:1 frame
主角飛彈
  • 像素:1 x 4
  • 格數:1 frame
爆炸效果
  • 像素:11 x 9
  • 格數:1 frame

C、製作日誌

開發工具
  • Python 3.7.0
  • PyGame
第1~3天
  • “點陣動畫系統”是我在這個專案第一完成的系統,在看完執行企劃後,就決定用pygame的基礎繪圖功能來製作重繪點陣區塊,實作後的效果其實還不錯,已將程式碼放置GitHub Gist上,點選以下連結查看:

【drewEngine.py程式碼】
程式碼內已寫上詳細說明
第4~10天
  • 接下來要開始實作遊戲Gameplay的部分,要實作的功能不少,已將程式碼放置GitHub Gist上,點選以下連結查看:

【play.py程式碼】
程式碼內已寫上詳細說明,以下在針對需要特別說明的部分加強解說
  • 15 ~ 33:遊戲參數設定,調整這邊的數值可以改變遊戲平衡
  • 35 ~ 63:這邊針對執行企劃文件內”點陣動畫系統”部分,所敘述的將圖形編碼成字串方式針對每張圖作編碼並存放在陣列內,一維以上的陣列會循環撥放,以達到動畫效果
  • 75:時脈陣列,紀錄遊戲裡面所有需要計算時間的時脈紀錄,舉例一下,請看以下程式碼:
# 移動敵人.
if((pygame.time.get_ticks() — last_time[0]) >= enemy_speed):
  • 這邊會將現在時間減掉last_time[0]時脈後如果大於設定的enemy_speed就會進入判斷式內執行,執行完記的要將現在時間寫回去,如下:
last_time[0] = pygame.time.get_ticks()
  • 209 ~ 254:產生所有遊戲所有需要用到的圖形物件
  • 263 ~ 512:遊戲主迴圈
  • 270 ~ 280:判斷鍵盤輸入
  • 283 ~ 302:判斷滑鼠輸入,可由game_mode變數判斷遊戲狀態,在game_mode = 20時表示遊戲進入Game Over狀態,在這狀態下玩家按下Mouse左鍵就可以重新開始遊戲
  • 309 ~ 318:處理讓玩家飛機跟隨滑鼠游標
  • 321 ~ 326:處理玩家飛彈移動
  • 327 ~ 362:處理敵人移動與每下降一次速度變快、子彈速度變短,跟敵人碰到主角飛機還有敵人超出下邊界時將狀態設定成Game Over模式(game_mode = 20)
  • 365 ~ 366:處理每隔N秒出現飛碟
  • 388 ~ 412:處理更新所有敵人,並判斷玩家發射的子彈有無碰撞到敵人,跟打死敵人加分,分數是2000分倍數就加一隻,還有敵人全滅處理遊戲初始設定並繼續進入下一關
  • 409 ~ 410:存入活著的敵人編號
  • 415 ~ 446:處理敵人發射子彈,移動子彈,判斷發射的子彈是否碰到玩家
  • 448 ~ 455:顯示開啟的爆炸圖像,N秒後會自動關閉
  • 457 ~ 468:處理玩家飛機重新,扣生命,如果已經沒生命數了就進入Game Over模式(game_mode = 20)
  • 470 ~ 484:判斷玩家發射的子彈是否打中飛碟,打中後處理顯示爆炸圖像與加分數,跟加隻判斷
  • 485 ~ 491:顯示Game Over畫面,並判斷此局分數是否有大於最高分,如果大於最高分的話就將本局分數更新為最高分數
  • 497 ~ 514:顯示畫面UI,如分數、剩餘數量、最高分等。。。

執行遊戲
  • 請在命令列下輸入python play.py 以執行遊戲

GitHub下載原始碼

後記
第一款完成,第二款也正在構思中,希望能有時間盡快付諸行動,以上,下次見。。。

版本更新

2020/03/29
  • Q:如何將畫面切換成全螢幕?
  • A:在play.py找到如下程式碼:
  • canvas = pygame.display.set_mode((canvas_width, canvas_height))
  • 並修改成以下方式:
  • canvas = pygame.display.set_mode((canvas_width, canvas_height), pygame.DOUBLEBUF and pygame.FULLSCREEN )
2018/10/20
  • 新增灰階版本(play_gray_scale.py)以更新至GitHub
分享至
成為作者繼續創作的動力吧!
© 2024 vocus All rights reserved.