99re热这里只有精品视频,7777色鬼xxxx欧美色妇,国产成人精品一区二三区在线观看,内射爽无广熟女亚洲,精品人妻av一区二区三区

第 17 章 創(chuàng)建動(dòng)畫(huà)應(yīng)用

2018-02-24 15:51 更新

本章將討論創(chuàng)建另一類(lèi)應(yīng)用的方法,應(yīng)用中使用了簡(jiǎn)單的可移動(dòng)的動(dòng)畫(huà)對(duì)象。你將學(xué)習(xí)使用App Inventor創(chuàng)建二維游戲的基本知識(shí),并熟練使用圖片精靈(image sprite)及處理兩個(gè)物體碰撞一類(lèi)的事件。

當(dāng)你在電腦屏幕上看到一個(gè)平滑移動(dòng)的物體時(shí),你實(shí)際上看到的是一連串快速移動(dòng)的圖片,每次只移動(dòng)一個(gè)極小的距離,它利用了人的視覺(jué)暫留,從這一點(diǎn)上,它無(wú)異于“手翻書(shū)”—— 一種通過(guò)快速翻頁(yè)來(lái)看到動(dòng)畫(huà)效果的書(shū)(這也是那些精美絕倫的動(dòng)畫(huà)電影的制作方法)。

在A(yíng)pp Inventor中,通過(guò)在Canvas組件上放置物體,并讓這些物體隨時(shí)間在Canvas內(nèi)移動(dòng),從而產(chǎn)生出動(dòng)畫(huà)效果。本章將學(xué)習(xí)使用Canvas的坐標(biāo)系統(tǒng),學(xué)習(xí)利用Clock.Timer事件來(lái)觸發(fā)運(yùn)動(dòng),以及如何控制運(yùn)動(dòng)速度、如何響應(yīng)兩個(gè)物體的碰撞事件等等。

{%}

在應(yīng)用中添加Canvas組件

從組件面板的Drawing and Animation組中拖出Canvas組件,然后定義它的Width及Height屬性。通常我們希望Canvas與屏幕等寬,為此將寬度設(shè)為“Fill parent”,如圖17-1所示。

{%}

圖 17-1 設(shè)置Canvas組件的Width屬性

可以用同樣的方式設(shè)定Height屬性,但一般會(huì)將其設(shè)為一個(gè)數(shù)字(如300像素),以便為Canvas上面或下面的其他組件留出空間。

Canvas的坐標(biāo)系統(tǒng)

Canvas上的圖畫(huà)實(shí)際上是一個(gè)許多像素構(gòu)成的表格,像素是手機(jī)(或其他設(shè)備)屏幕上能夠顯示的最小的色塊,每個(gè)像素都在Canvas上有它的位置(或者說(shuō)單元格),位置由X-Y坐標(biāo)系定義,如圖17-2所示,X定義了水平方向上的位置(方向是從左到右),Y定義了垂直方向的位置(從上到下)。

{%}

圖 17-2 Canvas的坐標(biāo)系統(tǒng)

坐標(biāo)軸的方向定義可能與你的經(jīng)驗(yàn)不一致,不過(guò)位于Canvas左上角的單元格的x、y坐標(biāo)都為零,因此這個(gè)位置表示為(x=0,y=0)。(這與App Inventor列表中使用的索引值有所不同,索引值從1開(kāi)始,看起來(lái)更容易理解。)向右移動(dòng)時(shí),x坐標(biāo)增大;向下移動(dòng)時(shí),y值變大。位于左上角單元格右側(cè)的單元格坐標(biāo)為(x=1,y=0)。右上角單元格的x坐標(biāo)等于canvas的寬度減1,多數(shù)手機(jī)屏幕的寬度都在300左右,但這里例子中顯示的寬度是20,因此右上角的單元格坐標(biāo)為(x=19,y=0)。

要改變canvas的外觀(guān)有兩種方法:①在上面繪畫(huà),或者②在上面放置移動(dòng)的物體,本章所涉及的是后者,但我們首先要討論如何繪畫(huà),以及如何通過(guò)繪畫(huà)來(lái)創(chuàng)建動(dòng)畫(huà)(這也是本書(shū)第二章油漆桶中的主要內(nèi)容)。

Canvas中的每一個(gè)單元格都對(duì)應(yīng)顯示為一個(gè)有顏色的像素。Canvas組件提供的Canvas.DrawLine及Canvas.Circle塊可以用來(lái)在canvas上以繪制像素組成的圖畫(huà)。首先需要將Canvas.PaintColor屬性設(shè)置為你需要的顏色,然后調(diào)用某個(gè)具體的繪畫(huà)塊來(lái)畫(huà)出顏色。其中的DrawCircle塊可以繪制直徑為任意大小的圓,但如果你將半徑設(shè)為1,如圖17-3所示,那么只能畫(huà)出一個(gè)單獨(dú)的像素。

