網頁

2022年7月3日 星期日

手機 App 程式設計- AppInventor2 -打磚塊,Canvas+Ball+ImageSprite+Clock+Sound+AccelerometerSensor

主題

設計一個「打磚塊」(Breakout clones)遊戲。

學習目標

學習如何使用 Canvas、Ball、ImageSprite、Clock、Sound、AccelerometerSensor 這些元件。

功能

  • 上面有6個磚塊(bricks), 下面有一個滑板(paddle),滑板上面先放一個球(ball)。
  • 開始玩,球往上跑(向上的角度為亂數) 。碰到磚塊,就得分,被碰到的磚塊跟著消失,如果6個磚塊都消失,結束遊戲。當球碰到Canvas(畫布)邊緣,如果不是畫布的下面就反彈,否則就結束遊戲。
  • 傾斜(tilt)手機可移動滑板,搖晃(shake)手機可加速球的速度。

執行畫面

開始畫面:
球碰到畫布邊緣,反彈。


球碰到畫布下面邊緣,結束遊戲:
如果6個磚塊都消失,結束遊戲:

素材

本 app的 icon (圖示),可自己繪製或網路搜尋。以下是阿旺師繪製的圖片:


(breakout_clone.gif)

paddle(滑板)
(paddle.gif)

brick(磚塊)

(brick.gif)

進入 Appinventor 

Google 輸入 appinventor,選 「MIT App Inventor」。


選 「Create Apps」。


網址為 :http://ai2.appinventor.mit.edu/

開新專案,Projects/Start new project,輸入專案的名稱,如 breakout_clone,按 「OK」鈕 。(專案的名稱只能使用大小寫字母、數字及「 _」符號,名稱的第一個字元必須是英文字母,不能使用中文字。)

Designer  (畫面編排)

Screen1:



Screen1 元件相關屬性表

元件

類別

屬性

功能

Screen1

 

AppName: breakout_clone,可以改成「打磚塊」(出現在手機上面的App名稱)
Icon :breakout_clone.gif
ScreenOrientation(螢幕方向):Portrait(鎖定直式畫面)
Title:打磚塊



1Screen元件就是1個螢幕 (畫面)。設定為Portrait,避免使用者晃動手機造成螢幕方向轉換。

Canvas1

Drawing and Animation(繪圖動畫)

BackgroundColor(背景顏色):Black
Height:300
Width:Fill Parent(
填滿)

畫布

Ball1

Drawing and Animation

PaintColor(畫筆顏色):White (白色)
Radius(
半徑):10

球形精靈

ImageSprite_brick1

Drawing and Animation

Picture:brick.gif

圖像精靈

……

 

 

圖像精靈

ImageSprite_brick6

Drawing and Animation

6ImageSprite_brick

圖像精靈

ImageSprite_paddle

Drawing and Animation

Image:paddle.gif

圖像精靈

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_Speed

Layout(介面配置)

AlignVertical:Center:2(垂直對齊,居中:2 )

Width:Fill Parent (填滿)

水平配置元件,讓裏面的元件可以水平對齊。

Label_Speed

User Interface

Text:速度:

 

標籤

Slider_Speed

User Interface

Width: 100 pixels
MaxValue:20
MinValue:1
ThumbPosition(指針位置):3


滑桿

Sound1

Media(多媒體)

 

音效

Clock1

Sensors(感測器)

TimerEnabled:不勾選TimerInterval(計時間隔):1000 (毫秒)


計時器

AccelerometerSensor1

Sensors(感測器)

Enabled(啟用):不勾選

加速度感測器



輸入文字

 遊戲結束,分數為:  ,時間:  分數為:

Blocks(程式設計)拼塊

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

Screen1:


----------------------------------------------------------------
說明:
全域性變數 Columns,表示一列有幾欄,即幾個磚塊,本例是3個。
全域性變數 Brick_List,磚塊清單。先設為空的清單。
全域性變數 ListX,每一個磚塊的 X 座標所形成的清單。
全域性變數 ListY,每一個磚塊的 Y 座標所形成的清單。
全域性變數 Score,得到的分數。
全域性變數 Score_Increment,碰到一次,得幾分。
全域性變數 Spend_Time,遊戲所花的時間。
---------------------------------------------------------------












