[轉]淺談Android重力感應


Android重力感應實現方式簡介

本文段轉自:http://developer.51cto.com/art/201001/180956.htm

在Android應用程序的開發中,占據主要地位的當屬游戲的開發。我們在這篇文章中將會針對在游戲中需要用到的重力感應功能,來為大家詳細分析Android重力感應的實現方法,以幫助大家解決相關問題。

Android中的很多游戲的游戲都使用了重力感應的技術,但其api demo卻並沒有重力感應的實例(不知道是不是我沒找到,找到的朋友麻煩告訴我一下,謝謝),因為開發的需要,就研究了一下重力感應這方面,因為網上關於這方面的東西比較少,所以寫出來跟大家交流一下,算是拋磚引玉吧。(ps.因為重力感應式需要真機才能測試的,所以,下面提供的demo程序只能在真機上跑。)

 

因為官方說明比較含糊難懂,我用最簡單的方式講一下Android重力感應系統的坐標系

 

以屏幕的左下方為原點(2d編程的時候,是以屏幕左上方為原點的,這個值得注意一下),箭頭指向的方向為正。

從-10到10,以浮點數為等級單位,想象一下以下情形:

手機屏幕向上(z軸朝天)水平放置的時侯,(x,y,z)的值分別為(0,0,10);

手機屏幕向下(z軸朝地)水平放置的時侯,(x,y,z)的值分別為(0,0,-10);

手機屏幕向左側放(x軸朝天)的時候,(x,y,z)的值分別為(10,0,0);

手機豎直(y軸朝天)向上的時候,(x,y,z)的值分別為(0,10,0);

其他的如此類推,規律就是:朝天的就是正數,朝地的就是負數。利用x,y,z三個值求三角函數,就可以精確檢測手機的運動狀態了。

 

接下來,用最短的代碼完成Android重力感應功能,程序效果就是在title上面輸出x,y,z的值。

Java代碼

package com.ray.test;   

import Android.app.Activity;   

import Android.os.Bundle;   

import Android.hardware.SensorManager;   

import Android.hardware.Sensor;   

import Android.hardware.SensorEventListener;   

import Android.hardware.SensorEvent;   

public class SensorTest extends Activity {   

private SensorManager sensorMgr;   

Sensor sensor = sensorMgr.getDefaultSensor
(Sensor.TYPE_ACCELEROMETER);   

private float x, y, z;   

protected void onCreate(Bundle savedInstanceState) {   

super.onCreate(savedInstanceState);   

sensorMgr = (SensorManager) 
getSystemService(SENSOR_SERVICE);   

SensorEventListener lsn = new SensorEventListener() {   

public void onSensorChanged(SensorEvent e) {   

x = e.values[SensorManager.DATA_X];   

y = e.values[SensorManager.DATA_Y];   

z = e.values[SensorManager.DATA_Z];   

setTitle("x="+(int)x+","+"y="+(int)y+","+"z="+(int)z);   

}   

public void onAccuracyChanged(Sensor s, int accuracy) {   

}   

};   

//注冊listener,第三個參數是檢測的精確度   

sensorMgr.registerListener(lsn, sensor, 
SensorManager.SENSOR_DELAY_GAME);   

}   

 

本文段:Android日記之2012/02/16——淺談Android重力感應

轉自:http://blog.csdn.net/zhuweijun/article/details/7265666

重力感應,也算是智能機和非智能機的區別之一了吧,Android設備中自然也能有這個功能。

       在Android中,使用重力感應功能需要使用SensorEventListener,其中有兩個方法, onSensorChanged和onAccuracyChanged,一般都是在onSensorChanged方法中做一些希望達到的效果處理(慚愧,才剛接觸這個重力感應,所以對這兩個方法也不是很了解)。重力感應是感應的一種方式,因此,我們還要用到感應檢測包Sensor。

       首先,我們要獲得一個SensorManager,SensorManager manager = (SensorManager) this.getSystemService(Context.SENSOR_SERVICE)。然后,再通過這個manager來獲得一個Sensor 的列表,List<Sensor> sensors = manager.getSensorList(Sensor.TYPE_ACCELEROMETER)。 Sensor.TYPE_ACCELEROMETER就是指加速度感應檢測,當然還有一些其他的感應檢測,這邊就沒必要都說一下了。

       我在做重力感應的時候,用的是manager.registerListener(listener, sensor, rate),這邊的sensor就是sensors中的一個Sensor,rate是指延遲時間。

       如果要取消這個重力感應的話,就manager.unregisterListener(listener)來取消注冊就行了。

public class SensorEventDemoActivity extends Activity implements SensorEventListener{

    private List<Sensor> sensors;

    private Sensor sensor;

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);

    }

   

    @Override

    protected void onResume() {

        super.onResume();

        SensorManager manager = (SensorManager) this.getSystemService(Context.SENSOR_SERVICE);

        sensors = manager.getSensorList(Sensor.TYPE_ACCELEROMETER);

       

        sensor = sensors.get(0);

       

        manager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_GAME);

    }

 

    @Override

    public void onSensorChanged(SensorEvent event) {

        Log.d("Sensor Demo", "do sensor");

    }

 

    @Override

    public void onAccuracyChanged(Sensor sensor, int accuracy) {

       

    }

}

       其實,代碼很簡單,主要就是要看在實際項目中如何運用了。

Android重力感應的相關實現方法就為大家介紹到這里。

 

本文段:Android 小球重力感應實現(三)
http://www.eoeandroid.com/thread-98312-1-1.html
import android.app.Activity;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.Window;
import android.view.WindowManager;
import android.view.SurfaceHolder.Callback;