{%}

圖 17-3 用1個(gè)像素畫(huà)圓,每次只能畫(huà)1個(gè)單獨(dú)的像素

在塊編輯器Built-in組的Colors抽屜中,App Inventor提供了13種常用的顏色,可以用來(lái)繪制像素圖(或設(shè)置組件背景色)。也可以使用顏色編碼方案來(lái)獲得更為豐富的顏色,顏色編碼方案的解釋請(qǐng)參見(jiàn)相關(guān)App Inventor文檔:http://appinventor.googlelabs.com/learn/reference/blocks/colors.html。

改變canvas外觀(guān)的第二種方法是在canvas上放置Ball和ImageSprite組件。sprite是一個(gè)被放置在場(chǎng)景中的圖形對(duì)象,所謂的場(chǎng)景這里指的就是canvas。Ball和ImageSprite組件都屬于sprites類(lèi)型,只是外觀(guān)不同而已。Ball為圓形,只能通過(guò)改變顏色和半徑來(lái)改變它的外觀(guān),而ImageSprite可以是任何形狀;ImageSprite和Ball都只能添加到Canvas中,不可能將它們拖入用戶(hù)界面中Canvas以外的區(qū)域。

用計(jì)時(shí)事件制造動(dòng)畫(huà)

在A(yíng)pp Inventor中,為應(yīng)用添加動(dòng)畫(huà)的方法之一就是讓物體對(duì)計(jì)時(shí)器事件做出響應(yīng),最常用的方法就是讓sprite按照設(shè)定的時(shí)間間隔,在canvas上進(jìn)行位置的移動(dòng)。設(shè)定的時(shí)間間隔的方法是使用計(jì)時(shí)器事件最通用的方法。稍后我們還將討論另一種方法,即,利用ImageSprite及Ball組件的Speed(速度)及Heading(方向)屬性,通過(guò)編程來(lái)實(shí)現(xiàn)動(dòng)畫(huà)效果。

點(diǎn)擊按鈕以及其他用戶(hù)觸發(fā)的事件理解起來(lái)非常簡(jiǎn)單:用戶(hù)做動(dòng)作,應(yīng)用通過(guò)執(zhí)行某些操作來(lái)進(jìn)行響應(yīng);但計(jì)時(shí)器事件則不然:這類(lèi)事件不是由最終用戶(hù)發(fā)起,而是由時(shí)間的流動(dòng)來(lái)觸發(fā)。你需要將應(yīng)用中的這類(lèi)手機(jī)時(shí)鐘觸發(fā)的事件與用戶(hù)的行為區(qū)分開(kāi)來(lái)。

定義計(jì)時(shí)器事件的第一步是在組件設(shè)計(jì)器中為應(yīng)用拖入一個(gè)Clock組件。Clock組件有一個(gè)關(guān)聯(lián)的TimerInterval(計(jì)時(shí)間隔)屬性,用來(lái)以毫秒為單位定義計(jì)時(shí)器的計(jì)時(shí)間隔(1秒=1000毫秒)。如果將TimerInterval設(shè)為500,就意味著每隔半秒鐘觸發(fā)一次計(jì)時(shí)器事件。計(jì)時(shí)間隔越小,物體的移動(dòng)也就越快。

在設(shè)計(jì)器中完成Clock的添加以及TimerInterval的設(shè)定后,就可以在塊編輯器中拖出“when Clock.Timer”事件塊,并在其中加入任何你需要的塊,這些塊將每個(gè)一個(gè)計(jì)時(shí)間隔執(zhí)行一次。

產(chǎn)生運(yùn)動(dòng)

要讓sprite隨時(shí)間移動(dòng),就需要用MoveTo函數(shù)。在塊編輯器的ImageSprite及Ball組件抽屜中可以找到這個(gè)函數(shù)。例如,要使一個(gè)球在水平方向上穿越屏幕,需要使用圖17-4中的塊。

{%}

圖 17-4 讓球在水平方向穿越屏幕

MoveTo的作用是在canvas上將物體移動(dòng)到一個(gè)絕對(duì)位置,而不是相對(duì)位置。因此,為了移動(dòng)到這個(gè)絕對(duì)位置,需要將MoveTo函數(shù)的參數(shù)設(shè)定為當(dāng)前位置與增量之和。這里我們要實(shí)現(xiàn)球的水平移動(dòng),只需要將參數(shù)x設(shè)定為當(dāng)前的x值與增量20之和,而y值保持不變(Ball1.Y)。