----------------------------------------------------------------
說明:
將 ImageSprite_brick1 ....  ImageSprite_brick6 這6個元件,放入 Brick_List 此清單內。  
----------------------------------------------------------------

---------------------------------------------------------------
說明:
6個磚塊放在畫布上面的中間位置,每一列放3個磚塊,共2列。阿旺師想出一維陣列轉為2維陣列的演算法來算出每個磚塊的位置。

1、2、3...6 這6個數字,如何轉換為2維陣列?
i 是 數字除以 Columns (即3,一列放3個元素) 的 商 (quotient)(商為整數)。
j 是 數字除以 Columns (即3,一列放3個元素) 的 餘數 (modulo)。
1、2、3...6 這6個數字,轉換為2維陣列的註標值如下表:

如數字6,6 除以3 的商為2,餘數為 0 ,結果是 (2,0)

當 數字為3的倍數(即 數字除以3 的餘數為 0)時註標值要修改。
j 改成 3,i 改為 原來的值減掉1。
以6來說,本來是 (2,0),修改後的結果 為 (1,3),下圖為修改後的結果。



參考上圖,磚塊1的註標值 (0,1),磚塊6的註標值 (1,3)。
以磚塊1為原點,先求出 磚塊1(即原點)的X 座標 (OriginX)和Y座標(即OriginY)
如何算出磚塊6的X、Y的值(假設每一個磚塊的水平間隔和垂直間隔都為10 pixels)? 
磚塊6的X = 磚塊1的X (即原點的X)+ (3-1) *(磚塊1的寬度 +10)
磚塊6的Y = 磚塊1的Y(即原點的Y) + (1-0) *(磚塊1的高度 +10)

把算出來的 X 插入到 ListX清單內。
把算出來的 Y 插入到 ListY清單內。
---------------------------------------------------------------


---------------------------------------------------------------
說明:
Brick_List 是由 ImageSprite_brick1 ... ImageSprite_brick6 組成的清單。
設定 Brick_List的每一個元素(ImageSprite 圖像精靈 )的 Enabled (啟用)設為 true(即啟用), Visible(可見性)設為 true (即顯示出來 ), X 的值為對應的 ListX 值,Y 的值為對應的 ListY 值。
例如 ListX 的第1個元素的值是放 磚塊1的X 。ListY 的第1個元素的值是放 磚塊1的Y。 
如何找到  set ImageSprite.Enabled ?
---------------------------------------------------------------








---------------------------------------------------------------
說明:
顯示結果:分數和所花的時間(轉換為幾分幾秒 )。
---------------------------------------------------------------

---------------------------------------------------------------
說明:
重新排列 brick、paddle、ball的位置。brick、paddle都儘量放在中間。ball是放在 paddle中間的上面,距離paddle  為 1pixel,免得觸發 碰撞事件程序。
---------------------------------------------------------------

---------------------------------------------------------------
說明:
當遊戲結束,要執行的動作。把一些元件的Enabled設為false, 即沒有啟用。
---------------------------------------------------------------

---------------------------------------------------------------
說明:
Screen1_initialize (初始化):當Screen1 出現(螢幕初始畫面),要執行的動作。
---------------------------------------------------------------

---------------------------------------------------------------
說明:
當使用者按了「開始」按鈕時,要執行的動作。Click:被點選。


設定 Ball1.Heading(指向)前進的方向 為 45 到135之間的亂數整數。
角度說明如下:
0度就是向右,90度是向上。




 設定 Ball1.Speed(速度) 為 滑桿(Slider)的指針位置(ThumbPosition)。
 設定 Ball1.Interval(間隔) 為 10。
 如果 Speed 為 2 ,Interval 為10,表示每10毫秒移動 2 pixels。
---------------------------------------------------------------

