Android游戏开发之小球重力感应实现

重力感应主要是依靠手机的加速度传感器(accelerometer)来实现

在Android的开发中一共有八种传感器但是不一定每一款真机都支持这些传感器。因为很多功能用户根本不care的所以可能开发商会把某些功能屏蔽掉。还是得根据真机的实际情况来做开发,今天我们主要来讨论加速度传感器的具体实现方式。

传感器名称如下:

加速度传感器(accelerometer)
陀螺仪传感器(gyroscope)
环境光照传感器(light)
磁力传感器(magnetic field)
方向传感器(orientation)
压力传感器(pressure)
距离传感器(proximity)
温度传感器(temperature)

1.SensorMannager传感器管理对象

手机中的所有传感器都须要通过SensorMannager来访问,调用getSystemService(SENSOR_SERVICE)方法就可以拿到当前手机的传感器管理对象。

  1. SensorManager mSensorMgr = (SensorManager) getSystemService(SENSOR_SERVICE);

复制代码

2.实现SensorEventListener接口

说道SensorEventListener接口就不得不说SensorListener接口。在Android1.5一下是通过实现SensorListener接口来捕获 手机传感器状态,但是在1.5以上如果实现这个接口系统会提示你这行代码已经过期。今天我们不讨论SensorListener因为它已经是过时的东西了。主要讨论一下SensorEventListener接口。我们须要实现SensorEventListener这个接口 onSensorChanged(SensorEvent event)方法来捕获手机传感器的状态,拿到手机 X轴Y轴Z轴三个方向的重力分量,有了这三个方向的数据重力感应的原理我们就已经学会了,简单吧

  1. public void onSensorChanged(SensorEvent e) {
  2. float x = e.values[SensorManager.DATA_X];
  3. float y = e.values[SensorManager.DATA_Y];
  4. float z = e.values[SensorManager.DATA_Z];
  5. }

复制代码

如图所示:上例代码中 float x y z 3个方向的取值范围是在 -10 到 10 之间,我向同学们说明一下 X轴 Y轴 Z轴 重力分量的含义。 这里须要注意的是坐标原点 向天空为正数 向地面为负数 刚好与编程时坐标是相反的。

手机屏幕向左侧方当X轴就朝向天空,垂直放置 这时候 Y 轴 与 Z轴没有重力分量,因为X轴朝向天空所以它的重力分量则最大 。这时候X轴 Y轴 Z轴的重力分量的值分别为(10,0,0)

手机屏幕向右侧方当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调用getDefaultSensor(Sensor.TYPE_ACCELEROMETER)方法拿到加速重力感应的Sensor对象。因为本章我们讨论重力加速度传感器所以参数为Sensor.TYPE_ACCELEROMETER,如果须要拿到其它的传感器须要传入对应的名称。使用SensorMannager调用registerListener()方法来注册,第三个参数是检测的灵敏精确度根据不同的需求来选择精准度,游戏开发建议使用  SensorManager.SENSOR_DELAY_GAME。

  1. mSensorMgr = (SensorManager) getSystemService(SENSOR_SERVICE);
  2. mSensor = mSensorMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
  3. // 注册listener,第三个参数是检测的精确度
  4. //SENSOR_DELAY_FASTEST 最灵敏 因为太快了没必要使用
  5. //SENSOR_DELAY_GAME    游戏开发中使用
  6. //SENSOR_DELAY_NORMAL  正常速度
  7. //SENSOR_DELAY_UI                最慢的速度
  8. mSensorMgr.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_GAME);

复制代码