如果想讓球沿著對(duì)角線(xiàn)的方向移動(dòng),就需要同時(shí)設(shè)定x、y坐標(biāo)的增量,如圖17-5所示。

{%}

圖 17-5 設(shè)置x、y坐標(biāo)的增量,實(shí)現(xiàn)球在對(duì)角線(xiàn)方向的移動(dòng)

控制速度

在前面的例子中,球的移動(dòng)有多快呢?速度取決于兩個(gè)因素:Clock組件的TimerInterval屬性值,以及MoveTo函數(shù)中的參數(shù)值。如果計(jì)時(shí)間隔設(shè)為1000毫秒,就意味著每秒鐘觸發(fā)一次計(jì)時(shí)事件,這樣會(huì)讓運(yùn)動(dòng)變得不流暢。為了得到更為平滑的運(yùn)動(dòng),就需要縮短計(jì)時(shí)間隔。如果將TimerInterval設(shè)為100毫秒,則球每隔1/10秒移動(dòng)20像素,或者每秒移動(dòng)200像素,對(duì)于應(yīng)用的使用者來(lái)說(shuō),這個(gè)速度看起來(lái)會(huì)平滑得多。除了改變計(jì)時(shí)間隔之外,還有一種方法也可以改變速度,你能想到是什么方法嗎?(提示:速度與球移動(dòng)的頻次以及每次的移動(dòng)量相關(guān)。)在保持計(jì)時(shí)間隔100毫秒不變的情況下,改變MoveTo中的算式也可以改變移動(dòng)的速度:讓球每次只移動(dòng)2個(gè)像素,即2像素/100毫秒,這相當(dāng)于20像素/秒。

高級(jí)動(dòng)畫(huà)功能

這種讓物體在屏幕上移動(dòng)的能力,適合于那些飄來(lái)飄去的動(dòng)畫(huà)類(lèi)廣告,但要制作游戲或其他的動(dòng)畫(huà)應(yīng)用,就需要更為復(fù)雜的功能。幸運(yùn)的是,App Inventor提供了幾個(gè)的高級(jí)塊,用于處理動(dòng)畫(huà)類(lèi)事件,如物體到達(dá)屏幕邊緣及兩個(gè)物體的碰撞。

在這種情況下,用高級(jí)塊來(lái)偵測(cè)兩個(gè)sprite之間的碰撞這類(lèi)事件,表明App Inventor已經(jīng)深入到了程序的底層細(xì)節(jié)。其實(shí)你自己也可以利用Clock.Timer事件,通過(guò)檢查每個(gè)sprite的xy坐標(biāo)及Width、Height屬性來(lái)檢測(cè)到這類(lèi)事件的發(fā)生,但這樣的程序涉及到非常復(fù)雜的邏輯。由于這類(lèi)事件在許多游戲及其他應(yīng)用中很常見(jiàn),因此App Inventor為你提供了這些功能。

抵達(dá)邊界

{%}

圖 17-6 當(dāng)球到達(dá)邊緣時(shí)讓它重回左上角

重新考慮前面的動(dòng)畫(huà),物體在canvas上沿著對(duì)角線(xiàn)方向從左上角向右下角移動(dòng)。依照前面的程序,物體沿對(duì)角線(xiàn)方向移動(dòng)并將停在canvas的右下角(因?yàn)橄到y(tǒng)不允許sprite對(duì)象超出canvas的邊界)。

如果想讓物體在到達(dá)右下角后再重新出現(xiàn)在左上角,可以定義一個(gè)事件處理程序Ball.EdgeReached來(lái)響應(yīng)到達(dá)邊緣事件。

當(dāng)Ball碰到canvas的任何一個(gè)邊時(shí),將觸發(fā)EdgeReached事件(到達(dá)邊緣事件,該事件只適用于Sprite及Ball組件)。這個(gè)事件,再加上前面提到的讓球沿斜線(xiàn)移動(dòng)的定時(shí)器事件,兩個(gè)事件共同作用的結(jié)果就是,球從左上角向右下角移動(dòng),在到達(dá)彼岸猿猴再跳回到左上角,然后繼續(xù)移動(dòng),并再次跳回,循環(huán)往復(fù),永不停止(或者直到接到其他指令)。

注意到在EdgeReached事件中有一個(gè)參數(shù),edge1,它代表球碰到的那個(gè)邊,這里用數(shù)字來(lái)代表不同的方向:

  • North = 1

  • Northeast = 2

  • East = 3

  • Southeast = 4

  • South = -1

  • Southwest = -2

  • West = -3

  • Northwest = -4

