好久没更新博客了,今天来谈谈android小游戏———重力感应,一般在游戏里运用的比较多,比如这类游戏有:神庙逃亡,极品飞车,平衡球,三围重力迷宫,重力赛车等。
首先什么是重力感应,重力感应是指现在手机中常用的一个器件,及加速度传感器。当手机静止时,加速度就是重力,所以一般也叫做重力传感器。这个硬件可以感应加速度的变化,转化为数据提供给系统。还有一种传感器是陀螺仪,检测围绕某轴的旋转动作,是利用有质量的刚体的在做旋转或震动时,如果发生垂直于旋转或震动轴的旋转,因为惯性会产生垂直于旋转或震动轴的柯氏力(G-sensor是加速度力)。陀螺仪必定会分x,y,z轴。两者的区别是前者,内部的测量对象是加速度力;后者,内部测量柯氏力。前者告诉你物体动没动,往哪个方向动了?后者告诉你动起来的物体转了吗?怎么转的,转了多少度? 多轴的的G-Sensor也可以检测到物体切向于竖直方向的转动,但角度判断起来很困难。
那么手机重力感应的原理是什么?(下面)
——通过对力敏感的传感器,感受手机在变换姿势时,重心的变化,使手机光标变化位置从而实现选择的功能。 手机重力感应技术:利用压电效应实现,简单来说是是测量内部一片重物(重物和压电片做成一体)重力正交两个方向的分力大小,来判定水平方向。 手机重力感应指的是手机内置重力摇杆芯片,支持摇晃切换所需的界面和功能,甩歌甩屏,翻转静音,甩动切换视频等,是一种非常具有使用乐趣的功能。
下面看一个简单的小游戏(范例)效果图:APK下载地址:http://download.csdn.net/detail/liuyang1990i/7448211
代码如下:(下为部分Java代码)
startActivity.java文件
package cn.m15.xys;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class startActivity extends Activity {
Context mContext = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mContext = this;
/**进入游戏世界 - 小球移动**/
Button botton0 = (Button)findViewById(R.id.button0);
botton0.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
Intent intent = new Intent(mContext,SurfaceViewAcitvity.class);
startActivity(intent);
}
});
}
}
SurfaceViewAcitvity.java文件
package cn.m15.xys;
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 = 30;
/** 游戏画笔 **/
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);
/**得到Sens
* orManager对象**/
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;
}
}
}
}