首頁 收藏 QQ群
 網(wǎng)站導航

ZNDS智能電視網(wǎng) 推薦當貝市場

TV應用下載 / 資源分享區(qū)

軟件下載 | 游戲 | 討論 | 電視計算器

綜合交流 / 評測 / 活動區(qū)

交流區(qū) | 測硬件 | 網(wǎng)站活動 | Z幣中心

新手入門 / 進階 / 社區(qū)互助

新手 | 你問我答 | 免費刷機救磚 | ROM固件

查看: 12208|回復: 0
上一主題 下一主題
[教程]

Android游戲開發(fā)之小球重力感應實現(xiàn)(二十五)

[復制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
發(fā)表于 2013-8-28 16:19 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
41016Android游戲開發(fā)之小球重力感應實現(xiàn)   
     
重力感應主要是依靠手機的加速度傳感器(accelerometer)來實現(xiàn)   
   
        在Android的開發(fā)中一共有八種傳感器但是不一定每一款真機都支持這些傳感器。因為很多功能用戶根本不care的所以可能開發(fā)商會把某些功能屏蔽掉。還是得根據(jù)真機的實際情況來做開發(fā),今天我們主要來討論加速度傳感器的具體實現(xiàn)方式。   
   
   
   
傳感器名稱如下:   
   
加速度傳感器(accelerometer)   
陀螺儀傳感器(gyroscope)   
環(huán)境光照傳感器(light)   
磁力傳感器(magnetic field)   
方向傳感器(orientation)   
壓力傳感器(pressure)   
距離傳感器(proximity)   
溫度傳感器(temperature)   
   
   
   
   
   
1.SensorMannager傳感器管理對象   
   
手機中的所有傳感器都須要通過SensorMannager來訪問,調(diào)用getSystemService(SENSOR_SERVICE)方法就可以拿到當前手機的傳感器管理對象。   
  1. SensorManager mSensorMgr = (SensorManager) getSystemService(SENSOR_SERVICE);  
復制代碼
2.實現(xiàn)SensorEventListener接口   
   
       說道SensorEventListener接口就不得不說SensorListener接口。在Android1.5一下是通過實現(xiàn)SensorListener接口來捕獲 手機傳感器狀態(tài),但是在1.5以上如果實現(xiàn)這個接口系統(tǒng)會提示你這行代碼已經(jīng)過期。今天我們不討論SensorListener因為它已經(jīng)是過時的東西了。主要討論一下SensorEventListener接口。我們須要實現(xiàn)SensorEventListener這個接口 onSensorChanged(SensorEvent event)方法來捕獲手機傳感器的狀態(tài),拿到手機 X軸Y軸Z軸三個方向的重力分量,有了這三個方向的數(shù)據(jù)重力感應的原理我們就已經(jīng)學會了,簡單吧   
  1.         public void onSensorChanged(SensorEvent e) {        
               float x = e.values[SensorManager.DATA_X];           
               float y = e.values[SensorManager.DATA_Y];           
               float z = e.values[SensorManager.DATA_Z];         
            }   
復制代碼
如圖所示:上例代碼中 float x y z 3個方向的取值范圍是在 -10 到 10 之間,我向同學們說明一下 X軸 Y軸 Z軸 重力分量的含義。 這里須要注意的是坐標原點 向天空為正數(shù) 向地面為負數(shù) 剛好與編程時坐標是相反的。   
   
手機屏幕向左側(cè)方當X軸就朝向天空,垂直放置 這時候 Y 軸 與 Z軸沒有重力分量,因為X軸朝向天空所以它的重力分量則最大 。這時候X軸 Y軸 Z軸的重力分量的值分別為(10,0,0)   
   
手機屏幕向右側(cè)方當X軸就朝向地面,垂直放置 這時候 Y 軸 與 Z軸沒有重力分量,因為X軸朝向地面所以它的重力分量則最小 。這時候X軸 Y軸 Z軸的重力分量的值分別為(-10,0,0)   
   
手機屏幕垂直豎立放置方當Y軸就朝向天空,垂直放置 這時候 X 軸 與 Z軸沒有重力分量,因為Y軸朝向天空所以它的重力分量則最大 。這時候X軸 Y軸 Z軸的重力分量的值分別為(0,10,0)   
   
手機屏幕垂直豎立放置方當Y軸就朝向地面,垂直放置 這時候 X 軸 與 Z軸沒有重力分量,因為Y軸朝向地面所以它的重力分量則最小 。這時候X軸 Y軸 Z軸的重力分量的值分別為(0,-10,0)   
   
   
手機屏幕向上當Z軸就朝向天空,水平放置 這時候 X 軸與Y軸沒有重力分量,因為Z軸朝向天空所以它的重力分量則最大 。這時候X軸 Y軸 Z軸的重力分量的值分別為(0,0,10)   
   
手機屏幕向上當Z軸就朝向地面,水平放置 這時候 X 軸與Y軸沒有重力分量,因為Z軸朝向地面所以它的重力分量則最小 。這時候X軸 Y軸 Z軸的重力分量的值分別為(0,0,-10)   
   
因為這張圖片是在模擬器上截得,所以沒有重力感應它的三個方向的的重力分量都為0。   
   
     
3.注冊SensorEventListener   
   
   
         使用SensorMannager調(diào)用getDefaultSensor(Sensor.TYPE_ACCELEROMETER)方法拿到加速重力感應的Sensor對象。因為本章我們討論重力加速度傳感器所以參數(shù)為Sensor.TYPE_ACCELEROMETER,如果須要拿到其它的傳感器須要傳入對應的名稱。使用SensorMannager調(diào)用registerListener()方法來注冊,第三個參數(shù)是檢測的靈敏精確度根據(jù)不同的需求來選擇精準度,游戲開發(fā)建議使用  SensorManager.SENSOR_DELAY_GAME。   
  1.             mSensorMgr = (SensorManager) getSystemService(SENSOR_SERVICE);      
                mSensor = mSensorMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);      
                // 注冊listener,第三個參數(shù)是檢測的精確度     
                //SENSOR_DELAY_FASTEST 最靈敏 因為太快了沒必要使用   
                //SENSOR_DELAY_GAME    游戲開發(fā)中使用   
                //SENSOR_DELAY_NORMAL  正常速度   
                //SENSOR_DELAY_UI                最慢的速度   
                mSensorMgr.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_GAME);  