CollidingWith事件與NoLongerCollidingWith事件

射擊類(lèi)、運(yùn)動(dòng)類(lèi)游戲以及其他類(lèi)型的動(dòng)畫(huà)應(yīng)用通常都會(huì)涉及到兩個(gè)或多個(gè)物體之間的碰撞(如,子彈擊中靶子)。

例如,考慮這樣一個(gè)游戲,當(dāng)其中的物體與其他物體發(fā)生碰撞時(shí),會(huì)改變顏色,并發(fā)出爆炸聲,圖17-7中顯示了這樣一個(gè)事件處理程序。

{%}

圖 17-7 當(dāng)球與其他物體發(fā)生碰撞時(shí),變色并發(fā)出爆炸聲

NoLongerCollidingWith事件是與CollidedWith相反的事件,當(dāng)兩個(gè)碰到一起的物體分開(kāi)時(shí),觸發(fā)該事件。而在游戲中,可能用到圖17-8中的塊。

{%}

圖 17-8 當(dāng)碰撞的物體離開(kāi)時(shí),球變黑色并停止爆炸聲

注意到CollidedWith及NoLongerCollidingWith事件都有一個(gè)參數(shù)other,它代表了被撞到的那個(gè)物體。這可以用來(lái)處理一個(gè)物體(如Ball1)與另一個(gè)指定物體之間的相互作用。如圖17-9所示。

{%}

圖 17-9 只有當(dāng)Ball1碰撞到ImageSprite1時(shí)才做相應(yīng)

之前我們沒(méi)有提到過(guò)這個(gè)“ImageSprite組件”塊。如果需要對(duì)兩個(gè)組件進(jìn)行比較(得知究竟是哪一個(gè)與之碰撞),如本例中的情形,就必須指定被比較的具體對(duì)象。為此,每個(gè)組件都有一個(gè)指向它自己的塊,而這個(gè)塊就在ImageSprite1的抽屜里,排在最后一個(gè)的就是。

交互動(dòng)畫(huà)

到目前為止,我們所討論的動(dòng)畫(huà)行為都沒(méi)有最終用戶(hù)的參與。毫無(wú)疑問(wèn),游戲都是交互的,最終用戶(hù)扮演著核心的角色,通常他們使用按鈕或其他界面對(duì)象來(lái)控制物體的速度及方向。

作為例子,我們來(lái)改變對(duì)角線(xiàn)移動(dòng)的動(dòng)畫(huà),用戶(hù)可以讓移動(dòng)停止然后再啟動(dòng)。可以通過(guò)對(duì)Button.Click事件編程來(lái)實(shí)現(xiàn)這一點(diǎn),具體方法是控制clock組件的啟用與禁用屬性。

在默認(rèn)情況下,Clock組件的timerEnabled屬性是被選中的,可以在事件處理程序中動(dòng)態(tài)地設(shè)置它,如設(shè)為false。例如,在圖17-10的事件處理程序中,在用戶(hù)第一次點(diǎn)擊按鈕時(shí),可以讓Clock的計(jì)時(shí)作用停止運(yùn)行。

{%}

圖 17-10 當(dāng)按鈕被第一次點(diǎn)擊時(shí),停止計(jì)時(shí)

在Clock1.TimerEnabled屬性被設(shè)為false之后,Clock1.Timer事件不再被觸發(fā),因此球停止移動(dòng)。

當(dāng)然,只是在第一次點(diǎn)擊時(shí)讓運(yùn)動(dòng)停止,這樣的操作并不能為游戲帶來(lái)樂(lè)趣,需要在事件處理程序中添加一個(gè)ifelse塊來(lái)控制計(jì)時(shí)功能的啟用與禁用,從而實(shí)現(xiàn)對(duì)運(yùn)動(dòng)的雙向控制(運(yùn)動(dòng)及停止)。如圖17-11所示。

{%}

圖 17-11 添加ifelse塊,通過(guò)點(diǎn)擊按鈕來(lái)控制運(yùn)動(dòng)的開(kāi)始與停止

在點(diǎn)擊按鈕的事件處理程序中,第一次點(diǎn)擊按鈕,計(jì)時(shí)器停止計(jì)時(shí),按鈕上的文字由“停止”變?yōu)椤伴_(kāi)始”;第二次點(diǎn)擊按鈕,此時(shí)TimerEnabled的值為false,因此執(zhí)行“else”分支,于是計(jì)時(shí)器被置于啟用狀態(tài),使得物體重新開(kāi)始移動(dòng),按鈕上的文字改回“停止”。關(guān)于ifelse快的詳細(xì)信息請(qǐng)參見(jiàn)第18章,另外,關(guān)于用方向傳感器創(chuàng)建交互動(dòng)畫(huà)的例子,請(qǐng)參見(jiàn)第5章及第23章。

