android平衡球的原理是什么,Android加速感应器开发平衡球代码解析 Android开发技术...

Android加速感应器开发平衡球代码解析 Android开发技术

2013 年 5 月 2 日

如何使用Android的加速感应器开发一个控制铁球滚动的游戏:

public class AccelerometerPlayActivity extends Activity {

private SimulationView mSimulationView; //游戏主显示View

private SensorManager mSensorManager; //感应器管理类

private PowerManager mPowerManager; //电源控制,比如防锁屏

private WindowManager mWindowManager;

private Display mDisplay;

private WakeLock mWakeLock;

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE); // 实例化感应器管理类

mPowerManager = (PowerManager) getSystemService(POWER_SERVICE);

mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);

mDisplay = mWindowManager.getDefaultDisplay(); //为了获取屏幕的DPI级别

mWakeLock = mPowerManager.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, getClass()

.getName()); //处理屏幕防止锁屏

mSimulationView = new SimulationView(this);

setContentView(mSimulationView); //设置游戏View

}

@Override

protected void onResume() {

super.onResume();

mWakeLock.acquire();  //恢复时解除锁屏

mSimulationView.startSimulation();

}

@Override

protected void onPause() {

super.onPause();

mSimulationView.stopSimulation(); //Activity切出去时停止画面更新

mWakeLock.release();

}

class SimulationView extends View implements SensorEventListener {

private static final float sBallDiameter = 0.004f; //设置小球直径

private static final float sBallDiameter2 = sBallDiameter * sBallDiameter;

private static final float sFriction = 0.1f; //摩擦系数

private Sensor mAccelerometer;

private long mLastT;

private float mLastDeltaT;

private float mXDpi;

private float mYDpi;

private float mMetersToPixelsX;

private float mMetersToPixelsY;

private Bitmap mBitmap; //小球素材

private Bitmap mWood; //背景使用木头

private float mXOrigin;

private float mYOrigin;

private float mSensorX;

private float mSensorY;

private long mSensorTimeStamp;

private long mCpuTimeStamp;

private float mHorizontalBound;

private float mVerticalBound;

private final ParticleSystem mParticleSystem = new ParticleSystem();

class Particle {

private float mPosX;

private float mPosY;

private float mAccelX;

private float mAccelY;

private float mLastPosX;

private float mLastPosY;

private float mOneMinusFriction;

Particle() {

final float r = ((float) Math.random() – 0.5f) * 0.2f;

mOneMinusFriction = 1.0f – sFriction + r;

}

public void computePhysics(float sx, float sy, float dT, float dTC) {

final float m = 1000.0f; // mass of our virtual object

final float gx = -sx * m;

final float gy = -sy * m;

final float invm = 1.0f / m;

final float ax = gx * invm;

final float ay = gy * invm;

final float dTdT = dT * dT;

final float x = mPosX + mOneMinusFriction * dTC * (mPosX – mLastPosX) + mAccelX

* dTdT;

final float y = mPosY + mOneMinusFriction * dTC * (mPosY – mLastPosY) + mAccelY

* dTdT;

mLastPosX = mPosX;

mLastPosY = mPosY;

mPosX = x;

mPosY = y;

mAccelX = ax;

mAccelY = ay;

}

public void resolveCollisionWithBounds() {

final float xmax = mHorizontalBound;

final float ymax = mVerticalBound;

final float x = mPosX;

final float y = mPosY;

if (x > xmax) {

mPosX = xmax;

} else if (x < -xmax) {

mPosX = -xmax;

}

if (y > ymax) {

mPosY = ymax;

} else if (y < -ymax) {

mPosY = -ymax;

}

}

}

class ParticleSystem { //收集取样感应器数据来绘制小球位置

static final int NUM_PARTICLES = 15;

private Particle mBalls[] = new Particle[NUM_PARTICLES];

ParticleSystem() {

for (int i = 0; i < mBalls.length; i++) {

mBalls[i] = new Particle();

}

}

private void updatePositions(float sx, float sy, long timestamp) {

final long t = timestamp;

if (mLastT != 0) {

final float dT = (float) (t – mLastT) * (1.0f / 1000000000.0f);

if (mLastDeltaT != 0) {

final float dTC = dT / mLastDeltaT;

final int count = mBalls.length;

for (int i = 0; i < count; i++) {

Particle ball = mBalls[i];

ball.computePhysics(sx, sy, dT, dTC);

}

}

mLastDeltaT = dT;

}

mLastT = t;

}

public void update(float sx, float sy, long now) {

updatePositions(sx, sy, now);

final int NUM_MAX_ITERATIONS = 10;

boolean more = true;

final int count = mBalls.length;

for (int k = 0; k < NUM_MAX_ITERATIONS && more; k++) {

more = false;

for (int i = 0; i < count; i++) {

Particle curr = mBalls[i];

for (int j = i + 1; j < count; j++) {

Particle ball = mBalls[j];

float dx = ball.mPosX – curr.mPosX;

float dy = ball.mPosY – curr.mPosY;

float dd = dx * dx + dy * dy;

// Check for collisions

if (dd <= sBallDiameter2) {

dx += ((float) Math.random() – 0.5f) * 0.0001f;

dy += ((float) Math.random() – 0.5f) * 0.0001f;

dd = dx * dx + dy * dy;

// simulate the spring

final float d = (float) Math.sqrt(dd);

final float c = (0.5f * (sBallDiameter – d)) / d;

curr.mPosX -= dx * c;

curr.mPosY -= dy * c;

ball.mPosX += dx * c;

ball.mPosY += dy * c;

more = true;

}

}

curr.resolveCollisionWithBounds();

}

}

}

public int getParticleCount() {

return mBalls.length;

}

public float getPosX(int i) {

return mBalls[i].mPosX;

}

public float getPosY(int i) {

return mBalls[i].mPosY;

}

}

public void startSimulation() {

mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_UI);

}

