Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android游戲 >> Android游戲開發 >> Android游戲開發15:詳談OnTouchEvent() 觸屏事件的性能優化

Android游戲開發15:詳談OnTouchEvent() 觸屏事件的性能優化

編輯:Android游戲開發

       各位童鞋肯定都知道在模擬器中,我們的鼠標當點擊一次模擬器屏幕然後釋放,先觸發 ACTION_DOWN 然後 ACTION_UP ;如果是在屏幕上移動那麼才會觸發 ACTION_MOVE 的動作;OK,很對。但是你要知道,這只是模擬器!

       真機與模擬器的區別

       當我們的用戶在玩我們的游戲的時候,尤其是RPG這種類型的,用戶肯定需要會長時間的去觸屏按我們的虛擬按鍵,比如我們會在屏幕上畫上一個虛擬方向盤類似這樣子~那麼其實 ACTION_MOVE 這個事件會被Android一直在響應!

       為什麼會一直響應 ACTION_MOVE 這個動作呢? 如果用戶沒有移動手指而是靜止不動也會一直響應?

       原因有兩點:第一點是因為,Android 對於觸屏事件很敏感!第二點,雖然我們的手指感覺是靜止沒有移動,其實事實不是如此!當我們的手指觸摸到手機屏幕上之後,感覺靜止沒動,其實手指在不停的微顫抖震動。不信你試試靜止下手指,是不是微微動?嘿嘿~

       so~ 我們就要分析了,如果ACTION_MOVE此時間一直被Android os 一直不停的響應並處理,無疑對我們游戲的性能增加了不少的負擔!

       比如我們游戲線程繪圖時間每次用了100ms,那麼當手指觸摸屏幕,這短暫的0.1秒內大概會產生10個左右的MotionEvent ,並且系統會盡可能快的把這些event發給監聽線程, 這樣的話在這一段時間內cpu就會忙於處理onTouchEvent從而杯具點的話會造成畫面一卡一卡的。

       那麼我們其實根本用不著按鍵響應這麼多次,而是需要在我們每次繪圖後,或者繪圖前接受一次用戶按鍵就OK了,這樣能讓幀率不至於下降的太厲害不是麼?!so~我們要控制這個時間,讓他慢下來,隨著我們的繪圖時間一起來合作~這樣就能減不少系統線程的負擔。

       實例分析

       下面貼一段代碼,一塊來看一下:

Java代碼
  1. package com.himi;   
  2. import android.app.Activity;   
  3. import android.os.Bundle;   
  4. import android.util.Log;   
  5. import android.view.MotionEvent;   
  6. import android.view.Window;   
  7. import android.view.WindowManager;   
  8. /**  
  9.  * @author Himi  
  10.  */  
  11. public class MainActivity extends Activity {   
  12.     private Object object;   
  13.     private final int TIME = 50;//備注1   
  14.     @Override  
  15.     public void onCreate(Bundle savedInstanceState) {   
  16.         super.onCreate(savedInstanceState);   
  17.         getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);   
  18.         this.requestWindowFeature(Window.FEATURE_NO_TITLE);   
  19.         setContentView(R.layout.main);   
  20.         object = new Object();   
  21.     }   
  22.     @Override  
  23.     public boolean onTouchEvent(MotionEvent event) {   
  24.         if (event.getAction() == MotionEvent.ACTION_DOWN) {   
  25.             Log.v("Himi", "ACTION_DOWN");   
  26.         } else if (event.getAction() == MotionEvent.ACTION_UP) {   
  27.             Log.v("Himi", "ACTION_UP");   
  28.         } else if (event.getAction() == MotionEvent.ACTION_MOVE) {   
  29.             Log.v("Himi", "ACTION_MOVE");   
  30.         }   
  31.         synchronized (object) {//備注2   
  32.             try {   
  33.                 object.wait(TIME);   
  34.             } catch (InterruptedException e) {   
  35.                 // TODO Auto-generated catch block   
  36.                 e.printStackTrace();   
  37.             }   
  38.         }   
  39.         return true;//這裡一定要返回true!原因請看【Android游戲開發9】   
  40.     }   
  41. }  

       代碼很清晰了,主要就是備注2的地方。

       備注2:

       可能有的童鞋會問為什麼不用sleep()的方法,其實如果我們只是想讓線程休眠指定時間的話可以用sleep()函數,但是這個沒有資源鎖的限制。而Object的wait、notify方法通常用在時間不定的條件限制等待,並且必須寫在同步代碼塊中。

       還有童鞋會問,為什麼不用當前類的object來使用:this.wait(),而是new 一個object來?這是因為:

       synchronized 中的Object 表示Object 調用wait必須擁有該對象的監視鎖,當前我們有了object的鎖,就要用object調用wait~

       備注1:

       這裡的變量大家都知道其實是我們設置的休眠的時間,那麼這裡我想拿出來跟大家說下關於這個時間的定值,在上文我也有說過我們的游戲中只要按鍵跟我們的繪圖線程的時間一樣即可,當然這裡是個我們的理想時間!如果我們游戲中有人物的幀,那麼我們可以來根據人物幀數來當成設定這個睡眠時間也是相當合適的,畢竟人物一幀說明邏輯執行了一遍了,呵呵~,這個還是根據大家游戲的情況而定吧。

       注意:Object.wait(long timeout)這個方法也需要慎用!

       原因是因為測試發現:這個睡眠的時間其實比你規定的時間要略微的長一些,不過我們合理控制好時間還是沒問題的。

       補充:

       1、看到有童鞋問//備注2這裡能不能用this,也就是當前的object,答案是可以的,但是要注意最好不要這樣用,原因是如果當其他地方也需要與當前的Object進行同步的話有可能出現死鎖情況!用一個新的object的原因也就是可以讓代碼中該干什麼就干什麼,互不影響,

       2、//備注2這裡其實我們可以對其優化,,畢竟一個Object比較浪費,我們其實只需要一個字節就足夠了,so~我們可以這樣定義一個:byte[] lock = new byte[0]; 這樣可以算是最優了~

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved