第 5 章 瓢蟲快跑

2018-02-24 15:51 更新

游戲是移動應用中最令人興奮的部分,無論是玩游戲,還是做游戲。最近紅極一時“憤怒的小鳥”,根據(jù)開發(fā)者Rovio公司稱,第一年下載量達50萬次,同時每天運行的人時數(shù)超過一百萬小時。(甚至有人說要把它拍成故事片!)我們可無法保證電影的成功,但可以讓您用App Inventor創(chuàng)建自己的游戲“瓢蟲快跑”,里面的瓢蟲要吃蚜蟲,同時要避免被青蛙吃掉。

{%}

應用描述

如圖5-1所示的“瓢蟲快跑”應用,用戶可以:

  • 通過傾斜設備來控制瓢蟲移動;

  • 查看屏幕上的能量指示條,能量會隨時間減少,并引起瓢蟲的饑餓;

  • 讓瓢蟲追逐并吃掉蚜蟲來獲得能量,抵御饑餓;

  • 幫助瓢蟲躲避青蛙,因為青蛙吃瓢蟲。

{%}

圖 5-1 瓢蟲快跑游戲手機截屏

學習要點

在開始探索本章之前,我們假設你已經(jīng)完成了第3章MoleMash的學習,并熟悉了過程創(chuàng)建、隨機數(shù)生成、Ifelse塊以及ImageSprite、Canvas、Sound和Clock組件。

本章在復習MoleMash以及前幾章內容的基礎上,主要介紹以下內容:

  • 使用多個ImageSprite組件,并檢測它們之間的碰撞;

  • 使用OrientationSensor(方向傳感器)組件檢測設備的傾斜,并用它來控制ImageSprite;

  • 改變ImageSprite的顯示圖片;

  • 在Canvas組件上畫線;

  • 用Clock組件控制多個事件;

  • 用變量來記錄數(shù)值(瓢蟲的能量水平);

  • 創(chuàng)建和使用帶參數(shù)的過程;

  • 使用and塊。

設計組件

在應用中,使用一個Canvas組件作為三個ImageSprite組件的活動場地,三個ImageSprite組件分別代表瓢蟲、蚜蟲和青蛙,此外,還要為青蛙配一個聲音組件。OrientationSensor(方向傳感器)通過測量設備的傾斜來移動瓢蟲,Clock組件用來改變蚜蟲的運動方向。另有一個顯示瓢蟲能量水平的Canvas組件;一個重新啟動按鈕,當瓢蟲餓死或被吃掉時,用來重新啟動游戲。表5-1提供了本應用中使用的全部組件列表。

表5-1 瓢蟲快跑游戲中的所有組件

組件類型 面板中分組 命名 作用
Canvas Drawing and Amination FieldCanvas 運動場地
ImageSprite Drawing and Amination Ladybug 用戶控制的角色
OrientationSensor Sensor OrientationSensor1 測試手機的傾斜,控制瓢蟲移動
Clock User Interface Clock1 決定何時改變Imagesprite的方向
ImageSprite Drawing and Amination Aphid 蚜蟲:瓢蟲的捕食對象
ImageSprite Drawing and Amination Frog 青蛙:瓢蟲的捕食者
Canvas Drawing and Amination EnergyCanvas 顯示瓢蟲的能量水平
Button User Interface RestartButton 重啟游戲
Sound Media Sound1 青蛙吃瓢蟲時發(fā)出的聲音

準備開始

下載瓢蟲、蚜蟲、死瓢蟲及青蛙的圖像,此外還有青蛙的聲音文件。

登陸App Inventor網(wǎng)站,建一個名為“LadybugChase”新項目,屏幕標題設置為“瓢蟲快跑”。打開塊編輯器并連接到測試設備,將下載的圖片及聲音文件上載(Upload file)到媒體面板。

如果使用設備而不是模擬器,你需要禁用“屏幕自動旋轉”功能,否則當設備旋轉時,會改變設備的顯示方向。在大多數(shù)設備上,可以點擊設置->顯示,然后取消選中的“屏幕自動旋轉”復選框即可。

活動的瓢蟲

在這個“第一人稱”的游戲中,瓢蟲代表玩家,玩家通過傾斜手機來控制瓢蟲的運動。與MoleMash不同,這里玩家被帶入游戲,而不是在設備以外用手觸碰。

添加組件

