
通過永恒之河,天色轉(zhuǎn)暗,一輪明月冉冉升起。卡卡慢慢走進了密林深處。
月光下的一切很安靜,只有卡卡自己的腳步聲,以及遠處不時傳來的不知名動物的叫聲。四周隱藏著一種莫名的危險氣息。
卡卡的夜視能力不錯。他瞪大眼睛,小心翼翼地向前走,想盡快走出這個令人不安的地方。
“嘩啦啦……”前面忽然傳來一陣異響??艚莸叵蚝筇艘徊?,抬頭看去——不好!一大群黑色的蝙蝠象烏云一樣飛快地向自己撲過來!

AI助手適時傳來了提示——請使用飛鏢消滅來襲的吸血蝙蝠。
卡卡發(fā)現(xiàn)手里出現(xiàn)了飛鏢,他急忙甩了出去。
“嗖”!“嗖嗖!”

鋒利的飛鏢呼嘯而去,被擊中的蝙蝠紛紛慘叫著化為黑煙消失。
卡卡正想松口氣,更多的蝙蝠黑壓壓地飛了過來……
本節(jié)學習目標
- 練習使用繪圖編輯器畫造型,進一步掌握繪圖方法;
- 使用隨機指令產(chǎn)生指定范圍任意數(shù)字的方法;
- 用鼠標或其它角色作為目標,改變當前角色方向的方法;
- 使用偵測類指令,判斷角色與其它角色或舞臺的碰撞情況;
- 學會使用克隆指令快速創(chuàng)建同一個角色的副本。
編程實戰(zhàn)
本節(jié)我們要開發(fā)的是一個射擊小游戲,在這個游戲中你要用鼠標引導方向,空格鍵發(fā)射飛鏢,擊落飛來的蝙蝠。
第一步:建立游戲場景
新建 Scratch 項目后,保留小貓角色,添加一個角色庫中的Bat(蝙蝠),并將背景設(shè)置為 Scratch 背景庫中的 Wood(樹林)。你可能覺得蝙蝠有點大,沒關(guān)系,待會我們把程序?qū)懞煤笤僬{(diào)整大小,現(xiàn)在這樣有利于查看動畫效果。

小貓、蝙蝠都有了,還差什么?小貓扔出的飛鏢??!使用“繪制”角色功能,打開繪圖編輯器,自己畫一支飛鏢吧。
先用畫方形工具畫一個長方形,然后選中圖中所示的變換工具:

這個變換工具的神奇之處在于,你可以用它任意修改形狀!比如,你可以用它在長方形左側(cè)這條邊中間位置點一下,這個位置就多出了一個節(jié)點,然后用鼠標拖動這個節(jié)點向左,這個長方形就會變成圖中的樣式:

然后選中長方形右上方的節(jié)點,點擊功能菜單區(qū)的“刪除”,刪除這個節(jié)點:

節(jié)點消失后,用變換工具拖動最右側(cè)的節(jié)點移動到垂直居中的位置,形狀調(diào)整成這樣:

再畫一個長方形的手柄,選中這個長方形后點擊功能菜單區(qū)的“放最后面”:

最后再畫一個紅色輪廓,無填充色的圓形到尾部。這個簡易飛鏢就完成了。盡管你可能覺得這個飛鏢角色不是那么完美,但相信通過這幾個簡單的步驟,你能理解繪圖中圖形變換的方法。

在飛鏢角色的屬性區(qū)把大小改成15或20,然后放到小貓前面?,F(xiàn)在你的舞臺區(qū)應(yīng)該是這樣:

第二步:為蝙蝠編寫代碼
運用前幾節(jié)課掌握的知識,我們用重復執(zhí)行指令,加上切換造型,讓蝙蝠“動”起來。

運行起來,這只蝙蝠就會開始不斷地扇動翅膀。與此同時,我們還希望蝙蝠從右上角出現(xiàn),然后向小貓逼近——這里面有一個問題,我們不希望它每次出現(xiàn)的位置都是固定的,而是在舞臺右上角的一個區(qū)域范圍內(nèi)出現(xiàn)。從上一節(jié)的內(nèi)容我們得知,可以用X、Y坐標確定角色位置,現(xiàn)在的問題是怎么讓每次程序運行的時候,獲得一個不一樣的坐標呢?這要用到隨機運算指令。你可以在“運算”類指令中找到它:

這條指令每次運行時,就能生成一個在指定范圍內(nèi)的數(shù)字,稱為“隨機數(shù)”,就像我們在買彩票的時候“機選”一樣,由計算機選擇的一個數(shù)。只要把X、Y坐標設(shè)置為隨機數(shù),就能控制蝙蝠出現(xiàn)的位置了。
掌握了隨機指令,我們就可以編寫另一段代碼了,注意這段代碼也使用綠旗啟動。這里有一個重要的概念,即同一個事件會觸發(fā)多段代碼執(zhí)行,它們是“同時”執(zhí)行的,這在計算機編程中被稱為“并行”。也就是說,蝙蝠在扇動翅膀的同時會執(zhí)行這段代碼,飛向小貓:

新增的代碼中我們用到了隨機指令確定蝙蝠的坐標位置,然后用“面向”指令(這也是一條運動類指令,它可以讓角色移動的方向朝向某一個角色或者鼠標指針)調(diào)整它的飛行方向,并調(diào)整旋轉(zhuǎn)方式為左右旋轉(zhuǎn),接著我們使用了一條“重復執(zhí)行直到”指令,這和以前我們使用的重復指令不同,它帶有一個“結(jié)束條件”,當這個條件滿足的時候就不再執(zhí)行自己包含的代碼,而是繼續(xù)向下執(zhí)行后續(xù)指令。
那么這個“結(jié)束條件”是什么呢?這是一條“偵測”類條件判斷指令(湖藍色),執(zhí)行指令的時候如果當前角色碰到了指定的對象(可以是其它角色、舞臺邊緣或鼠標指針),條件就成立(判斷結(jié)果為“真”),重復執(zhí)行結(jié)束。對這段代碼來說,就是蝙蝠不再移動,而是說“哈哈,你失敗了”,中止全部腳本(中止全部腳本意味著所有角色的代碼都會停止執(zhí)行)。
第三步:創(chuàng)建一群蝙蝠
現(xiàn)在你執(zhí)行程序,會看到蝙蝠直接飛向小貓。但故事中說的是一大群蝙蝠,怎么讓創(chuàng)造出“一群”蝙蝠呢?你可以用鼠標右鍵點擊蝙蝠,復制角色,復制出來的蝙蝠和原來的蝙蝠一樣都具有同樣的代碼,你執(zhí)行程序的時候,這兩只蝙蝠都會飛向小貓:

那么是不是用這種方法就可以了呢?理論上是可行的,但是首先這種方法很麻煩,有多少只蝙蝠你就要復制多少次,還不能控制這些蝙蝠出現(xiàn)的時間,不過更致命的問題是——如果復制完發(fā)現(xiàn)程序有點問題,要調(diào)整蝙蝠的代碼怎么辦——你就需要把所有蝙蝠的代碼全部給改一遍!是不是很痛苦!
還好,單調(diào)重復的事情應(yīng)該由電腦而不是程序員去做。所以 Scratch 為我們提供了強大的“克隆”功能來應(yīng)對這種場景??寺∵@個詞現(xiàn)在已經(jīng)不新鮮了,就是以一個對象為“本體”復制出一個完全一模一樣的“克隆體”來,它們具有一樣的外觀和執(zhí)行邏輯——你一定對《西游記》中孫大圣拔下毫毛變成許多個一模一樣的大圣這個情節(jié)記憶猶新吧?克隆就讓Scratch中的角色具備了這種復制自己的能力,復制出來的角色和本體一模一樣,而且受統(tǒng)一的指令控制!很強大吧?
Scratch 提供了三條克隆相關(guān)的指令來幫助我們進行克隆操作:

“當作為克隆體啟動時” 是一個觸發(fā)指令,和綠旗一樣,意味著你每克隆出一個角色,就會觸發(fā)后面的代碼執(zhí)行。它一般由下面“克隆”指令觸發(fā)?!皠h除此克隆體”則是讓克隆出來的角色把自己刪除,比如克隆出來的蝙蝠如果被擊中了,它就要被刪除。讓我們用這三條指令修改一下蝙蝠的代碼。
首先,我們把蝙蝠的大小設(shè)置為30,拖動到右下角隱藏起來。然后添加下面的代碼,讓蝙蝠每一秒克隆一個自己。

接著,把原來的兩段綠旗觸發(fā)的指令改為由克隆體執(zhí)行的,因為本體被我們隱藏了,復制出來的本體也是不可見的,我們還需要添加一個“外觀”類的“顯示”指令把這個克隆體顯示出來,現(xiàn)在蝙蝠的代碼變成了這樣:

現(xiàn)在點擊綠旗,是不是從舞臺右上角不斷地冒出蝙蝠飛向小貓?現(xiàn)在你已經(jīng)知道,那些其實是“克隆體”——也就是大圣身上的毫毛,真正的本體還在舞臺右下角隱藏著睡大覺呢!
第四步:為飛鏢編寫代碼
你可能已經(jīng)迫不及待想趕緊寫程序讓小貓具備攻擊能力了。不過我們不需要為小貓編寫代碼,而是直接為飛鏢寫代碼。我們需要先把飛鏢隱藏起來,然后拖動下列指令:

其實飛鏢代碼與蝙蝠的代碼很相似,它們都會先克隆自己(這里有一個新的觸發(fā)方式,按鍵觸發(fā)。當按下鍵盤上指定鍵的時候后面的代碼會執(zhí)行),當作為克隆體啟動時顯示出來,移動到小貓身前位置,面向鼠標指標(你需要用鼠標移動來為飛鏢引導方向)飛出去,直到——這里你注意到有什么不一樣了嗎?這個條件是由“碰到舞臺邊緣”和“碰到Bat”兩個條件組成的,它們之間是“或”的關(guān)系,只要有一個條件成立,循環(huán)就會終止,去刪除自己——所以我們使用了“運算”類指令(綠色)的“或”運算把這兩個條件組合到了一起,你可以體會一下這個指令的用法。
第五步:完善蝙蝠代碼
啟動程序,按空格鍵并用鼠標移動來引導飛鏢方向,你會看到一支又一支飛鏢飛向了蝙蝠,碰到蝙蝠或者舞臺邊緣就消失了——且慢,這些蝙蝠怎么沒事呢?明明被擊中了啊——這是因為我們還沒有編寫代碼讓蝙蝠處理被擊中的事件呢。切換到蝙蝠角色,在蝙蝠重復執(zhí)行內(nèi)部的移動2步指令后加一個“如果...那么”指令,我們加了一個偵測條件,如果碰到飛鏢,這個克隆體就被刪除。
蝙蝠完整的指令如下圖:

至此,你的第一個小游戲開發(fā)完成,你可以扮演卡卡,來一場痛快的“小貓大戰(zhàn)吸血蝙蝠”了!
指令小貼示
- 在【數(shù)值】和【數(shù)值】之間取隨機數(shù):獲得一個在兩個數(shù)值范圍之內(nèi)的任意數(shù)值,這個指令往往用在需要感覺更“自然”的場合,比如游戲中敵人出現(xiàn)的位置,最好不是固定的,就用這個指令來生成坐標值;
- 面向【角色或鼠標】:利用這個指令可以立即調(diào)整角色面對的方向;
- 重復執(zhí)行直到:它包括的代碼會執(zhí)行直到指定的條件成立,這實際上是重復執(zhí)行指令和如果...那么指令的綜合;
- 碰到【對象名稱】:這個指令可以是偵測指令,如果碰到了指定的角色、舞臺的邊緣或者鼠標,這個指令就返回“真”,代表成立,也就可以作為如果...那么一類指令的條件。游戲中一般檢測是否碰到子彈、敵人或超出舞臺范圍等;
- 當按下【按鍵】:用于用戶和程序交互,按下鍵盤上指定的按鍵時,后面的代碼會啟動執(zhí)行;
- 當作為克隆體啟動時:這是和綠旗啟動一類的指令,每一個克隆體產(chǎn)生后,會執(zhí)行這個指令開頭的代碼;
- 克隆【對象】:在舞臺上生成一個和指定的角色一模一樣的對象,而且會執(zhí)行“當作為克隆體啟動時”指令的代碼。在游戲中,屏幕上出現(xiàn)的敵人往往都是克隆體,便于創(chuàng)建和刪除;
- 刪除此克隆體:如果克隆體不再有效(比如被殺死的敵人),那就使用這條指令刪除它。在Scratch中,同時存在的克隆體有300多個,一旦超過就不再執(zhí)行克隆指令,所以用完的克隆體要及時刪除而不是隱藏它。
課后思考
本節(jié)牽涉的內(nèi)容牽涉隨機指令、克隆指令、偵測指令、組合條件判斷等,請你結(jié)合實際場景體會一下這些指令的用法。在編寫游戲類程序的過程中,這些指令的運用是必不可少的。
本節(jié)我們還學習了新的觸發(fā)程序執(zhí)行的方式,比如當按下按鍵時、當作為克隆體啟動時,這類指令只能作為一段代碼的開始,當特定的條件滿足時啟動代碼。這類“特定”條件,我們稱之為“事件”。實際上,在編寫角色代碼的時候,也就是為角色編寫 “事件”處理程序的過程。
你平時玩的射擊類小游戲,原理和本節(jié)程序是類似的,只要學會了本節(jié)內(nèi)容,開發(fā)同類小游戲就容易多了。