public void stopSimulation() { //暂停时主要是停掉感应器

mSensorManager.unregisterListener(this);

}

public SimulationView(Context context) {

super(context);

mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); //实例化加速感应器

DisplayMetrics metrics = new DisplayMetrics();

getWindowManager().getDefaultDisplay().getMetrics(metrics); //分辨率获取

mXDpi = metrics.xdpi;

mYDpi = metrics.ydpi;

mMetersToPixelsX = mXDpi / 0.0254f;

mMetersToPixelsY = mYDpi / 0.0254f;

Bitmap ball = BitmapFactory.decodeResource(getResources(), R.drawable.ball);

final int dstWidth = (int) (sBallDiameter * mMetersToPixelsX + 0.5f);

final int dstHeight = (int) (sBallDiameter * mMetersToPixelsY + 0.5f);

mBitmap = Bitmap.createScaledBitmap(ball, dstWidth, dstHeight, true); //根据屏幕分辨率来设置素材的显示缩放比例

Options opts = new Options();

opts.inDither = true;

opts.inPreferredConfig = Bitmap.Config.RGB_565;

mWood = BitmapFactory.decodeResource(getResources(), R.drawable.wood, opts);

}

@Override

protected void onSizeChanged(int w, int h, int oldw, int oldh) { //当View有变化时,Android123提示比如说横竖屏切换

mXOrigin = (w – mBitmap.getWidth()) * 0.5f;

mYOrigin = (h – mBitmap.getHeight()) * 0.5f;

mHorizontalBound = ((w / mMetersToPixelsX – sBallDiameter) * 0.5f);

mVerticalBound = ((h / mMetersToPixelsY – sBallDiameter) * 0.5f);

}

@Override

public void onSensorChanged(SensorEvent event) { //感应器数据有变化时

if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER)

return;

switch (mDisplay.getRotation()) {

case Surface.ROTATION_0:

mSensorX = event.values[0];

mSensorY = event.values[1];

break;

case Surface.ROTATION_90:

mSensorX = -event.values[1];

mSensorY = event.values[0];

break;

case Surface.ROTATION_180:

mSensorX = -event.values[0];

mSensorY = -event.values[1];

break;

case Surface.ROTATION_270:

mSensorX = event.values[1];

mSensorY = -event.values[0];

break;

}

mSensorTimeStamp = event.timestamp;

mCpuTimeStamp = System.nanoTime();

}

@Override

protected void onDraw(Canvas canvas) { //主要的小球绘制

canvas.drawBitmap(mWood, 0, 0, null); //先画出背景

final ParticleSystem particleSystem = mParticleSystem;

final long now = mSensorTimeStamp + (System.nanoTime() – mCpuTimeStamp);

final float sx = mSensorX;

final float sy = mSensorY;

particleSystem.update(sx, sy, now);

final float xc = mXOrigin;

final float yc = mYOrigin;

final float xs = mMetersToPixelsX;

final float ys = mMetersToPixelsY;

final Bitmap bitmap = mBitmap;

final int count = particleSystem.getParticleCount();

for (int i = 0; i < count; i++) {

final float x = xc + particleSystem.getPosX(i) * xs;

final float y = yc – particleSystem.getPosY(i) * ys;

canvas.drawBitmap(bitmap, x, y, null);

}

invalidate();

}

@Override

public void onAccuracyChanged(Sensor sensor, int accuracy) {

}

}

}

整个例子可以在Android 2.3 SDK的Samples文件夹下找到,这个小铁球的例子可以帮助我们改造为平衡球游戏。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值