第三話 移動動畫特效

第三話 移動動畫特效

上一堂課我們說明了如何在按鈕上監聽Touch事件並執行相關程式,這個技巧是非常重要的,且常與其他程式相互配合,建議同學們如果還不夠熟悉如何建立偵聽器可回到上一課去複習喔。

本堂課的話題是移動動畫特效,這到底是做甚麼用的哩?很簡單,讓元件的屬性隨著時間產生數值變化是也!

每個元件常用的屬性其實不太多,通常有x . y . alpha . rotation . xScale. yScale. width .height等等。

最常用的當屬x.y,第一堂課當我們創建圖片元件時,就透過設定x.y來放置圖片於指定的位置,當隨著時間不斷的更改x.y的數值時,就可以讓元件移動。

其次則是alpha和rotation,前者用來調整元件的透明度。當想要讓元件有些半透明時就可以調整alpha,比如像是開頭頁面上的閃爍提示文字(PS:請按我開始遊戲)就可以用alpha來達成,其最大與最小值分別為1和0。至於後者則用來將元件進行旋轉,常搭配時間函式(timer.performWithDelay)來進行使用,其數值指的是旋轉的角度,要注意的是旋轉的中心點並非元件的中心點而是元件的錨點(anchorPoint)。
PS:元件錨點的位置可透過設定anchorX和anchorY來修改,最大與最小值分別為1和0,右端與上端為1,相對的,左端與下端為0。

再接著則是xScale和yScale,這兩個屬性用來調整元件位於X軸和Y軸的縮放比例。舉例來說如果希望某元件的寬度提高為2倍,只要設定xScale為2即可。要特別了解的是,修改這兩個參數並不會變更該元件的width和height。

最後一組屬性為width和height,也就是寬度和高度。同學也許覺得納悶,設定元件的寬度和高度應該很必要才是阿,為何會被列為較不常用。一般來說,width和height這一組屬性會在元件生成時設定好,接下來就不會再變更它。一來片面變更寬度或高度會讓元件的圖案被扭曲,二來當需要進行縮放的時候只要透過前一組xScale和yScale即可達到相同的效果,又可以保留width和height的原始數值。
PS:如需參考所有的元件屬性,請參考這裡。     

剛說到移動動畫特效就是讓元件的屬性隨時間產生數值變化,換句話說,就是隨著時間調整剛才介紹到的這些屬性,就能產生元件的視覺變化效果。

節省時間,就讓我們進入本課程的範例程式。本範例包含了兩個按鈕,分別是播放和停止。按下播放鈕將會開始播放位移動畫,可以看到一隻小野馬不斷的在左右兩端移動,並在碰到右端時略為彈跳。按下停止鍵時動畫將會暫停。

首先來聊聊新的東西,在程式碼的56~65行的部分,使用了widget函式庫的newButton方法,用來建立按鈕。另外在89.92這兩行使用了transition函式庫,用來進行位移動畫的控制。以下分別介紹...

widget庫的newButton方法在效果上有點類似第一課的圖片元件加上第二課的偵聽控制,優點在於製作按鈕上更為方便,像是按鈕被按下時通常會需要更換圖片.按鈕上需要顯示文字等等,如果使用display.newImageRect來製作時就需要多寫一些程式才能達到,而widget.newButton只需要於生成時設定即可。另外當需要暫時移除偵聽功能時,widget.newButton也更為簡單,只需要設定isEnabled屬性為false即可。

下方為 widget.newButton的程式碼,生成後會回傳按鈕的參考,我們要將其用區域變數存起來以便之後進行控制。


    btn_play = widget.newButton{
         id = "play",  --自訂屬性,用來辨認被按下的按鈕
         width = 600,  --按鈕寬度
         height = 150,  --按鈕寬度
         defaultFile = "images/btn_normal.png",  --按鈕預設圖片
         overFile = "images/btn_over.png",  --按鈕按下時圖片
         label = "播放",  --按鈕文字
         fontSize = 80,  --按鈕文字大小
         onEvent = handleButtonEvent  --當按下時要呼叫的韓式
     }

再來聊聊transition函式庫,最常用的函式為to,用來進行位移動畫。這裡再次提醒同學的是,雖然本文用位移動畫來命名這個應用,但絕不代表只能用來做移動的動畫,如果修改開頭所提的其他屬性,就能夠生成更多有趣的動畫,就請同學多多嘗試喔。當呼叫完to函式後會回傳transition參考,以便之後用來控制該動畫,比方說用pause函式來暫停動畫。如果希望把所有的動畫都暫停也可以直接呼叫transition函式庫的pause()函式。

關於transition.to函式的參數請參考下圖。

 

to函式並不難理解,主要是針對某一個元件進行控制,設定在幾秒的時間內(time屬性,單位為微秒),要將那些屬性值變更為多少,一個to函式不限定只能變動一個屬性。需要特別說明的是transition這個參數主要是用來控制屬性變動的曲線,這個概念對初學者來講有些費解,用個例子來說明。