重力感应简单速度计算的方式。 每次摇晃手机计算出 X轴 Y轴 Z轴的重力分量可以将它们记录下来 然后每次摇晃的重力分量和之前的重力分量可以做一个对比 利用差值和时间就可以计算出他们的移动速度。(下面这段代码是我之前的博文中摘录过来的,因为那篇写的不是很好所以在这一篇中我详细总结一下)

  1. private SensorManager sensorMgr;
  2. Sensor sensor = sensorMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
  3. //保存上一次 x y z 的坐标
  4. float bx = 0;
  5. float by = 0;
  6. float bz = 0;
  7. long btime = 0;//这一次的时间
  8. sensorMgr = (SensorManager) getSystemService(SENSOR_SERVICE);
  9. SensorEventListener lsn = new SensorEventListener() {
  10. public void onSensorChanged(SensorEvent e) {
  11. float x = e.values[SensorManager.DATA_X];
  12. float y = e.values[SensorManager.DATA_Y];
  13. float z = e.values[SensorManager.DATA_Z];
  14. //在这里我们可以计算出 X Y Z的数值 下面我们就可以根据这个数值来计算摇晃的速度了
  15. //我想大家应该都知道计算速度的公事 速度 = 路程/时间
  16. //X轴的速度
  17. float speadX = (x – bx) / (System.currentTimeMillis() – btime);
  18. //y轴的速度
  19. float speadY = (y – by) / (System.currentTimeMillis() – btime);
  20. //z轴的速度
  21. float speadZ = (z – bz) / (System.currentTimeMillis() – btime);
  22. //这样简单的速度就可以计算出来 如果你想计算加速度 也可以 在运动学里,加速度a与速度,
  23. //位移都有关系:Vt=V0+at,S=V0*t+1/2at^2, S=(Vt^2-V0^2)/(2a),根据这些信息也可以求解a。
  24. //这里就不详细介绍了 公事 应该初中物理课老师就教了呵呵~~
  25. bx = x;
  26. by = y;
  27. bz = z;
  28. btime = System.currentTimeMillis();
  29. }
  30. public void onAccuracyChanged(Sensor s, int accuracy) {
  31. }
  32. };
  33. // 注册listener,第三个参数是检测的精确度
  34. sensorMgr.registerListener(lsn, sensor, SensorManager.SENSOR_DELAY_GAME);

复制代码

真机上的效果图