關(guān)于沒(méi)有計(jì)時(shí)器的sprite動(dòng)畫(huà)

目前為止我們講述的動(dòng)畫(huà)案例都是利用Clock組件的計(jì)時(shí)功能,計(jì)時(shí)器事件每觸發(fā)一次,物體就移動(dòng)一次。采用Clock.Timer事件的方案是設(shè)定動(dòng)畫(huà)最普遍的方案,除了可以移動(dòng)物體,還可以隨時(shí)間改變物體的顏色,改變某些文字(好像應(yīng)用自己在輸入文字一樣),或者讓?xiě)?yīng)用以某個(gè)速度說(shuō)話(huà),等等。

App Inventor提供了另外一種不需要Clock組件而讓物體的移動(dòng)的方法。你可能已經(jīng)注意到,ImageSprite及Ball組件都具有Heading(方向)、Speed(速度)及Interval(間隔)屬性。與Clock.Timer方案中定義事件處理程序相比,這里可以在組件設(shè)計(jì)器及塊編輯器中設(shè)置這些屬性,來(lái)實(shí)現(xiàn)對(duì)sprite運(yùn)動(dòng)的控制。

為了便于描述,我們來(lái)重新考慮沿對(duì)角線(xiàn)移動(dòng)的例子。Sprite或ball的Heading屬性的取值范圍為0-360度,如圖17-2所示。

{%}

圖 17-12 Heading屬性的取值范圍

如果Heading屬性設(shè)置為0,則球從左向右移動(dòng);如果設(shè)為90,則從底向上移動(dòng);如果設(shè)為180,則從右向左移動(dòng);如果設(shè)為270,則從上向下移動(dòng)。

當(dāng)然,可以將Heading設(shè)定為0-360之間的任何值。要想讓球沿對(duì)角線(xiàn)從左上角向右下角移動(dòng),就需要將Heading設(shè)為315。

此外,還需要設(shè)置Speed屬性,它可以是0以外的任何值。此處Speed屬性對(duì)物體的移動(dòng)作用與MoveTo函數(shù)的作用相同:定義了每個(gè)時(shí)間間隔(interval)物體移動(dòng)的像素?cái)?shù),而時(shí)間間隔由物體的Interval屬性來(lái)定義。

嘗試設(shè)置這些屬性,用Canvas及Ball創(chuàng)建一個(gè)測(cè)試應(yīng)用,并點(diǎn)擊“Connect AICompanion”,在手機(jī)(或設(shè)備)上查看應(yīng)用。修改Heading、Speed以及Interval屬性,看看球是如何運(yùn)動(dòng)的。

如果你想通過(guò)編程來(lái)實(shí)現(xiàn)球在左上角與右下角之間做連續(xù)往復(fù)運(yùn)動(dòng),可以在組件設(shè)計(jì)器中將球的Heading屬性初始值設(shè)為315,然后在塊編輯器中添加Ball1.EdgeReached事件處理程序,當(dāng)球到達(dá)邊緣時(shí),改變它的方向。如圖17-13所示。

{%}

圖 17-13 當(dāng)球到達(dá)邊緣時(shí)改變它的方向

小結(jié)

動(dòng)畫(huà)是物體隨時(shí)間的位置移動(dòng)或某些屬性的變化,App Inventor為提供了幾個(gè)高級(jí)的組件及功能,讓動(dòng)畫(huà)的實(shí)現(xiàn)變得簡(jiǎn)單易行。通過(guò)對(duì)Clock組件的Timer事件進(jìn)行編程,可以創(chuàng)建任何類(lèi)型的動(dòng)畫(huà),包括物體的移動(dòng)——這是任何類(lèi)型游戲中最基本的活動(dòng)。

Canvas組件在設(shè)備的屏幕上定義了一個(gè)區(qū)域,物體可以在其中移動(dòng),并產(chǎn)生交互。Canvas內(nèi)部只接受兩種類(lèi)型的組件,即ImageSprite組件及Ball組件。這些組件為處理碰撞及到達(dá)邊界這樣的事件提供了高級(jí)功能。此外,這些組件的Heading、Speed及Interval屬性也為運(yùn)動(dòng)的實(shí)現(xiàn)提供了替代方法。

以上內(nèi)容是否對(duì)您有幫助:
在線(xiàn)筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)