主題
設計一個「射擊」(Shooting)遊戲。
學習目標
學習如何使用 Canvas、Ball、ImageSprite、Slider、Spinner、Clock、Sound、AccelerometerSensor 這些元件。
功能
- 使用者可選怪物(Monster)的數目(1~8),預設有 8 個怪物。怪物先擺放在畫布的上面,下面有一架戰鬥機(Fighter),可發射子彈。
- 開始玩,怪物隨機往下移動,碰到子彈,此怪物就消失,得分加1分。如果怪物都消失,結束遊戲。當怪物碰到Canvas(畫布)邊緣或其它怪物,就反彈,碰到戰鬥機,會發出音效,戰鬥機的生命力減1 (生命力初始值設為5),如果生命力小於或等於0,結束遊戲。
- 子彈速度和怪物速度,皆可由玩家調整。
- 傾斜(tilt)手機可移動戰鬥機,搖晃(shake)手機可加快子彈的速度。
- 使用計時器記錄玩遊戲的時間。
執行畫面
開始畫面:
當畫布被壓下(TouchDown)(即使用者觸壓到螢幕畫布的區域),發射子彈。
生命力小於或等於0,結束遊戲:
怪物都消失,結束遊戲:
素材
本 app的 icon (圖示),可自己繪製或網路搜尋。以下是阿旺師繪製的圖片:
shooting.jpg
如果使用網路的作品,請注意著作權。可使用 創用CC的作品,但要知道其標示圖章的意義,並遵守其規定。如果是 CC0 , 就比較沒有限制。
免費線上去背(移除影像背景), Adobe Express。
免費音效
線上聲音剪輯(將聲音剪短)
進入 Appinventor
Google 輸入 appinventor,選 「MIT App Inventor」。
選 「Create Apps」。
網址為 :
http://ai2.appinventor.mit.edu/本主題是修改 阿旺師的 「手機 App 程式設計- AppInventor2 -打磚塊」此篇文章。
開啟原來的舊專案(My Projects/My projects),選舊專案,如 breakout_clone,按一下,打開此專案。另存新專案(My Projects/ Save project as... ),輸入新專案的名稱,如 Shooting,按 「OK」鈕 。專案的名稱只能使用大小寫字母、數字及「 _」符號,名稱的第一個字元必須是英文字母,不能使用中文字。
註:如果要開 新專案 也可以,Projects/Start new project,輸入新專案的名稱。
Designer (畫面編排)
Screen1:
Screen1 元件相關屬性表
元件
|
類別
|
屬性
|
功能
|
Screen1
|
|
AppName: Shooting,可以改成「射擊遊戲」(出現在手機上面的App名稱)
Icon : shooting.jpg
ScreenOrientation(螢幕方向):Portrait(鎖定直式畫面)
Scrollable:勾選 (如果下面的怪物速度和怪物數目看不到,要能往下捲動,才看得到)
Title:射擊遊戲
|
1個Screen元件就是1個螢幕 (畫面)。設定為Portrait,避免使用者晃動手機造成螢幕方向轉換。
|
Canvas1
|
Drawing and Animation(繪圖動畫)
|
BackgroundColor(背景顏色):Black(黑色)
Height:400
Width:Fill Parent(填滿)
|
畫布
|
ImageSprite_Fighter
|
Drawing and Animation
|
Image: fighter.png
|
圖像精靈
戰鬥機
|
Ball1
|
Drawing and Animation
|
PaintColor(畫筆顏色):White (白色)
Radius(半徑):6
|
球形精靈
子彈
|
ImageSprite_Monster1
|
Drawing and Animation
|
Picture: Monster.png
Rotates:勾選 (移動時會旋轉)
|
圖像精靈
怪物
|
……
|
|
|
圖像精靈
|
ImageSprite_Monster8
|
Drawing and Animation
|
有8個ImageSprite_Monster
Rotates:勾選 (移動時會旋轉)
|
圖像精靈
最多有8個怪物
|
Label_Vitality
|
User Interface(使用者介面)
|
Text:生命力:
|
標籤
|
Label_Score
|
User Interface(使用者介面)
|
Text:分數:
|
標籤
|
HorizontalArrangement_Play
|
Layout(介面配置)
|
AlignVertical:Center:2(垂直對齊,居中:2 )。
Width:Fill Parent (填滿)
|
水平配置元件,讓裏面的元件可以水平對齊。
|
Button_Play
|
User Interface
|
Text:開始
|
按鈕
|
Button_Replay
|
User Interface
|
Text:重玩
|
按鈕
|
HorizontalArrangement_BulletSpeed
|
Layout(介面配置)
|
AlignVertical:Center:2(垂直對齊,居中:2 )。
Width:Fill Parent (填滿)
|
水平配置元件,讓裏面的元件可以水平對齊。
|
Label_BulletSpeed
|
User Interface
|
Text: 子彈速度:
|
標籤
|
Slider_BulletSpeed
|
User Interface
|
Width: 100 pixels MaxValue:30 MinValue:1 ThumbPosition(指針位置):3
|
滑桿
|
HorizontalArrangement_MonsterSpeed
|
Layout(介面配置)
|
AlignVertical:Center:2(垂直對齊,居中:2 )。
Width:Fill Parent (填滿)
|
水平配置元件,讓裏面的元件可以水平對齊。
|
Label_MonsterSpeed
|
User Interface
|
Text:怪物速度:
|
標籤
|
Slider_MonsterSpeed
|
User Interface
|
Width: 100 pixels MaxValue:20 MinValue:5 ThumbPosition(指針位置):10
|
滑桿
|
HorizontalArrangement_MonsterNumber
|
Layout(介面配置)
|
AlignVertical:Center:2(垂直對齊,居中:2 )。
Width:Fill Parent (填滿)
|
水平配置元件,讓裏面的元件可以水平對齊。
|
Label_MonsterNumber
|
User Interface
|
Text:怪物數目:
|
標籤
|
Spinner_MonsterNumber
|
User Interface
|
ElementsFromString: 1,2,3,4,5,6,7,8
Prompt:怪物數目
Selection:8 (預設先選取8,表示有8個怪物)
|
下拉式選單
|
Sound_Hit
|
Media(多媒體)
|
Source:hit.wav(子彈打中的音效)
|
音效
|
Sound_Monster
|
Media(多媒體)
|
Source:wow.mp3(怪物碰到戰鬥機的音效)
|
音效
|
Clock1
|
Sensors(感測器)
|
TimerEnabled:不勾選
TimerInterval(計時間隔):1000 (毫秒)
|
計時器
|
AccelerometerSensor1
|
Sensors(感測器)
|
Enabled(啟用):不勾選
|
加速度感測器
|
輸入文字
遊戲結束,分數為: ,時間: 分數為: 生命力:
Blocks(程式設計)拼塊
跟元件有關的拼塊,要先點選該元件後,再選擇是那一個拼塊;不是元件的拼塊,可以根據拼塊的顏色,判斷是屬於那一個類別。
Screen1:
----------------------------------------------------------------
說明:
全域性變數 Columns,表示一列有幾欄,即幾個怪物,本例是4個。
全域性變數 Monster_List,怪物清單。先設為空的清單。
全域性變數 ListX,每一個怪物的 X 座標所形成的清單。
全域性變數 ListY,每一個怪物的 Y 座標所形成的清單。
全域性變數 Score,得到的分數。
全域性變數 Score_Increment,打到一個怪物得幾分。
全域性變數 Spend_Time,遊戲所花的時間。
全域性變數 Vitality,生命力,初始值為5。
-----------------------------------------------------------------------------------
---------------------------------------------------------------
說明:
阿旺師想出一維陣列轉為2維陣列的演算法來算出每個怪物的位置,請參考 阿旺師的 「手機 App 程式設計- AppInventor2 -打磚塊」的程式說明。
---------------------------------------------------------------
----------------------------------------------------------------
說明:
將 ImageSprite_Monster1 .... ImageSprite_Monster8 這8個元件,先放入 Monster_List 此清單內。
根據使用者選的怪物數目,從 Monster_List移除多餘的怪物。
----------------------------------------------------------------
---------------------------------------------------------------
說明:
Monster_List 是由怪物 組成的清單。
設定Monster_List的每一個元素(ImageSprite 圖像精靈 )的 Enabled (啟用)設為 false(即未啟用), Visible(可見性)設為 true (即顯示出來 ), X 的值為對應的 ListX 值,Y 的值為對應的 ListY 值。
例如 ListX 的第1個元素的值是放 怪物1的X 。ListY 的第1個元素的值是放 怪物1的Y。
---------------------------------------------------------------
---------------------------------------------------------------
說明:
顯示結果:分數和所花的時間(轉換為幾分幾秒 )、生命力。
---------------------------------------------------------------
---------------------------------------------------------------
說明:
重新排列 Monster、Fighter的位置, 儘量放在中間。
Ball1的Visibe 設為 false,看不到子彈,因為一開始子彈尚未發射。
---------------------------------------------------------------
---------------------------------------------------------------
說明:
當遊戲結束,要執行的動作。把一些元件的Enabled設為false, 即沒有啟用。
---------------------------------------------------------------
---------------------------------------------------------------
Screen1_initialize (初始化):當Screen1 出現(螢幕初始畫面),要執行的動作。
---------------------------------------------------------------
---------------------------------------------------------------
當使用者按了「開始」按鈕時,要執行的動作。Click:被點選。
設定Monster.Heading(指向)前進的方向 為 225 到325之間的亂數整數。即一開始玩時,怪物是往下移動,角度是 225 到325 中的隨機一個數字。
---------------------------------------------------------------
---------------------------------------------------------------
說明:
因為 Clock1的TimerInterval(計時間隔)設為1000 (毫秒),即1秒鐘執行 Clock1.Timer (計時)事件程序1次。 把Spend_Time加1。
---------------------------------------------------------------
---------------------------------------------------------------
說明:
when ImageSprite_Fighter.Dragged (當戰鬥機被拖曳時) , 戰鬥機移到 currentX(當前X座標) , Y值為ImageSprite_Fighter原來的Y,也就是 Y 值不變(高度不變),所以戰鬥機祇能左右平移。
---------------------------------------------------------------
---------------------------------------------------------------
說明:
當畫布被壓下,即使用者碰觸螢幕中的畫布區域,就從戰鬥機發射子彈。Ball1的Heading 設為90,即向上跑。
---------------------------------------------------------------
---------------------------------------------------------------
說明:
如果怪物發生碰撞,怪物的前進的方向變為 360 減去原指向角度。即反彈回去。
set ImageSprite.Heading to 360 - ImageSprite.Heading。
如果怪物碰到的是戰鬥機,然後 播放怪物的聲音( call Sound_Monster.Play ),戰鬥機的生命力減1,分數也減1 。若生命力小於等於0,遊戲結束。
否則 如果怪物碰到的是 Ball1(即子彈), 然後 播放碰撞的聲音( call Sound_Hit.Play ),子彈和怪物皆消失(Enabled (啟用)設為 false,Visible (可見性)設為 false) 。得分加1分。將此怪物從怪物清單 移除。如果 怪物清單的長度為0 (即裏面沒有任何怪物),表示遊戲結束。
---------------------------------------------------------------
---------------------------------------------------------------
說明:
EdgeReached,到達邊界。
如果怪物 碰到畫布邊緣,就反彈回去。edge (邊緣數值)為目前的邊緣數值。
---------------------------------------------------------------
---------------------------------------------------------------
說明:
當Ball 元件觸碰到畫布邊緣,如果 edge(邊緣數值) 為1 (表示碰到畫布的上緣),就消失掉。
---------------------------------------------------------------
---------------------------------------------------------------
說明:
更改 Ball1(子彈)的Speed(速度)。
更改 怪物的Speed(速度)。
因 Slider_Speed.ThumbPosition(指針位置) 可能有小數,所以使用 round(四捨五入) 來取整數 。
---------------------------------------------------------------
---------------------------------------------------------------
說明:
PositionChanged ,位置變化。
---------------------------------------------------------------
---------------------------------------------------------------
說明:
當 AccelerometerSensor1(加速度感測器) 發生AccelerationChanged(加速度變化),
get xAccel : 取得 X分量。
ImageSprite_Fighter.X - get xAccel 會變大,ImageSprite_Fighter.X 座標變大,戰鬥機向右滑。
當向左傾斜時,xAccel 變成正更大,所以
ImageSprite_Fighter.X - get xAccel 會變小,ImageSprite_Fighter.X 座標變小,戰鬥機向左滑。
---------------------------------------------------------------
---------------------------------------------------------------
說明:
Shaking: 搖晃。當手機 搖晃一下,速度就加1。
---------------------------------------------------------------