下面给出这个DEMO小球重力感应的完整代码

  1. import android.app.Activity;
  2. import android.content.Context;
  3. import android.content.pm.ActivityInfo;
  4. import android.graphics.Bitmap;
  5. import android.graphics.BitmapFactory;
  6. import android.graphics.Canvas;
  7. import android.graphics.Color;
  8. import android.graphics.Paint;
  9. import android.hardware.Sensor;
  10. import android.hardware.SensorEvent;
  11. import android.hardware.SensorEventListener;
  12. import android.hardware.SensorManager;
  13. import android.os.Bundle;
  14. import android.view.SurfaceHolder;
  15. import android.view.SurfaceView;
  16. import android.view.Window;
  17. import android.view.WindowManager;
  18. import android.view.SurfaceHolder.Callback;
  19. public class SurfaceViewAcitvity extends Activity {
  20. MyView mAnimView = null;
  21. @Override
  22. public void onCreate(Bundle savedInstanceState) {
  23. super.onCreate(savedInstanceState);
  24. // 全屏显示窗口
  25. requestWindowFeature(Window.FEATURE_NO_TITLE);
  26. getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
  27. WindowManager.LayoutParams.FLAG_FULLSCREEN);
  28. //强制横屏
  29. setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
  30. // 显示自定义的游戏View
  31. mAnimView = new MyView(this);
  32. setContentView(mAnimView);
  33. }
  34. public class MyView extends SurfaceView implements Callback,Runnable ,SensorEventListener{
  35. /**每50帧刷新一次屏幕**/
  36. public static final int TIME_IN_FRAME = 50;
  37. /** 游戏画笔 **/
  38. Paint mPaint = null;
  39. Paint mTextPaint = null;
  40. SurfaceHolder mSurfaceHolder = null;
  41. /** 控制游戏更新循环 **/
  42. boolean mRunning = false;
  43. /** 游戏画布 **/
  44. Canvas mCanvas = null;
  45. /**控制游戏循环**/
  46. boolean mIsRunning = false;
  47. /**SensorManager管理器**/
  48. private SensorManager mSensorMgr = null;
  49. Sensor mSensor = null;
  50. /**手机屏幕宽高**/
  51. int mScreenWidth = 0;
  52. int mScreenHeight = 0;
  53. /**小球资源文件越界区域**/
  54. private int mScreenBallWidth = 0;
  55. private int mScreenBallHeight = 0;
  56. /**游戏背景文件**/
  57. private Bitmap mbitmapBg;
  58. /**小球资源文件**/
  59. private Bitmap mbitmapBall;
  60. /**小球的坐标位置**/
  61. private float mPosX = 200;
  62. private float mPosY = 0;
  63. /**重力感应X轴 Y轴 Z轴的重力值**/
  64. private float mGX = 0;
  65. private float mGY = 0;
  66. private float mGZ = 0;
  67. public MyView(Context context) {
  68. super(context);
  69. /** 设置当前View拥有控制焦点 **/
  70. this.setFocusable(true);
  71. /** 设置当前View拥有触摸事件 **/
  72. this.setFocusableInTouchMode(true);
  73. /** 拿到SurfaceHolder对象 **/
  74. mSurfaceHolder = this.getHolder();
  75. /** 将mSurfaceHolder添加到Callback回调函数中 **/
  76. mSurfaceHolder.addCallback(this);
  77. /** 创建画布 **/
  78. mCanvas = new Canvas();
  79. /** 创建曲线画笔 **/
  80. mPaint = new Paint();
  81. mPaint.setColor(Color.WHITE);
  82. /**加载小球资源**/
  83. mbitmapBall = BitmapFactory.decodeResource(this.getResources(), R.drawable.ball);
  84. /**加载游戏背景**/
  85. mbitmapBg = BitmapFactory.decodeResource(this.getResources(), R.drawable.bg);
  86. /**得到SensorManager对象**/
  87. mSensorMgr = (SensorManager) getSystemService(SENSOR_SERVICE);
  88. mSensor = mSensorMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
  89. // 注册listener,第三个参数是检测的精确度
  90. //SENSOR_DELAY_FASTEST 最灵敏 因为太快了没必要使用
  91. //SENSOR_DELAY_GAME    游戏开发中使用
  92. //SENSOR_DELAY_NORMAL  正常速度
  93. //SENSOR_DELAY_UI                最慢的速度
  94. mSensorMgr.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_GAME);
  95. }
  96. private void Draw() {
  97. /**绘制游戏背景**/
  98. mCanvas.drawBitmap(mbitmapBg,0,0, mPaint);
  99. /**绘制小球**/
  100. mCanvas.drawBitmap(mbitmapBall, mPosX,mPosY, mPaint);
  101. /**X轴 Y轴 Z轴的重力值**/
  102. mCanvas.drawText(“X轴重力值 :” + mGX, 0, 20, mPaint);
  103. mCanvas.drawText(“Y轴重力值 :” + mGY, 0, 40, mPaint);
  104. mCanvas.drawText(“Z轴重力值 :” + mGZ, 0, 60, mPaint);
  105. }
  106. @Override
  107. public void surfaceChanged(SurfaceHolder holder, int format, int width,
  108. int height) {
  109. }
  110. @Override
  111. public void surfaceCreated(SurfaceHolder holder) {
  112. /**开始游戏主循环线程**/
  113. mIsRunning = true;
  114. new Thread(this).start();
  115. /**得到当前屏幕宽高**/
  116. mScreenWidth = this.getWidth();
  117. mScreenHeight = this.getHeight();
  118. /**得到小球越界区域**/
  119. mScreenBallWidth = mScreenWidth – mbitmapBall.getWidth();
  120. mScreenBallHeight = mScreenHeight – mbitmapBall.getHeight();
  121. }
  122. @Override
  123. public void surfaceDestroyed(SurfaceHolder holder) {
  124. mIsRunning = false;
  125. }
  126. @Override
  127. public void run() {
  128. while (mIsRunning) {
  129. /** 取得更新游戏之前的时间 **/
  130. long startTime = System.currentTimeMillis();
  131. /** 在这里加上线程安全锁 **/
  132. synchronized (mSurfaceHolder) {
  133. /** 拿到当前画布 然后锁定 **/
  134. mCanvas = mSurfaceHolder.lockCanvas();
  135. Draw();
  136. /** 绘制结束后解锁显示在屏幕上 **/
  137. mSurfaceHolder.unlockCanvasAndPost(mCanvas);
  138. }
  139. /** 取得更新游戏结束的时间 **/
  140. long endTime = System.currentTimeMillis();
  141. /** 计算出游戏一次更新的毫秒数 **/
  142. int diffTime = (int) (endTime – startTime);
  143. /** 确保每次更新时间为50帧 **/
  144. while (diffTime <= TIME_IN_FRAME) {
  145. diffTime = (int) (System.currentTimeMillis() – startTime);
  146. /** 线程等待 **/
  147. Thread.yield();
  148. }
  149. }
  150. }
  151. @Override
  152. public void onAccuracyChanged(Sensor arg0, int arg1) {
  153. // TODO Auto-generated method stub
  154. }
  155. @Override
  156. public void onSensorChanged(SensorEvent event) {
  157. mGX = event.values[SensorManager.DATA_X];
  158. mGY= event.values[SensorManager.DATA_Y];
  159. mGZ = event.values[SensorManager.DATA_Z];
  160. //这里乘以2是为了让小球移动的更快
  161. mPosX -= mGX * 2;
  162. mPosY += mGY * 2;
  163. //检测小球是否超出边界
  164. if (mPosX < 0) {
  165. mPosX = 0;
  166. } else if (mPosX > mScreenBallWidth) {
  167. mPosX = mScreenBallWidth;
  168. }
  169. if (mPosY < 0) {
  170. mPosY = 0;
  171. } else if (mPosY > mScreenBallHeight) {
  172. mPosY = mScreenBallHeight;
  173. }
  174. }
  175. }
  176. }