public class SurfaceViewAcitvity extends Activity {

MyView mAnimView = null;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

// 全屏顯示窗口
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);

//強制橫屏
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

// 顯示自定義的游戲View
mAnimView = new MyView(this);
setContentView(mAnimView);
}

public class MyView extends SurfaceView implements Callback,Runnable ,SensorEventListener{
/**每50幀刷新一次屏幕**/
public static final int TIME_IN_FRAME = 50;
/** 游戲畫筆 **/
Paint mPaint = null;
Paint mTextPaint = null;
SurfaceHolder mSurfaceHolder = null;
/** 控制游戲更新循環 **/
boolean mRunning = false;
/** 游戲畫布 **/
Canvas mCanvas = null;
/**控制游戲循環**/
boolean mIsRunning = false;
/**SensorManager管理器**/
private SensorManager mSensorMgr = null;
Sensor mSensor = null;
/**手機屏幕寬高**/
int mScreenWidth = 0;
int mScreenHeight = 0;
/**小球資源文件越界區域**/
private int mScreenBallWidth = 0;
private int mScreenBallHeight = 0;
/**游戲背景文件**/
private Bitmap mbitmapBg;
/**小球資源文件**/
private Bitmap mbitmapBall;
/**小球的坐標位置**/
private float mPosX = 200;
private float mPosY = 0;
/**重力感應X軸 Y軸 Z軸的重力值**/
private float mGX = 0;
private float mGY = 0;
private float mGZ = 0;

public MyView(Context context) {
super(context);
/** 設置當前View擁有控制焦點 **/
this.setFocusable(true);

/** 設置當前View擁有觸摸事件 **/
this.setFocusableInTouchMode(true);

/** 拿到SurfaceHolder對象 **/
mSurfaceHolder = this.getHolder();

/** 將mSurfaceHolder添加到Callback回調函數中 **/
mSurfaceHolder.addCallback(this);

/** 創建畫布 **/
mCanvas = new Canvas();

/** 創建曲線畫筆 **/
mPaint = new Paint();
mPaint.setColor(Color.WHITE);

/**加載小球資源**/
mbitmapBall = BitmapFactory.decodeResource(this.getResources(), R.drawable.ball);

/**加載游戲背景**/
mbitmapBg = BitmapFactory.decodeResource(this.getResources(), R.drawable.bg);

/**得到SensorManager對象**/
mSensorMgr = (SensorManager) getSystemService(SENSOR_SERVICE);

mSensor = mSensorMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);

// 注冊listener,第三個參數是檢測的精確度
//SENSOR_DELAY_FASTEST 最靈敏 因為太快了沒必要使用
//SENSOR_DELAY_GAME 游戲開發中使用
//SENSOR_DELAY_NORMAL 正常速度
//SENSOR_DELAY_UI 最慢的速度

mSensorMgr.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_GAME);

}


private void Draw() {

/**繪制游戲背景**/
mCanvas.drawBitmap(mbitmapBg,0,0, mPaint);
/**繪制小球**/
mCanvas.drawBitmap(mbitmapBall, mPosX,mPosY, mPaint);
/**X軸 Y軸 Z軸的重力值**/
mCanvas.drawText("X軸重力值 :" + mGX, 0, 20, mPaint);
mCanvas.drawText("Y軸重力值 :" + mGY, 0, 40, mPaint);
mCanvas.drawText("Z軸重力值 :" + mGZ, 0, 60, mPaint);
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {

}


@Override

public void surfaceCreated(SurfaceHolder holder) {

/**開始游戲主循環線程**/

mIsRunning = true;

new Thread(this).start();

/**得到當前屏幕寬高**/

mScreenWidth = this.getWidth();

mScreenHeight = this.getHeight();

/**得到小球越界區域**/

mScreenBallWidth = mScreenWidth - mbitmapBall.getWidth();

mScreenBallHeight = mScreenHeight - mbitmapBall.getHeight();

}

@Override

public void surfaceDestroyed(SurfaceHolder holder) {

mIsRunning = false;

}

@Override

public void run() {

while (mIsRunning) {

/** 取得更新游戲之前的時間 **/
long startTime = System.currentTimeMillis();
/** 在這里加上線程安全鎖 **/
synchronized (mSurfaceHolder) {

/** 拿到當前畫布 然后鎖定 **/

mCanvas = mSurfaceHolder.lockCanvas();

Draw();

/** 繪制結束后解鎖顯示在屏幕上 **/

mSurfaceHolder.unlockCanvasAndPost(mCanvas);

}

/** 取得更新游戲結束的時間 **/

long endTime = System.currentTimeMillis();

/** 計算出游戲一次更新的毫秒數 **/

int diffTime = (int) (endTime - startTime);

/** 確保每次更新時間為50幀 **/

while (diffTime <= TIME_IN_FRAME) {

diffTime = (int) (System.currentTimeMillis() - startTime);

/** 線程等待 **/

Thread.yield();

}

}

}

@Override

public void onAccuracyChanged(Sensor arg0, int arg1) {
// TODO Auto-generated method stub

}

@Override

public void onSensorChanged(SensorEvent event) {

mGX = event.values[SensorManager.DATA_X];

mGY= event.values[SensorManager.DATA_Y];

mGZ = event.values[SensorManager.DATA_Z];

//這里乘以2是為了讓小球移動的更快

mPosX -= mGX * 2;

mPosY += mGY * 2;

//檢測小球是否超出邊界

if (mPosX < 0) {

mPosX = 0;

} else if (mPosX > mScreenBallWidth) {

mPosX = mScreenBallWidth;

}

if (mPosY < 0) {

mPosY = 0;

} else if (mPosY > mScreenBallHeight) {

mPosY = mScreenBallHeight;

}
}
}
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM