李華明Himi 原創,轉載務必在明顯處註明:
轉載自【黑米GameDev街區】 原文連結: http://www.himigame.com/android-game/344.html
很多童鞋說My Code運行後,點擊home或者back後會程式異常,如果你也這樣遇到過,那麼你肯定沒有仔細讀完Himi的博文,第十九篇Himi專門寫了關於這些錯誤的原因和解決方案,這裡我在部落格都補充說明下,省的童鞋們總疑惑這一塊;請點擊下面聯絡進入閱讀:
【Android遊戲開發十九】(必看篇)SurfaceView運行機制詳解—剖析Back與Home按鍵及切入後台等異常處理!
前兩篇都是向大家介紹了很有意思的兩種手勢操作,嵌入我們遊戲中,不得不說讓遊戲的自由度、可玩性和趣味性都增色不少!那麼今天繼續給大家介紹一亮點!感應器!
一:什麼是感應器:
所謂感應器能夠探測如光、熱、溫度、重力、方向 等等的功能!
二:Android中提供感應器有哪些:
1. 加速度感應器(重力感應器)
2. 陀螺儀感應器
3. 光感應器
5. 恒定磁場感應器
6. 方向感應器
7. 恒定的壓力感應器
8. 接近感應器
9. 溫度感應器
今天我們給大家介紹的是遊戲開發中最最常見的,用到的頻率最高的一種感應器,加速度感應器(重力感應器)!
因為模擬器無法測試,所以我用手機調試的~,先上兩張;
/**<br /> *@author Himi<br /> *@Sensor 加速度感應器 ,也稱為重力感應器<br /> *@SDK 1.5(api 3)就支援感應器了<br /> *@解釋:此感應器不僅對玩家反轉手機的動作可以檢測到,而且會根據反轉手機的程度,得到感應器的值也會不同!<br /> */<br />public class MySurfaceView extends SurfaceView implements Callback, Runnable {<br />private Thread th = new Thread(this);<br />private SurfaceHolder sfh;<br />private Canvas canvas;<br />private Paint paint;<br />private SensorManager sm;<br />private Sensor sensor;<br />private SensorEventListener mySensorListener;<br />private int arc_x, arc_y;// 圓形的x,y位置<br />private float x = 0, y = 0, z = 0;<br />public MySurfaceView(Context context) {<br />super(context);<br />this.setKeepScreenOn(true);<br />sfh = this.getHolder();<br />sfh.addCallback(this);<br />paint = new Paint();<br />paint.setAntiAlias(true);<br />setFocusable(true);<br />setFocusableInTouchMode(true);<br />//通過服務得到感應器管理對象<br />sm = (SensorManager) MainActivity.ma.getSystemService(Service.SENSOR_SERVICE);<br />sensor = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);//得到一個重力感應器執行個體<br />//TYPE_ACCELEROMETER 加速度感應器(重力感應器)類型。<br />//TYPE_ALL 描述所有類型的感應器。<br />//TYPE_GYROSCOPE 陀螺儀感應器類型<br />//TYPE_LIGHT 光感應器類型<br />//TYPE_MAGNETIC_FIELD 恒定磁場感應器類型。<br />//TYPE_ORIENTATION 方向感應器類型。<br />//TYPE_PRESSURE 描述一個恒定的壓力感應器類型<br />//TYPE_PROXIMITY 常量描述型接近感應器<br />//TYPE_TEMPERATURE 溫度感應器類型描述<br />mySensorListener = new SensorEventListener() {<br />@Override<br />//感應器擷取值發生改變時在響應此函數<br />public void onSensorChanged(SensorEvent event) {//備忘1<br />//感應器擷取值發生改變,在此處理<br />x = event.values[0]; //手機橫向翻滾<br />//x>0 說明當前手機左翻 x<0右翻<br />y = event.values[1]; //手機縱向翻滾<br />//y>0 說明當前手機下翻 y<0上翻<br />z = event.values[2]; //螢幕的朝向<br />//z>0 手機螢幕朝上 z<0 手機螢幕朝下<br />arc_x -= x;//備忘2<br />arc_y += y;<br />}<br />@Override<br />//感應器的精度發生改變時響應此函數<br />public void onAccuracyChanged(Sensor sensor, int accuracy) {<br />// TODO Auto-generated method stub<br />}<br />};<br />sm.registerListener(mySensorListener, sensor, SensorManager.SENSOR_DELAY_GAME);<br />//第一個參數是感應器監聽器,第二個是需要監聽的感測執行個體<br />//最後一個參數是監聽的感應器速率類型: 一共一下四種形式<br />//SENSOR_DELAY_NORMAL 正常<br />//SENSOR_DELAY_UI 適合介面<br />//SENSOR_DELAY_GAME 適合遊戲 (我們必須選這個呀 哇哈哈~)<br />//SENSOR_DELAY_FASTEST 最快<br />}<br />public void surfaceCreated(SurfaceHolder holder) {<br />arc_x = this.getWidth() / 2 - 25;<br />arc_y = this.getHeight() / 2 - 25;<br />th.start();<br />}<br />public void draw() {<br />try {<br />canvas = sfh.lockCanvas();<br />if (canvas != null) {<br />canvas.drawColor(Color.BLACK);<br />paint.setColor(Color.RED);<br />canvas.drawArc(new RectF(arc_x, arc_y, arc_x + 50,<br />arc_y + 50), 0, 360, true, paint);<br />paint.setColor(Color.YELLOW);<br />canvas.drawText("當前重力感應器的值:", arc_x - 50, arc_y-30, paint);<br />canvas.drawText("x=" + x + ",y=" + y + ",z=" + z,<br />arc_x - 50, arc_y, paint);<br />String temp_str = "Himi提示: ";<br />String temp_str2 = "";<br />String temp_str3 = "";<br />if (x < 1 && x > -1 && y < 1 && y > -1) {<br />temp_str += "當前手機處於水平放置的狀態";<br />if (z > 0) {<br />temp_str2 += "並且螢幕朝上";<br />} else {<br />temp_str2 += "並且螢幕朝下,提示別躺著玩手機,對眼睛不好喲~";<br />}<br />} else {<br />if (x > 1) {<br />temp_str2 += "當前手機處於向左翻的狀態";<br />} else if (x < -1) {<br />temp_str2 += "當前手機處於向右翻的狀態";<br />}<br />if (y > 1) {<br />temp_str2 += "當前手機處於向下翻的狀態";<br />} else if (y < -1) {<br />temp_str2 += "當前手機處於向上翻的狀態";<br />}<br />if (z > 0) {<br />temp_str3 += "並且螢幕朝上";<br />} else {<br />temp_str3 += "並且螢幕朝下,提示別躺著玩手機,對眼睛不好喲~";<br />}<br />}<br />paint.setTextSize(20);<br />canvas.drawText(temp_str, 0, 50, paint);<br />canvas.drawText(temp_str2, 0, 80, paint);<br />canvas.drawText(temp_str3, 0, 110, paint);<br />}<br />} catch (Exception e) {<br />Log.v("Himi", "draw is Error!");<br />} finally {<br />sfh.unlockCanvasAndPost(canvas);<br />}<br />}<br />@Override<br />public void run() {<br />// TODO Auto-generated method stub<br />while (true) {<br />draw();<br />try {<br />Thread.sleep(100);<br />} catch (Exception ex) {<br />}<br />}<br />}<br />public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {<br />}<br />public void surfaceDestroyed(SurfaceHolder holder) {<br />}<br />}
備忘1:
SensorEventListener的onSensorChanged事件將返回SensorEvent對象,包含Sensor的最新資料,通過event.values獲得一個float[]數組!對於不同的感應器類型,其數組包含的元素個數是不同的,重力感應器總是返回一個長度為3的數組,分別代表X、Y和Z方向的數值。Z軸表示了手機是螢幕朝上還是螢幕朝下;
這裡還要注意你當前手機處於 縱向, 還是橫向,因為這個會影響我們的X,Y表示的意思!
如果當前手機是縱向螢幕:
x>0 說明當前手機左翻 x<0右翻
y>0 說明當前手機下翻 y<0上翻
如果當前手機是橫向螢幕:
x>0 說明當前手機下翻 x<0上翻
y>0 說明當前手機右翻 y<0左翻
我要提醒各位童鞋:
1.要考慮玩家當前拿手機的姿勢,例如豎屏,橫屏
2.根據橫豎螢幕的不同,雖然螢幕座標系會自動改變,但是感應器的值不會自動改變座標系!所以為什麼會橫屏豎屏改變的時候我們從感應器中取出的值表示的動作不一樣的原因!!!因此大家遊戲開發的時候對於人物移動、圖片移動等等操作的時候,手勢X,Y的正負值代表什麼一定要想清楚!否則玩家會玩著玩著吐的 (太暈了!)- -、
備忘2 :
這裡本應該arc_x+=x;但是因為當前我螢幕是縱向!造成x>0的手勢表示玩家將手機左翻了,但是我們螢幕的圓形應該根據人的反轉相對應的移動,那麼這裡玩家將手機左翻,我們就應該讓原型的X座標減少!所以這裡寫成了arc_x-=x;!
總結一下: 對於感應器的雖然本章只是講了一個重力感應器,但是一個足夠了,因為如果你想使用其他的感應器,那麼你只要以下步驟就OK:
1. 利用 SensorManager.getDefaultSensor();傳入一個你想要的感應器的參數得到其執行個體!
2.註冊!
3.在監聽器裡處理事件!
OK!就是這麼簡單、
源碼: http://www.himigame.com/android-game/344.html