Android游戏开发之小球重力感应实现相关推荐

  1. Android游戏开发Android软件开发【教程三十篇】

    Android软件开发之发送短信与系统短信库解析(三十)  New Android软件开发之获取通讯录联系人信息(二十九)  New Android软件开发之PreferenceActivity中的组 ...

  2. Unity3D 游戏引擎之平面小球重力感应详解【转】

    http://blog.csdn.net/xys289187120/article/details/6969333       手机重力感应应该对大多数开发者并不陌生,在新一代智能手机Android  ...

  3. (转载)Android游戏开发之旅一 长按Button原理

    (转载)http://www.android123.com.cn/androidkaifa/538.html 作者: Android开发网原创 时间: 2010-06-22 今天Android123开 ...

  4. Android游戏开发的入门实例

         在Android系统上开发游戏是Android开发学习者所向往的,有成就感也有乐趣,还能取得经济上的报酬.那怎样开发Android游戏呢?下面介绍一个简单的入门实例.        一.创建 ...

  5. Android游戏开发大全

    查看书籍详细信息: Android游戏开发大全 编辑推荐 帮助读者掌握Android游戏项目的开发流程 和项目驱动的好书! 内容简介 <Android游戏开发大全>以Android手机游戏 ...

  6. Android游戏开发教程:手教你写跳跃类游戏

    Android游戏开发教程:手教你写跳跃类游戏 package jumpball.game; import android.app.Activity; import android.os.Bundle ...

  7. Android游戏开发十日通(7)- 开发一个双人游戏

    提要 游戏需要分享才能获得快乐,想想你以前玩过的那些游戏,那些会是真正地存在你婶婶的脑海里?是独自一人躲在被窝里酣战PSP,还是和哥们在网吧一起开黑?是一个人单刷迅龙三连,还是和朋友联机怒刷黄黑龙? ...

  8. 【Android游戏开发二十七】讲解游戏开发与项目下的hdpi 、mdpi与ldpi资源文件夹以及游戏高清版本的设置...

    今天一个开发者问到我为什么游戏开发要删除项目下的hdpi.mdpi和ldpi文件夹:下面详细给大家解答一下: 首先童鞋们如果看过我写的<[Android游戏开发二十一]Android os设备谎 ...

  9. 【ANDROID游戏开发十六】ANDROID GESTURE之【触摸屏手势识别】操作!利用触摸屏手势实现一个简单切换图片的功能!...

    本站文章均为 李华明Himi 原创,转载务必在明显处注明: 转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/android-game/337.html - ...

  10. 《Android游戏开发详解》——第1章,第1.6节函数(在Java中称为“方法”更好)...

    本节书摘来自异步社区<Android游戏开发详解>一书中的第1章,第1.6节函数(在Java中称为"方法"更好),作者 [美]Jonathan S. Harbour,更 ...

最新文章

  1. 对话推荐算法研究综述
  2. webpack 原理图_webpack打包原理
  3. 排球比赛计分规则功能说明书
  4. 认认真真推荐几个机器学习和Python类的公众号
  5. WPF Binding
  6. Redis 通过 RDB 方式进行数据备份与还原
  7. Datepicker
  8. -1-3 java集合框架基础 java集合体系结构 Collection 常用java集合框架 如何选择集合 迭代器 泛型 通配符概念 Properties 集合 迭代器...
  9. 附录-SpringFactoriesLoader
  10. linux下磁盘分区方法详解
  11. qq空间留言板php,qq留言板留言关心的话 qq空间留言板签名档图片
  12. 新物种爆炸:认知升级时代的新商业思维
  13. 2016面试总结,面试宝典有木有
  14. P、NP、NPC问题
  15. Android中的热修复
  16. TensorFlow基础学习
  17. 全球及中国标签印刷行业十四五发展形势与需求规模预测报告2022版
  18. 做了一款 TCP/IP 调试工具
  19. 图形学笔记(三)画一个彩色的三角形
  20. FileIterator

热门文章

  1. Window Server 2008 概述
  2. logstash之output插件-输出数据到控制台、file文件、elasticsearch、redis
  3. excel打不开html超链接,excel超链接打不开怎么回事 excel超链接的详细制作教程
  4. 中国移动短信中心服务中心号码一览表
  5. 何为裂变?上百个裂变营销活动让我揭开了其神秘面目!
  6. 最新十大透支健康行业(2019年版)
  7. 【题解 图论建模】 航空管制
  8. 二维码在Access中的使用
  9. python贪吃蛇游戏手把手教学 第一课
  10. P5514 [MtOI2019]永夜的报应