2011年6月30日 星期四

Corona SDK -- Event Control

Event控制,我想應該是Corona最最最最最....最重要的項目了。為什麼這樣說呢,因為除了各種顯示物件的建立以外,全部都需要透過Event來達到與使用者互動或者觸發特殊事件,例如:
       1. 使用者按下按鈕,切換顯示圖片,這就是一種Event
       2. 使用者按下iPhone的暫停按鍵,要觸發暫停遊戲的動作
       3. 遊戲每次重新進入畫面(enterFrame),希望有相對應觸發動作
       4. 如果有使用Physics物理世界,有物件碰撞的話,要觸發什麼動作
        以上只是部分例子,看得出來,遊戲要有互動性,要有自動反應性,就是要透過Event的控制,好好設定好您想要觸發的動作與觸發機制。有這樣好的設計考量,您的遊戲程式將會變得很簡單,因為,你只要在主程式把畫面與物件設定好,其他就丟給Event自己去觸發,自己去跑程式了,你根本不用管玩家會怎麼樣去玩這個遊戲(你也無法管,哈)。

 先來看看,Corona玩家Jonathan Beebe是怎麼提到Event觸發時機:
        1. The user touches something on the screen
        2. A new “frame” in the app’s runtime has started(“enterFrame”)
        3. An in-app purchase item was requested
        4. Something has finished happen

        (跟我寫的很像喔~~ 可是我沒有抄他喔~ 哈哈)
        總之呢,就是要針對某特殊事件觸發特殊動作。
        因此,在設計Event的動作的時候,要先考慮清楚以下問題:
        1. 什麼物件的什麼動作要被傾聽?觸發後要做什麼動作?
        2. 在什麼時候可以開始傾聽?什麼時候要關掉?
        3. 在觸發動作的Function裡面,在什麼Phase做什麼事情?
        4. 你是否需要Runtime事件?需要哪一種Runtime事件?

        但是呢,你是無法知道玩家(使用者)何時會去觸發事件,所以呢,你要去傾聽(listen)這些事件何時被觸發,例如:老師要打你,你要跑給他追。你怎麼知道老師何時會打你,因此你要眼觀四方,耳聽八方,當他一有動作,你就要開始跑。因此,在Corona SDK裡面要設定你要傾聽(listen)什麼樣子的事件,而且也要設定,當事件被觸發時,要啟動什麼動作。

        以下先介紹特定物件事件,以touch某物件作為範例:
設定傾聽(listen)
local function ButtonTouch( event )
print( "Button Touched!" )
end
Button:addEventListener( “touch”, ButtonTouch )
以上,是表示當按下Button這個物件(display Object)時,去觸發ButtonTouch動作,當然,ButtonControl必須要是一個相對應的Function,如下:
----------------------------------------
        local function ButtonTouch( event )
                print( "Button Touched!" )
        end
        -- 設定 ”touch” event
        Button:addEventListener( "touch", ButtonTouch )
----------------------------------------
設定好listen之後,你一定會想,我觸發事件,也有個不同觸發方式相對不同衝發動作吧?什麼意思呢?再拿上面老師要打你的例子,他一拿起籐條(began相位),你就要開始跑,可是如果他打到你了(end 相位),你要哇哇叫。因此,在觸發動作的Function裡面呢,也是可以設定不同相位(phase)進行不同動作。
touch相位分為以下幾類:(以下針對touch事件,不同觸發事件有不同相位)
        1. began    :一開始觸控按下
        2. moved    :玩家手指在螢幕上移動,但並未移開手指
        3. ended     :玩家把手指拿開
        4. cancelled:系統結束相位
因此,為了避免在每一個相位都重複做動作,在Function裡面建議需要設定特定相位(phase)進行特定動作:
----------------------------------------
        local function ButtonTouch( event )
                if event.phase == "began" then
                        print( "Button Touched!" )
                elseif event.phase == "move" then
                        print( "Button moved at " .. event.x .. " , " .. event.y )
                elseif event.phase == "end" then
                        print( "Button ended" )
                end
        end
        Button:addEventListener( "touch", ButtonTouch )
----------------------------------------
這樣就很清楚分出,什麼phase要做什麼事情了。
        在上面範例,我直接使用了event.x以及event.y這是什麼呢?
在Event裡面,有一些相對應的參數可以調用的,不然你怎麼知道,手指的位置在哪邊呢?
        1. event.id 
                特殊的識別證,可以用來辨識一些很相似的物件,例如:每一家的門鈴,要透過門
                牌號碼來辨識
        2. event.target
                用來辨別是哪一個物件,例如:上述範例中,event.target就是Button
        3. event.x & event.y
                手指觸控的位置,此為即時資訊,隨時更新的。
        4. event.xStart & event.yStart
                第一次手指按下的位置,只有第一次按下,不再更新。

        了解以上Event定義之後,再來談談觸發事件Function的宣告方法。宣告有以下三種:
1.
----------------------------------------
        local function ButtonTouch( event )
                print( "Button Touched!" )
        end
        Button:addEventListener( "touch", ButtonTouch )
----------------------------------------
2.
----------------------------------------
        local function ButtonTouch( self, event )
        -- self就跟event.target一樣
                print( "Button Touched!" )
        end
        Button.touch = ButtonTouch
        Button:addEventListener( "touch", Button )
----------------------------------------
3.
----------------------------------------
        local function Button:touch( event )
                print( "Button Touched!" )
        end
        Button:addEventListener( "touch", Button )
----------------------------------------
最後,怎麼移除傾聽事件呢?
----------------------------------------
        local function ButtonTouch( event )
                print( "Button Touched!" )
        end
        Button:addEventListener( "touch", ButtonTouch )
        Button:removeEventListener( "touch", Button )
----------------------------------------
就這樣,採用removeEventListener就可以囉。
============================================================================
接來來介紹,除了特殊物件事件以外,當然也有一些事件是跟著遊戲進行一直一直在進行的,稱為Runtime Event。也就是,在遊戲進行中,只要有具體事件(非特定物件)符合觸發機制,就可以觸發動作。
Runtime Event有哪些呢:
                * enterFrame
 
                * system

                * orientation

                * accelerometer

                * location (GPS)

                * heading (compass)

                * completion

                * timer

                * touch

                * tap

                * Custom Events
設定方法就跟以上很相近:
----------------------------------------
        local function BackgroundTouch( event )
                print( "Background " .. event.name )
                -- event.name就等於 touch
                -- Output: Background touch
        end
        Runtime:addEventListener( "touch", BackgroundTouch )
        Runtime:removeEventListener( "touch", BackgroundTouch )
----------------------------------------
這樣設定,只要玩家有按下螢幕上任一的地方,都會觸發。
在介紹一個enterFrame,每一次進入新Frame,就會觸發一次(如果fps設定為30,則每秒進入30次)
----------------------------------------
        local function SystementerFrame( event )
                print( "enterFrame " )
        end
        Runtime:addEventListener( "enterFrame", SystementerFrame )
        Runtime:removeEventListener( "enterFrame", SystementerFrame )
----------------------------------------

ok,去玩玩看Event的威力吧。

沒有留言:

張貼留言