網頁

2022年7月12日 星期二

手機 App 程式設計- AppInventor2 -射擊遊戲,Canvas+Ball+ImageSprite+Slider+Spinner+Clock+Sound+AccelerometerSensor 的應用

主題

設計一個「射擊」(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 , 就比較沒有限制。

可在 https://svgsilh.com/  尋找  戰鬥機 的圖形 ,關鍵字 :fighter 或 jet plane。
可在 https://pixabay.com/  尋找  怪物 的圖形 ,關鍵字 :ghost  或 monster,類型是 :vector graphics。

免費線上去背(移除影像背景), Adobe Express。
如果不會去背,可參考 阿旺師的文章 : Google 繪圖- 封面設計,內有去背的方法。

免費音效
線上聲音剪輯(將聲音剪短)

進入 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:射擊遊戲

1Screen元件就是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

8ImageSprite_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(程式設計)拼塊

跟元件有關的拼塊,要先點選該元件後,再選擇是那一個拼塊;不是元件的拼塊,可以根據拼塊的顏色,判斷是屬於那一個類別。

程式拼塊若沒有說明清楚,請參考 阿旺師的 「手機 App 程式設計- AppInventor2 -打磚塊」的程式說明。

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分量。
當向右傾斜時,xAccel 變成負更大,所以
ImageSprite_Fighter.X - get xAccel  會變大,ImageSprite_Fighter.X 座標變大,戰鬥機向右滑。
當向左傾斜時,xAccel 變成正更大,所以
ImageSprite_Fighter.X - get xAccel  會變小,ImageSprite_Fighter.X 座標變小,戰鬥機向左滑。
---------------------------------------------------------------

---------------------------------------------------------------
說明:
Shaking: 搖晃。當手機 搖晃一下,速度就加1。
---------------------------------------------------------------