在前幾章,我們一次性地創(chuàng)建了所有的組件,但這不是開發(fā)人員的習慣做法。相反,通常每次只創(chuàng)建一部分組件,編寫相應的程序,并進行測試,然后在進入到下一部分。在本節(jié)中,我們先來創(chuàng)建瓢蟲并控制它的運動。

  • 在組件設計器中創(chuàng)建一個Canvas,命名為FieldCanvas,并設置其寬度為“Fill parent”,高度為300像素;

  • 在FieldCanvas上放置一個ImageSprite,重命為Ladybug,并設置其Picture屬性為活的瓢蟲圖片。不必在意它的x、y屬性,這取決于ImageSprite被放在畫布上的位置。

也許你已經(jīng)注意到,ImageSprites還有Interval、Heading以及speed屬性,而這些都是在本程序中要用到的:

  • Interval屬性:在本游戲中可以設置為10(毫秒),來設定ImageSprite自身的移動頻率(而不是像MoleMash中那樣,運動被MoveTo過程所控制);

  • Heading屬性:指示ImageSprite將要移動的方向。例如:0表示向右,90表示向上,180表示向左,等等?,F(xiàn)在就讓它取默認值——向右,我們將在塊編輯器中改變它;

  • Speed屬性:指定ImageSprite在每個時間間隔內移動的距離(單位為像素)。我們將在塊編輯器中設置Speed屬性。

瓢蟲的運動由OrientationSensor通過檢測設備的傾斜程度來進行控制;Clock組件用來每隔10毫秒(每秒100次)檢測一次設備的方向,并相應地改變瓢蟲的Heading(方向)屬性 。我們將在塊編輯器中做如下設置:

1. 添加OrientationSensor組件,它將出現(xiàn)在“不可見組件”區(qū)域;

2. 添加Clock組件,它也將出現(xiàn)在“不可見組件”區(qū)域,并設置其TimerInterval屬性為10毫秒。對照圖5-2檢查添加的組件。

{%}

圖 5-2 在組件設計器中為動畫瓢蟲設置用戶界面

添加行為

切換到塊編輯器,創(chuàng)建名為UpdateLadybug的過程(procedure)及Clock1.Timer塊,如圖5-3所示。嘗試不使用抽屜,直接輸入塊的名字(如“when Clock1.Timer”)來生成塊。(請注意,對數(shù)字100的乘法操作使用的是星號(*),但圖中看不到。)雖然可以單擊右鍵選擇添加注釋,但這不是必須的。

{%}

圖 5-3 每隔10毫秒改變一次瓢蟲的方向及速度

在UpdateLadybug過程里用到了兩個OrientationSensor最有用的屬性:

  • Angle(角度):表示設備傾斜的方向;

  • Magnitude(幅度):表示設備的傾斜程度,范圍從0 (不傾斜)至1(最大傾斜)。

Magnitude乘以100是告訴瓢蟲,在每個時間間隔(TimerInterval)內,在某個特定的方向,移動的距離在0到100像素之間。時間間隔為之前在組件設計器中設定的10毫秒。

雖然在連接設備上可以測試瓢蟲的移動,但與打包下載到設備上的運行效果相比,瓢蟲的速度要么太慢,要么太快。對于安裝運行的應用,如果太慢,可以增加速度;相反,則減小速度。

顯示能量水平

在第二個Canvas組件上用一個紅色線條來顯示瓢蟲的能量水平。線條高度為1個像素,寬度為瓢蟲的能量值,取值范圍從200(健康)到0(死)。

添加組件

在組件設計器中,在FieldCanvas下方創(chuàng)建一個新的Canvas組件,命名為EnergyCanvas;設置Width屬性為“Fill parent”,Height屬性為1個像素。

創(chuàng)建變量:Energy

在塊編輯器中,創(chuàng)建一個初始值為200的變量來記錄瓢蟲的能量水平。(還記得吧,在第2章PaintPot中,第一次使用變量dotSize)以下是具體步驟:

1. 在塊編輯器中,拖出一個initialize global name to塊,將name改為energy;

2. 如果energy塊的右側插槽內有其他塊,刪掉它:選中并按Delete鍵或直接拖到垃圾桶;

3. 創(chuàng)建一個數(shù)組塊200(直接輸入數(shù)字200或拖動Math抽屜中的0塊),然后插入initialize global energy to塊,如圖5-4所示。

{%}