復制代碼
重力感應簡單速度計算的方式。 每次搖晃手機計算出 X軸 Y軸 Z軸的重力分量可以將它們記錄下來 然后每次搖晃的重力分量和之前的重力分量可以做一個對比 利用差值和時間就可以計算出他們的移動速度。(下面這段代碼是我之前的博文中摘錄過來的,因為那篇寫的不是很好所以在這一篇中我詳細總結(jié)一下)   
  1.     private SensorManager sensorMgr;      
        Sensor sensor = sensorMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);        
             
         //保存上一次 x y z 的坐標     
         float bx = 0;     
         float by = 0;     
         float bz = 0;     
         long btime = 0;//這一次的時間      
         sensorMgr = (SensorManager) getSystemService(SENSOR_SERVICE);        
            SensorEventListener lsn = new SensorEventListener() {        
                public void onSensorChanged(SensorEvent e) {        
                   float x = e.values[SensorManager.DATA_X];           
                   float y = e.values[SensorManager.DATA_Y];           
                   float z = e.values[SensorManager.DATA_Z];      
                   //在這里我們可以計算出 X Y Z的數(shù)值 下面我們就可以根據(jù)這個數(shù)值來計算搖晃的速度了      
                   //我想大家應該都知道計算速度的公事 速度 = 路程/時間     
                   //X軸的速度     
                   float speadX = (x - bx) / (System.currentTimeMillis() - btime);      
                   //y軸的速度     
                   float speadY = (y - by) / (System.currentTimeMillis() - btime);      
                   //z軸的速度     
                   float speadZ = (z - bz) / (System.currentTimeMillis() - btime);      
                   //這樣簡單的速度就可以計算出來 如果你想計算加速度 也可以 在運動學里,加速度a與速度,     
                   //位移都有關(guān)系:Vt=V0+at,S=V0*t+1/2at^2, S=(Vt^2-V0^2)/(2a),根據(jù)這些信息也可以求解a。      
                   //這里就不詳細介紹了 公事 應該初中物理課老師就教了呵呵~~     
             
                   bx = x;     
                   by = y;     
                   bz = z;     
             
                   btime = System.currentTimeMillis();     
             
             
                }        
                        
                public void onAccuracyChanged(Sensor s, int accuracy) {        
                }        
            };        
            // 注冊listener,第三個參數(shù)是檢測的精確度     
            sensorMgr.registerListener(lsn, sensor, SensorManager.SENSOR_DELAY_GAME);  
