您好,登錄后才能下訂單哦!
OGEngine學習筆記--- 事件傳遞
事件傳遞
Android中的事件在表現形式上有很多,如onTouch、onClick和onLongClick等,在具體微觀上的表現形勢有action_down、action_move和action_up等。
無論哪種事件表現類型,首先都是基于事件的傳遞模型。其實Android中的事件傳遞有點類似于JS中事件傳遞模型。都是基于先捕獲然后冒泡的形式。
在OGEngine的API中,OGEngine負責捕獲觸摸事件,如果我們需要監聽觸摸事件,則需要向Scene注冊。
mScene.registerTouchArea(touchArea);
復制代碼
通過查閱ITouchArea的源碼發現
public boolean contains(final float pX, final float pY);
public float[] convertSceneToLocalCoordinates(final float pX, final float pY);
public float[] convertLocalToSceneCoordinates(final float pX, final float pY);
public boolean onAreaTouched(final TouchEvent pSceneTouchEvent, final float pTouchAreaLocalX, final float pTouchAreaLocalY);
復制代碼
一個區域里有自己的判斷當前觸摸的坐標是不是屬于自己感興趣的,如果不是則直接拋棄。
因為Shape類是實現了ITouchArea接口的,所以我們的Sprite等精靈類都可以直接被注冊。
在Scene的源碼里可以找到相關的代碼,于是我們了解了,在Andengine中,監聽觸摸和Entity并不是同一個概念,兩者是獨立的,于是這也解釋了,為什么在Scene中detach了一個Entity,在其注冊過監聽的地方觸摸還是會觸發和以前一樣的效果。
再來關注事件的傳遞,在源碼中我們發現由于事件需要Area本身來判斷其是否屬于Area,所以在注冊的時候并不存在類似Android中的父子關系,傳遞是根據注冊的順序一個一個進行的,但是相同的是如果一個Area宣布自己處理了時間(返回了true),傳遞序列就會直接終止,這里和Android中的事件是一樣的。
但是這樣固定的順序會有一些問題,其實設計者已經考慮到了這個問題,于是我們在源碼中發現了一個標志量:mOnAreaTouchTraversalBackToFront。 這個標志會決定當前事件的傳遞是正序還是逆序,這樣就在一定程度上解決了我們的問題。
屏幕事件
OnAreaTouchListener的注冊
BaseGameActivity.onLoadEngine():生成引擎,設置引擎的參數
BaseGameActivity.startScene():跳轉到某個場景中
復制代碼
其中會調用setOnTouchListener(),將Engine作為TouchListener注冊到scene中。其后所有的屏幕事件就會知道調用Engine的onTouch()方法。
屏幕事件的預處理
Android中的屏幕事件是即時突發,也就是說只要產生了屏幕事件就會在事件線程內直接調用注冊監聽器的onTouch()方法,如果處理時間過長,Android會直接將程序判定為無響應,并被踢出來。在OGEngine中支持兩種響應方式
*即時觸發:接受到屏幕事件后立即調用注冊的監聽器(默認)
優點:和Android一樣,容易學習
缺點:需要注意處理時間,超時的話會被判定為無響應
容易與OGEngine中的UpdateThread線程或描畫線程形成資源競爭
為了避免競合,又要做線程安全麻煩,比較復雜
*UpdateThread中觸發:接受到屏幕事件后先放入池中,在UpdateThread中統一調用和上面的相反
預處理Flow
Engine.onTouch():判斷引擎是否運行中,如果已停止就什么也不做,否則交給mTouchController處理。
SingleTouchControler.onHandleMotionEvent():有兩個分支
* 即時觸發:
TouchEvent.obtain():生成TouchEvent
mTouchEventCallback.onTouchEvent():響應事件(調用Engine.onTouchEven
*UpdateThread中觸發:
TouchEvent.obtain():生成TouchEvent
mTouchEventRunnablePoolUpdateHandler.obtainPoolItem():生成事件處理對象
事件處理對象就是在run()方法中通過mTouchEventCallback.onTouchEvent()響應事件
touchEventRunnablePoolItem.set(touchEvent):設定屏幕事件
mTouchEventRunnablePoolUpdateHandler.postPoolItem:放入事件池中
Engine.onUpdate中調用mTouchController.onUpdate()執行事件處理
屏幕事件處理
a) Engine.onTouchEvent():屏幕事件處理入口
b) Camera.convertSurfaceToSceneTouchEvent():坐標變換
c) Engine.onTouchScene():處理Scene屏幕事件(遍歷注冊的TouchArea,找到合適的就調用對應的處理監聽器,如果沒有就調用Scene的監聽器Scene的屏幕處理中有三個比較有意思的屬性:
mOnAreaTouchTraversalBackToFront:事件的響應順序是從后往前,還是調過來。默認是從后往前
mTouchAreaBindingEnabled:當監聽到ACTION_DOWN事件后是否需要綁定。綁定的意思是說到ACTION_UP或ACTION_CANCEL為止的事件全部交給這個監聽器處理。
mOnSceneTouchListenerBindingEnabled:和上一次差不多,這筆綁定的對象是Scene的監聽器
http://www.eoeandroid.com/forum-863-1.html
www.ogengine.com
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。