transition.to( img, {time = 3000 , xScale = 1 )

上面的這個to函式會控制img元件,用3秒的時間慢慢地將寬度放大為2倍,因為沒設定transition,因此放大的速度會一直維持相同。但是變動transition的曲線之後,就能夠做到一開始變大的較慢,然後越來越快的這種變速效果,就如同變速球的效果一般,如下圖為例。

PS:如果想要了解transition支持那些曲線效果,請參考本網址

進階技巧:to函式的table屬性onComplete除了賦值一個函式變數外,甚至可以直接宣告一個匿名函式來傳入,當這個完成後的執行內容只會做一次時很方便,如下例:


transition.to( img, {time = 3000 , x = orign_x , xScale = 1 ,onComplete = function ()    print('hello world') end} )

介紹完新東西,現在來說明一下本範例的架構。首先引入各種函式庫並宣告變數,接著宣告本程式碼管理員函式main(),在裏頭呼叫initail()來進行元件初始化。再接著實作initial(),以及按鈕被按下時要呼叫的函式。當一切的元件和函式都準備完畢之後,最後才呼叫main()來啟動本範例。

本課程範例碼:


-----------------------------------------------------------------------------------------
--    這個範例解說如何製作神魔之塔的移動動畫
--    Author: Zack Lin
--    Time: 2015/9/17
-----------------------------------------------------------------------------------------
_SCREEN = {
    HEIGHT = display.contentHeight,   --執行裝置螢幕的高度
    WIDTH = display.contentWidth      --執行裝置螢幕的寬度
}

_SCREEN.CENTER = {
    X = display.contentCenterX,       --執行裝置螢幕的中心點X軸
    Y = display.contentCenterY        --執行裝置螢幕的中心點Y軸
}

display.setStatusBar( display.HiddenStatusBar )
local widget = require( "widget" ) --載入Widget函式庫

--宣告區域變數
local img
local btn_play
local btn_stop
local transitionGo
local transitionBack

local origin_alpha = 0.6
local orign_x = _SCREEN.CENTER.X + 120
--宣告區域變數函式
local initial
local handleButtonEvent
local moveBack
local move
--=======================================================================================
--宣告與定義main()函式
--=======================================================================================
local main = function (  )
    initial()
end

--=======================================================================================
--定義其他函式
--=======================================================================================
initial = function (  )
    local logo = display.newImageRect( "logo.png", _SCREEN.WIDTH/1.5, _SCREEN.HEIGHT/3 )
    logo.x = _SCREEN.CENTER.X
    logo.y = _SCREEN.CENTER.Y

    timer.performWithDelay(3000, function ( )
        logo:removeSelf( )
        logo = nil

        img = display.newImageRect(  "images/horse-0.gif", 150, 135 )
          img.x = orign_x
          img.y = _SCREEN.CENTER.Y  - 100
          img.alpha = origin_alpha
        btn_play = widget.newButton{
            id = "play", --自訂屬性,用來辨認被按下的按鈕
            width = 600,  --按鈕寬度
            height = 150,  --按鈕高度
            defaultFile = "images/btn_normal.png",  --按鈕預設圖片
            overFile = "images/btn_over.png",  --按鈕按下時圖片
            label = "播放",  --按鈕文字
            fontSize = 80,  --按鈕文字大小
            onEvent = handleButtonEvent  --當按下時要呼叫的函式
        }
        btn_play.x = _SCREEN.CENTER.X
        btn_play.y = _SCREEN.CENTER.Y + 100

        btn_stop = widget.newButton{
            id = "stop",
            width = 600,
            height = 150,
            defaultFile = "images/btn_normal.png",
            overFile = "images/btn_over.png",
            label = "停止",
            fontSize = 80,
            onEvent = handleButtonEvent
        }
        btn_stop.x = _SCREEN.CENTER.X
        btn_stop.y = _SCREEN.CENTER.Y + 300
    end )

end

--用於onComplete事件發生時所要被呼叫的function
moveBack = function (  )
    --執行移動動畫,參數依序為目標物件以及option table,裡頭option中較特別的為transition屬性用於設定移動效果,onComplete用於設定當結束後要呼叫的function
    transitionBack = transition.to( img, {time = 3000 , x = orign_x , xScale = 1 , yScale = 1 , rotation = 0 , alpha = origin_alpha , transition = easing.outBounce ,onComplete = move} )
end
move = function ()
    transitionGo = transition.to( img, {time = 2000 , x = 30 , xScale = 1.4 , yScale = 1.4 , rotation = 0 , alpha = 1 , transition = easing.inQuad , onComplete = moveBack} )
end
--按鈕事件偵聽函式
handleButtonEvent = function ( event )
    if ("play" == event.target.id) then
        move()
    elseif ( "stop" == event.target.id) then
        --暫停所有動畫
        transition.pause()
    end
end
--=======================================================================================
--呼叫主函式
--=======================================================================================
main()
分享這篇文章:

發佈自 林品爵

林品爵
一個堅信程式教育能夠改變下一代未來的狂熱者,青少年揚帆計畫的推動者。十年以上全端程式開發,上百場程式教學經驗,累積學生數達百人以上。 成大學士畢業,使用過J2EE.PHP.MySQL.CoronaSDK.Android.Objective-C.Swift.Python等技術知識,歷任友訊科技總部Java工程師首席.黑快馬股份有限公司研發經理.諾亞數碼娛樂執行長等職位,現任哥布林程式教育學苑創辦人,所開發過專案涵括產品管理系統.POS系統.拍賣平台.擴增實境.問券.社區App等等。 程式啟蒙班講師 . Laravel網頁程式班講師 . App程式班講師

關聯文章:

留下留言