圖 5-4 將變量energy初始化為200

圖5-5中顯示了當鼠標懸浮在初始化變量塊的“energy”文本上時,呼出了全局變量energy的“get”及“set”塊;

{%}

圖 5-5 從初始化變量塊中獲得set及get塊

畫出能量條

我們要在變量energy與紅色線條之間建立通信,使線條長度(像素)與能量值相等。為此創(chuàng)建如下兩個類似的組塊:

1. 在EnergyCanvas上從(0, 0)點到(energy, 0)點畫一條紅線,以顯示當前的能量水平;

2. 在EnergyCanvas上從(0, 0)點到(EnergyCanvas.Width, 0)點畫一條白線,在畫新能量水平線之前,清除當前的能量水平線。(記得前面設置EnergyCanvas.Width為“Fill parent”。)

然而,最好能創(chuàng)建一個過程,能用任何顏色在EnergyCanvas上畫任意長度的線。為此,需要定義兩個參數(shù):length(長度)和color(顏色),當程序被調用時,我們只需要指定參數(shù)值,就像在MoleMash一章中調用random integer內置過程一樣。下面是創(chuàng)建DrawEnergyLine過程的步驟,如圖5-6所示。

1. 進入Procedures抽屜,拖出一個to procedure塊;

2. 點擊過程名(可能是“procedure” ),改為“DrawEnergyLine”;

3. 點擊過程塊左上角的藍色方塊,呼出兩個塊:input及input x;

4. 將input x塊插入到input塊內,將x修改為color;

5. 重復步驟4:插入第二塊input x并命名為“l(fā)ength”;

6. 按照圖5-6所示,為該過程添加的其余的塊:將鼠標懸停在to DrawEnergyLine塊的參數(shù)color及l(fā)ength文本上,獲得get color及get length塊;或者從Variables抽屜中直接拖出get塊,插入到to DrawEnergyLine內部的塊中,點擊下拉菜單選擇color或length。

{%}

圖 5-5a 為DrawEnergyLine過程添加輸入(參數(shù))

{%}

圖 5-6 定義過程DrawEnergyLine

現(xiàn)在,你已經(jīng)掌握了創(chuàng)建過程的竅門,讓我們再寫一個DisplayEnergy的過程,兩次調用DrawEnergyLine過程:第一次用來擦除舊線(覆蓋整個EnergyCanvas的白線),第二次用來顯示新的能量線,如圖5-7所示。

{%}

圖 5-7 定義過程DisplayEnergy

DisplayEnergy過程由以下四行命令組成:

1. 設定畫筆顏色為白色;

2. 畫一條貫穿EnergyCanvas的橫線(1個像素高);

3. 設定畫筆顏色為紅色;

4. 畫一條長度等于energy值的線。

 提示:將若干行代碼規(guī)整到一個過程中,通過調用這個過程來取代逐行地執(zhí)行這些代碼,這個過程被稱作重構,這種強大的技術使得程序更易于維護,也更可靠。在這種情況下,如果我們想改變能量線的高度或位置,我們只需對DrawEnergyLine過程做一次修改,而不必分兩次來完成這一修改。

饑餓而死

不同于前幾章的應用,本游戲設定了結束環(huán)節(jié):如果瓢蟲吃不到足夠的蚜蟲,或者被青蛙吃掉,則游戲結束。此時我們希望瓢蟲不再移動(設置Ladybug.Enabled為false),并將活瓢蟲圖片換成死瓢蟲(將Ladybug.Picture設置為已上傳的圖片文件名)。GameOver過程的創(chuàng)建如圖5-8所示。

{%}

圖 5-8 定義GameOver過程

再按圖5-9所示向UpdateLadybug(由Clock.Timer每10毫秒調用一次)添加紅框內的代碼:

  • 減少瓢蟲的能量(energy = energy - 1);

  • 顯示新的能量水平(call DisplayEnergy);

  • 如果energy值為0則游戲結束。

 測試:你可以在設備上測試這段代碼,并驗證能量水平隨時間的減少,并最終導致瓢蟲死亡。重啟應用可以點擊“Reset Connection->AI Companion”。

{%}

圖 5-9 UpdateLadybug過程的第二個版本

添加蚜蟲

