手勢操作可以說是智能手機的一種魅力所在,前兩節給大家講解了兩種有趣的手勢操作,將它們置於游戲當中,大大提升了游戲的可玩性和趣味性。本節將繼續介紹智能手機的另一種神奇之處:傳感器。
一、何為傳感器
所謂傳感器就是能夠探測如光、熱、溫度、重力、方向等等的裝置。
二、Android提供了哪些傳感器
1、加速度傳感器(重力傳感器)
2、陀螺儀傳感器
3、光傳感器
4、恆定磁場傳感器
5、方向傳感器
6、恆定的壓力傳感器
7、接近傳感器
8、溫度傳感器
今天我們給大家介紹的是游戲開發中最最常見的,用到的頻率最高的一種傳感--加速度傳感器(重力傳感器)!
三、傳感器實例講解
因為模擬器無法測試,所以我用手機調試的,先上兩張截圖:
下面貼代碼:
Java代碼
- /**
- *@author Himi
- *@Sensor 加速度傳感器 ,也稱為重力傳感器
- *@SDK 1.5(api 3)就支持傳感器了
- *@解釋:此傳感器不僅對玩家反轉手機的動作可以檢測到,而且會根據反轉手機的程度,得到傳感器的值也會不同!
- */
- public class MySurfaceView extends SurfaceView implements Callback, Runnable {
- private Thread th = new Thread(this);
- private SurfaceHolder sfh;
- private Canvas canvas;
- private Paint paint;
- private SensorManager sm;
- private Sensor sensor;
- private SensorEventListener mySensorListener;
- private int arc_x, arc_y;// 圓形的x,y位置
- private float x = 0, y = 0, z = 0;
- public MySurfaceView(Context context) {
- super(context);
- this.setKeepScreenOn(true);
- sfh = this.getHolder();
- sfh.addCallback(this);
- paint = new Paint();
- paint.setAntiAlias(true);
- setFocusable(true);
- setFocusableInTouchMode(true);
- //通過服務得到傳感器管理對象
- sm = (SensorManager) MainActivity.ma.getSystemService(Service.SENSOR_SERVICE);
- sensor = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);//得到一個重力傳感器實例
- //TYPE_ACCELEROMETER 加速度傳感器(重力傳感器)類型。
- //TYPE_ALL 描述所有類型的傳感器。
- //TYPE_GYROSCOPE 陀螺儀傳感器類型
- //TYPE_LIGHT 光傳感器類型
- //TYPE_MAGNETIC_FIELD 恆定磁場傳感器類型。
- //TYPE_ORIENTATION 方向傳感器類型。
- //TYPE_PRESSURE 描述一個恆定的壓力傳感器類型
- //TYPE_PROXIMITY 常量描述型接近傳感器
- //TYPE_TEMPERATURE 溫度傳感器類型描述
- mySensorListener = new SensorEventListener() {
- @Override
- //傳感器獲取值發生改變時在響應此函數
- public void onSensorChanged(SensorEvent event) {//備注1
- //傳感器獲取值發生改變,在此處理
- x = event.values[0]; //手機橫向翻滾
- //x>0 說明當前手機左翻 x<0右翻
- y = event.values[1]; //手機縱向翻滾
- //y>0 說明當前手機下翻 y<0上翻
- z = event.values[2]; //屏幕的朝向
- //z>0 手機屏幕朝上 z<0 手機屏幕朝下
- arc_x -= x;//備注2
- arc_y += y;
- }
- @Override
- //傳感器的精度發生改變時響應此函數
- public void onAccuracyChanged(Sensor sensor, int accuracy) {
- // TODO Auto-generated method stub
- }
- };
- sm.registerListener(mySensorListener, sensor, SensorManager.SENSOR_DELAY_GAME);
- //第一個參數是傳感器監聽器,第二個是需要監聽的傳感實例
- //最後一個參數是監聽的傳感器速率類型: 一共一下四種形式
- //SENSOR_DELAY_NORMAL 正常
- //SENSOR_DELAY_UI 適合界面
- //SENSOR_DELAY_GAME 適合游戲 (我們必須選這個呀 哇哈哈~)
- //SENSOR_DELAY_FASTEST 最快
- }
- public void surfaceCreated(SurfaceHolder holder) {
- arc_x = this.getWidth() / 2 - 25;
- arc_y = this.getHeight() / 2 - 25;
- th.start();
- }
- public void draw() {
- try {
- canvas = sfh.lockCanvas();
- if (canvas != null) {
- canvas.drawColor(Color.BLACK);
- paint.setColor(Color.RED);
- canvas.drawArc(new RectF(arc_x, arc_y, arc_x + 50,
- arc_y + 50), 0, 360, true, paint);
- paint.setColor(Color.YELLOW);
- canvas.drawText("當前重力傳感器的值:", arc_x - 50, arc_y-30, paint);
- canvas.drawText("x=" + x + ",y=" + y + ",z=" + z,
- arc_x - 50, arc_y, paint);
- String temp_str = "Himi提示: ";
- String temp_str2 = "";
- String temp_str3 = "";
- if (x < 1 && x > -1 && y < 1 && y > -1) {
- temp_str += "當前手機處於水平放置的狀態";
- if (z > 0) {
- temp_str2 += "並且屏幕朝上";
- } else {
- temp_str2 += "並且屏幕朝下,提示別躺著玩手機,對眼睛不好喲~";
- }
- } else {
- if (x > 1) {
- temp_str2 += "當前手機處於向左翻的狀態";
- } else if (x < -1) {
- temp_str2 += "當前手機處於向右翻的狀態";
- }
- if (y > 1) {
- temp_str2 += "當前手機處於向下翻的狀態";
- } else if (y < -1) {
- temp_str2 += "當前手機處於向上翻的狀態";
- }
- if (z > 0) {
- temp_str3 += "並且屏幕朝上";
- } else {
- temp_str3 += "並且屏幕朝下,提示別躺著玩手機,對眼睛不好喲~";
- }
- }
- paint.setTextSize(20);
- canvas.drawText(temp_str, 0, 50, paint);
- canvas.drawText(temp_str2, 0, 80, paint);
- canvas.drawText(temp_str3, 0, 110, paint);
- }
- } catch (Exception e) {
- Log.v("Himi", "draw is Error!");
- } finally {
- sfh.unlockCanvasAndPost(canvas);
- }
- }
- @Override
- public void run() {
- // TODO Auto-generated method stub
- while (true) {
- draw();
- try {
- Thread.sleep(100);
- } catch (Exception ex) {
- }
- }
- }
- public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
- }
- public void surfaceDestroyed(SurfaceHolder holder) {
- }
- }
備注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;。
總結
雖然本節只講了重力傳感器這一種,但已經足夠了,因為如果你想使用其他的傳感器,只要按以下步驟操作就可以:
1、利用 SensorManager.getDefaultSensor();傳入一個你想要的傳感器的參數得到其實例;
2、注冊;
3、在監聽器裡處理事件。
其實並不難,你也可以讓自己的游戲有各種感應效果了。