---------------------------------------------------------------
說明:
因為 Clock1的TimerInterval(計時間隔)設為1000 (毫秒),即1秒鐘執行 Clock1.Timer (計時)事件程序1次。 把Spend_Time加1。
---------------------------------------------------------------

---------------------------------------------------------------
說明:
when ImageSprite_paddle.Dragged (當滑板被拖曳時) , 滑板移到 currentX(當前X座標) , Y值為ImageSprite_paddle原來的Y,也就是 Y 值不變(高度不變),所以滑板祇能左右平移。
---------------------------------------------------------------

---------------------------------------------------------------
說明:
當Ball 元件與其它元件碰撞(collide)時,播放碰撞的聲音( call Sound1.Play )。

set Ball1.Heading to 360 - Ball1.Heading
Ball元件前進的方向變為 360 減去原指向角度。
例如 : 本來是 135,360-135=225。本來是315,360-315=45。圖例如下:


不管是碰到磚塊或滑板,分數都加1 分。
如果碰撞到磚塊元件,設定此磚塊元件無法啟用,消失掉。
Enabled (啟用)設為 false,Visible (可見性)設為 false,即不可見(消失掉) 。
將此磚塊元件從磚塊清單 移除。
如果 磚塊清單的長度為0 (即裏面沒有任何磚塊),表示遊戲結束。
---------------------------------------------------------------

---------------------------------------------------------------
說明:
EdgeReached,到達邊界。
當Ball 元件觸碰到畫布邊緣,如果 edge(邊緣數值) 為-1 (表示碰到畫布的下緣),就呼叫 Game_Over 程序,執行遊戲結束的工作。
否則 呼叫 Ball元件的反彈方法,edge (邊緣數值)為目前的邊緣數值。 
Canvas元件被碰撞的邊界會以 edge 回傳,依順時針方向,上方為1,右上角為2,右邊為3,右下角為4,下方為-1,左下角為-2,左邊為 -3,左上角為 -4。

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 
---------------------------------------------------------------

---------------------------------------------------------------
說明:
更改 Ball1的Speed(速度)。
因 Slider_Speed.ThumbPosition(指針位置) 可能有小數,所以使用 round(四捨五入) 來取整數 。
round 函數跟一般數學的四捨五入不一樣,其定義如下:
小數點後面若是 >5 , 則進1位到整數。小數點後面若是 < 5, 則捨去。
小數點後面祇有1位,若是  = 5 , 就看個位數字,如果是奇數,就進一位到整數,如果是偶數,則不進位。如 round(3.5)=4,round(4.5)=4。
一般數學的四捨五入是 >= 0.5 就進位, <0.5 捨去。
---------------------------------------------------------------
---------------------------------------------------------------
說明:
PositionChanged ,位置變化。
---------------------------------------------------------------
---------------------------------------------------------------
說明:
當 AccelerometerSensor1(加速度感測器) 發生AccelerationChanged(加速度變化),

AccelerometerSensor 元件可回傳 Android 裝置上的加速度感測器狀態,並可偵測裝置三個軸的晃動狀況,偵測單位為m/s^2。如果裝置面朝上水平靜置時, Z 軸加速度值約為9.8(受地心引力影響)。 

手機是直放在水平面上。
• X軸:正面向上時,向右傾斜,值愈小(變負值),向左傾斜,值愈大(變正值)。負面向上時,跟正面相反。

• Y軸:正面或反面向上放,手機愈往上方立起來,值愈大,往下方放,值愈小。
• Z軸:正面朝上為正,朝下為負。當從正面慢慢轉到下面,Z軸 的值由正變負,9.8 慢慢變成 -9.8。

get  xAccel : 取得 X分量。
當向右傾斜時,xAccel 變成負更大,所以
ImageSprite_paddle.X - get xAccel  會變大,ImageSprite_paddle.X 座標變大,滑板向右滑。
當向左傾斜時,xAccel 變成正更大,所以
ImageSprite_paddle.X - get xAccel  會變小,ImageSprite_paddle.X 座標變小,滑板向左滑。
---------------------------------------------------------------

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