下面來添加蚜蟲,即讓蚜蟲在FieldCanvas上浮動。如果瓢蟲撞上蚜蟲(視同“吃”掉它),則瓢蟲的能量水平升高,而蚜蟲消失,且稍后會再次出現(xiàn)。(在用戶看來,這完全是另一只蚜蟲,但實際上是同一個ImageSprite組件。)

添加一個ImageSprite

添加蚜蟲首先要回到組件設計器,創(chuàng)建另一個ImageSprite,要確保它不落在瓢蟲上,命名為Aphid,其屬性設置如下:

1. Picture屬性:設置為已上傳的蚜蟲圖像文件;

2. Interval屬性:設置為10,即:像瓢蟲一樣,每10毫秒移動一次;

3. Speed屬性:設置為2,因此蚜蟲移動不會太快,以便讓瓢蟲能抓住它。

不必在意它的x、y屬性(只要不是在瓢蟲上)或title屬性,這些可以在塊編輯器中設置。

控制蚜蟲

實驗發(fā)現(xiàn),蚜蟲每隔50毫秒(Clock1跳動5次)改變一次方向的效果最好??梢酝ㄟ^創(chuàng)建第二個Clock組件,并設定其TimerInterval屬性為50毫秒來實現(xiàn)這一效果。但是,我們希望能夠嘗試不同的技術:使用random fraction(隨機分數(shù))塊,每次調用,它都將返回一個≥0但<1的隨機數(shù)。創(chuàng)建UpdateAphid過程,并用Clock1.Timer來調用它,如圖5-10所示。

{%}

圖 5-10 添加UpdateAphid過程

塊的作用

定時器每次跳動(每秒100次)都將調用UpdateLadybug及UpdateAphid過程。UpdateAphid過程首先生成一個介于0到1之間的隨機數(shù),例如0.15,如果該數(shù)<0.20(在20%的時間里),蚜蟲將改變方向,改變的角度為0到360之間的隨機數(shù);如果該數(shù)≥0.20(在其余80%的時間里),蚜蟲方向保持不變。

瓢蟲吃掉蚜蟲

下一步,當他們碰撞時,讓瓢蟲“吃掉”蚜蟲。幸運的是,App Inventor提供了ImageSprite組件之間的碰撞檢測。問題是:當瓢蟲與蚜蟲碰撞時,會發(fā)生哪些事情?在繼續(xù)閱讀之前,請你停下來想想這個問題。

為了處理瓢蟲與蚜蟲的碰撞,創(chuàng)建EatAphid過程,其具體步驟如下:

  • 瓢蟲的能量水平上升50,來模擬享受美食;

  • 讓蚜蟲消失(設置其Visible屬性為false);

  • 讓蚜蟲停止移動(設置其Enabled屬性為false);

  • 讓蚜蟲移動到屏幕上任意位置(這與MoleMash中移動地鼠遵循了相同的編碼方式)。

請對照圖5-11檢查您的塊。如果你還能想到發(fā)生其他事情,比如音效,可以自行添加。

{%}

圖 5-11 創(chuàng)建EatAphid過程

塊的作用

每次調用EatAphid,變量energy增加50,緩解了瓢蟲的饑餓。然后,蚜蟲的Visible及Enabled屬性都被設置為false,看上去像是消失了。最后,產(chǎn)生隨機的x、y坐標,并調用Aphid.MoveTo,這樣,蚜蟲會在一個新位置再次出現(xiàn)(否則,它一出現(xiàn)便會被立即吃掉)。

瓢蟲與蚜蟲之間的碰撞檢測

圖5-12顯示了在瓢蟲與蚜蟲之間做碰撞檢測的代碼。

{%}

圖 5-12 檢測并處理瓢蟲與蚜蟲之間的碰撞

塊的作用

當瓢蟲與另一個ImageSprite碰撞時,將調用Ladybug.CollidedWith,參數(shù)“other”指向任何與瓢蟲發(fā)生相撞的ImageSprite。此時,只有蚜蟲可以碰撞,但稍后會有青蛙加入進來。我們采用防御性編程方式,即在調用EatAphid之前,要確認碰撞的對象就是蚜蟲;此外還要確認蚜蟲可見,否則,蚜蟲在被吃掉之后而重新出現(xiàn)之前,還會與瓢蟲再次碰撞。如果缺少這項確認,隱形的蚜蟲會被再次吃掉,并引起能量水平的再次增加,這會讓用戶感到費解。

{%} 測試:重新啟動游戲,并確信瓢蟲出現(xiàn)在一個新的任意位置。