復制代碼
真機上的效果圖   
   
     
下面給出這個DEMO小球重力感應的完整代碼   
  1. 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;   
       
            /** 控制游戲更新循環(huán) **/   
            boolean mRunning = false;   
       
            /** 游戲畫布 **/   
            Canvas mCanvas = null;   
       
            /**控制游戲循環(huán)**/   
            boolean mIsRunning = false;   
               
            /**SensorManager管理器**/   
            private SensorManager mSensorMgr = null;      
            Sensor mSensor = null;      
               
            /**手機屏幕寬高**/   
            int mScreenWidth = 0;   
            int mScreenHeight = 0;   
               
            /**小球資源文件越界區(qū)域**/   
            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);   
                /** 設(shè)置當前View擁有控制焦點 **/   
                this.setFocusable(true);   
                /** 設(shè)置當前View擁有觸摸事件 **/   
                this.setFocusableInTouchMode(true);   
                /** 拿到SurfaceHolder對象 **/   
                mSurfaceHolder = this.getHolder();   
                /** 將mSurfaceHolder添加到Callback回調(diào)函數(shù)中 **/   
                mSurfaceHolder.addCallback(this);   
                /** 創(chuàng)建畫布 **/   
                mCanvas = new Canvas();   
                /** 創(chuàng)建曲線畫筆 **/   
                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,第三個參數(shù)是檢測的精確度     
                //SENSOR_DELAY_FASTEST 最靈敏 因為太快了沒必要使用   
                //SENSOR_DELAY_GAME    游戲開發(fā)中使用   
                //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) {   
                /**開始游戲主循環(huán)線程**/   
                mIsRunning = true;   
                new Thread(this).start();   
                /**得到當前屏幕寬高**/   
                mScreenWidth = this.getWidth();   
                mScreenHeight = this.getHeight();   
                   
                /**得到小球越界區(qū)域**/   
                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();   
                        /** 繪制結(jié)束后解鎖顯示在屏幕上 **/   
                        mSurfaceHolder.unlockCanvasAndPost(mCanvas);   
                    }   
       
                    /** 取得更新游戲結(jié)束的時間 **/   
                    long endTime = System.currentTimeMillis();   
       
                    /** 計算出游戲一次更新的毫秒數(shù) **/   
                    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;   
                }   
            }   
        }   
    }
復制代碼
老規(guī)矩每篇文章都會附帶源代碼,最后如果你還是覺得我寫的不夠詳細 看的不夠爽 不要緊我把源代碼的下載地址貼出來 歡迎大家一起討論學習   
第十五講重力感應.rar(1.65 MB, 下載次數(shù): 2300)[/I]2011-9-3 01:00 上傳點擊文件名   下載積分: 下載豆 -2

上一篇:第十六講:菜單 Android Menu
下一篇:第十四講:Service入門指南
您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

Archiver|新帖|標簽|軟件|Sitemap|ZNDS智能電視網(wǎng) ( 蘇ICP備2023012627號 )

網(wǎng)絡(luò)信息服務信用承諾書 | 增值電信業(yè)務經(jīng)營許可證:蘇B2-20221768 丨 蘇公網(wǎng)安備 32011402011373號

GMT+8, 2024-12-22 17:09 , Processed in 0.068962 second(s), 16 queries , Redis On.

Powered by Discuz!

監(jiān)督舉報:report#znds.com (請將#替換為@)

© 2007-2024 ZNDS.Com

快速回復 返回頂部 返回列表