添加音效

測試游戲時,你可能注意到:當蚜蟲或瓢蟲被吃掉時,缺少良好的反饋。要添加音效及觸覺反饋,請執(zhí)行以下操作:

1. 在組件設計器中添加一個Sound組件。設置其Source屬性為已上傳的聲音文件;

2. 進入塊編輯器,進行如下操作:

  • 在EatAphid過程中添加Sound1.Vibrate塊,參數(shù)為100毫秒,以便在蚜蟲被吃掉時,設備產(chǎn)生振動;

  • 在Ladybug.CollidedWith中調Sound1.Play,位置在調用GameOver之前,以便當青蛙吃掉瓢蟲時發(fā)出叫聲。

改進

下面這些想法目的是改進游戲,或者讓游戲更個性化:

  • 目前,當游戲結束時,青蛙和蚜蟲還在移動,這與其Enabled屬性有關:在GameOver中將其設置為false,并在RestartButton.Click中重新設置為true;

  • 設置并顯示一個分數(shù),來表示瓢蟲的存活時間。你可以用Label來顯示一個數(shù)值,該數(shù)值在Clock1.Timer內不斷遞增;

  • 將EnergyCanvas的Height屬性增加為2,以便使能量條更加明顯,并在DrawEnergyLine內畫兩條線,一個在另一個之上。(使用一個過程,而不是復制代碼先擦除再重繪能量線,這樣做的另一個好處是:如果你需要修改線的粗細、顏色或位置時,只需要修改一處的代碼。)

  • 添加背景圖和更多音效來渲染氣氛,比如用真聲或預警聲來提示瓢蟲能量水平的降低;

  • 讓游戲隨時間推移而變得越來越難,如增加青蛙的速度,或降低Interval屬性值;

  • 從技術上來說,被青蛙吃掉的瓢蟲應該消失。改變游戲規(guī)則:如果瓢蟲被吃,則隱形;如果是餓死,則顯示死瓢蟲圖;

  • 將瓢蟲、蚜蟲和青蛙的圖片換成更適合你個人口味的圖片,如霍比特人、半獸人以及邪惡的巫師;或者是反叛星際戰(zhàn)斗機、能源艙及帝國戰(zhàn)機。

小結

已經(jīng)有兩個游戲被你收入囊中(假設你學習了MoleMash),現(xiàn)在你該知道如何創(chuàng)建自己的游戲了,這是許多新程序員或有志者的目標!具體來說,您學習了:

  • 可以創(chuàng)建多個ImageSprite組件(瓢蟲,蚜蟲和青蛙),并在它們之間做碰撞檢測;

  • 用OrientationSensor可以檢測設備的傾斜,而測得的值可用于控制sprite(或你能想到的任何其他對象)的移動;

  • 一個Clock組件可以控制多個發(fā)生頻率相同(改變瓢蟲和青蛙的方向),或通過使用random fraction塊來控制頻率不同的事件。例如,如果你想在一個周期中,有大約1/4(25%)的時間里會發(fā)生某事件,只要將它放在if塊中,并設定條件為random fraction的結果<0.25即可;

  • 一個應用中可以使用多個Canvas組件,我們的例子中有兩個,一個用于游戲場地,另一個用于變量的圖形化顯示(而不是用Label顯示);

  • 用戶自定義過程可以使用參數(shù)(如在DrawEnergyLine 中使用的“color”及“l(fā)ength”)來控制其行為,這極大地擴展了過程抽象的能力。

另一個游戲中常用的組件是Ball,與ImageSprite唯一不同的是,它的外觀是一個被填充的圓形,而不是一張任意的圖片。

資源下載

frog.png

ladybug.png

deadladybug.png

aphid.png

frog.wav

英漢對照

orientation: 方向

field: 場地

ladybug: 瓢蟲

aphid: 蚜蟲

frog: 青蛙

energy: 能量

restart: 重新開始

chase: 追逐,奔跑

upload: 上載,上傳

file: 文件

interval: 間隔

heading: 前進方向

speed: 速度

timer: 計時器

updat: 更新

angle: 角度

magnitude: 幅度

delete: 刪除

procedure: 過程

input: 輸入

display: 顯示

enable: 使有效

reset: 重置

visible: 可見的

eat: 吃

collide: 碰撞

with: 與...

else: 否則

fraction: 分數(shù)

以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號