AccelerometerPlayActivity代码注释(未完成)
来源:互联网 发布:java 图片识别数字 编辑:程序博客网 时间:2024/06/06 08:49
因需要将类名修改为testActivity,同时对弃用的方法进行替换。因涉及Verlet积分法来计算位置,尚未充分理解,故代码注释不完整,待继续完善,此处先做以保存。
import android.app.Activity;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.BitmapFactory.Options;import android.hardware.Sensor;import android.hardware.SensorEvent;import android.hardware.SensorEventListener;import android.hardware.SensorManager;import android.os.Bundle;import android.util.DisplayMetrics;import android.view.Display;import android.view.Surface;import android.view.View;import android.view.WindowManager;/** * This is an example of using the accelerometer to integrate the device's * acceleration to a position using the Verlet method. This is illustrated with * a very simple particle system comprised of a few iron balls freely moving on * an inclined wooden table. The inclination of the virtual table is controlled * by the device's accelerometer. * 这是一个通过加速度计使用Verlet方法来积分计算设备在某位置时的加速度的例子。 * 通过一个非常简单的粒子系统——在斜木桌上自由移动铁球来进行演示。 * 设备的加速度计控制着虚拟木卓的倾向程度。 * @see SensorManager * @see SensorEvent * @see Sensor */public class testActivity extends Activity { private SimulationView mSimulationView; private SensorManager mSensorManager; private Display mDisplay; //private WakeLock mWakeLock; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE); //mPowerManager = (PowerManager) getSystemService(POWER_SERVICE); WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE); // 获取系统当前默认的显示对象 mDisplay = windowManager.getDefaultDisplay(); // Create a bright wake lock创建一个亮度唤醒锁 // SCREEN_BRIGHT_WAKE_LOCK已废弃,推荐使用如下方式来保持屏幕常亮 getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); //mWakeLock = mPowerManager.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, getClass().getName()); // instantiate our simulation view and set it as the activity's content //实例化我们定制的模拟View对象,并把它设置为Activity的显示内容 mSimulationView = new SimulationView(this); setContentView(mSimulationView); } @Override protected void onResume() { super.onResume(); /* * when the activity is resumed, we acquire a wake-lock so that the * screen stays on, since the user will likely not be fiddling with the * screen or buttons. * 当Activity进入resume状态时,我们申请了一个唤醒锁,让屏幕在程序运行期间保持高亮, * 因为用户不太会在程序运行期间频繁的点击屏幕或按钮。 */ //mWakeLock.acquire(); mWakeLock已优化注释掉 // Start the simulation启动模拟窗口 mSimulationView.startSimulation(); } @Override protected void onPause() { super.onPause(); /* * When the activity is paused, we make sure to stop the simulation, * release our sensor resources and wake locks * 当Activity被挂起时,我们要确保终止模拟窗口,释放传感器资源和唤醒锁。 */ // Stop the simulation终止模拟窗口 mSimulationView.stopSimulation(); // and release our wake-lock mWakeLock已优化注释掉 //mWakeLock.release(); } class SimulationView extends View implements SensorEventListener { // diameter of the balls in meters以米为单位定义小球的直径 private static final float sBallDiameter = 0.004f; //小球的直径的平方 private static final float sBallDiameter2 = sBallDiameter * sBallDiameter; // friction of the virtual table and air虚拟桌面和空气的摩擦力 private static final float sFriction = 0.1f; private Sensor mAccelerometer; //持续时间 private long mLastT; //时间增量 private float mLastDeltaT; //X、Y轴方向Dpi private float mXDpi; private float mYDpi; //X、Y轴米像素 private float mMetersToPixelsX; private float mMetersToPixelsY; private Bitmap mBitmap; private Bitmap mWood; //X、Y轴初始位置 private float mXOrigin; private float mYOrigin; // private float mSensorX; private float mSensorY; //传感器时间戳 private long mSensorTimeStamp; //CPU时间戳 private long mCpuTimeStamp; //水平和垂直边界 private float mHorizontalBound; private float mVerticalBound; private final ParticleSystem mParticleSystem = new ParticleSystem(); /* * Each of our particle holds its previous and current position, its * acceleration. for added realism each particle has its own friction * coefficient. * 每个粒子都保存这它的前一个位置和当前位置,以及加速度。 * 为了表现的更加真实,每个粒子都有它们自己的摩擦系数。 */ class Particle { //当前位置的X、Y坐标 private float mPosX; private float mPosY; //X、Y方向上的加速度 private float mAccelX; private float mAccelY; //前一个位置的X、Y坐标 private float mLastPosX; private float mLastPosY; //摩擦系数( < 1 ) private float mOneMinusFriction; Particle() { /* * make each particle a bit different by randomizing its * coefficient of friction * 通过设置随机的摩擦系数让每个粒子稍有不同 */ final float r = ((float) Math.random() - 0.5f) * 0.2f; //[-0.1,0.1) mOneMinusFriction = 1.0f - sFriction + r; } void computePhysics(float sx, float sy, float dT, float dTC) { // Force of gravity applied to our virtual object //我们虚拟物理的重力 final float m = 1000.0f; // mass of our virtual object质量 //X、Y轴方向上的重力 final float gx = -sx * m; final float gy = -sy * m; /* * F = mA <=> A = F / m We could simplify the code by * completely eliminating "m" (the mass) from all the equations, * but it would hide the concepts from this sample code. * 把公式 F=mA 转换成 A=F/m,我们能够通过完全消除所有公式中的“m”(质量)来简化代码 * 但是它也从这段示例代码中隐藏了概念合力=质量乘以加速度 */ //m分之一 final float invm = 1.0f / m; //X、Y轴方向上的加速度 final float ax = gx * invm; final float ay = gy * invm; /*用d来表示deltaT * Time-corrected Verlet integration The position Verlet * integrator is defined as x(t+d) = x(t) + x(t) - x(t-d) + * a(t)d? However, the above equation doesn't handle variable * d very well, a time-corrected version is needed: x(t+d) = * x(t) + (x(t) - x(t-d)) * (d/d_prev) + a(t)d? We also add * a simple friction term (f) to the equation: x(t+d) = x(t) + * (1-f) * (x(t) - x(t-d)) * (d/d_prev) + a(t)d? * * 关于Verlet积分法的使用,参见以下链接: * https://en.wikipedia.org/wiki/Verlet_integration * http://www.cnblogs.com/crackpotisback/p/5293991.html * * 计算通过Δt时间后的位置。 */ 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; } /* * Resolving constraints and collisions with the Verlet integrator * can be very simple, we simply need to move a colliding or * constrained particle in such way that the constraint is * satisfied. * 用Verlet积分法能轻易的解决约束和碰撞的问题, * 我们只需用满足约束条件的方式来移动发生碰撞或受到约束的粒子 * */ void resolveCollisionWithBounds() { // X,Y轴的最大边界 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; } } } /* * A particle system is just a collection of particles * 一个粒子系统即粒子的集合 */ class ParticleSystem { static final int NUM_PARTICLES = 15; private Particle mBalls[] = new Particle[NUM_PARTICLES]; ParticleSystem() { /* * Initially our particles have no speed or acceleration * 最初我们的例子没有速度和加速度 */ for (int i = 0; i < mBalls.length; i++) { mBalls[i] = new Particle(); } } /* * Update the position of each particle in the system using the * Verlet integrator. * 使用Verlet积分法更新系统中每个粒子的位置 */ 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 (Particle ball : mBalls) { ball.computePhysics(sx, sy, dT, dTC); } } mLastDeltaT = dT; } mLastT = t; } /* * Performs one iteration of the simulation. First updating the * position of all the particles and resolving the constraints and * collisions. * 执行一次传感器模拟的迭代。 * 首先更新所有的粒子的位置,并解决约束和碰撞的问题 */ void update(float sx, float sy, long now) { // update the system's positions更新粒子系统中各粒子的位置 updatePositions(sx, sy, now); // We do no more than a limited number of iterations //最大迭代数 final int NUM_MAX_ITERATIONS = 10; /* * Resolve collisions, each particle is tested against every * other particle for collision. If a collision is detected the * particle is moved away using a virtual spring of infinite * stiffness. * 每个粒子都要被检测是否碰撞了其他粒子 * 如果检测到了一个碰撞,那么使用无限刚度的弹性运动来移走这个粒子 */ 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) { /* * add a little bit of entropy, after nothing is * perfect in the universe. */ 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; } } /* * Finally make sure the particle doesn't intersect * with the walls. */ curr.resolveCollisionWithBounds(); } } } int getParticleCount() { return mBalls.length; } float getPosX(int i) { return mBalls[i].mPosX; } float getPosY(int i) { return mBalls[i].mPosY; } } public void startSimulation() { /* * It is not necessary to get accelerometer events at a very high * rate, by using a slower rate (SENSOR_DELAY_UI), we get an * automatic low-pass filter, which "extracts" the gravity component * of the acceleration. As an added benefit, we use less power and * CPU resources. */ 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; // rescale the ball so it's about 0.5 cm on screen 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) { // compute the origin of the screen relative to the origin of // the bitmap 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; /* * record the accelerometer data, the event's timestamp as well as * the current time. The latter is needed so we can calculate the * "present" time during rendering. In this application, we need to * take into account how the screen is rotated with respect to the * sensors (which always return data in a coordinate space aligned * to with the screen in its native orientation). * 记录加速传感器的数据、事件发生的时间以及当前时间。 * 我们需要后者来计算渲染期间的展现时间。在这个应用程序中, * 我们需要考虑屏幕是怎样跟传感器一起旋转的(让它返回的数据 * 跟屏幕的原始坐标空间相对应) */ 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) { /* * draw the background */ canvas.drawBitmap(mWood, 0, 0, null); /* * compute the new position of our object, based on accelerometer * data and present time. */ 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++) { /* * We transform the canvas so that the coordinate system matches * the sensors coordinate system with the origin in the center * of the screen and the unit is the meter. */ final float x = xc + particleSystem.getPosX(i) * xs; final float y = yc - particleSystem.getPosY(i) * ys; canvas.drawBitmap(bitmap, x, y, null); } // and make sure to redraw asap invalidate(); } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } }}
0 0
- AccelerometerPlayActivity代码注释(未完成)
- AccelerometerPlayActivity
- 编码&注释的小问题(未完成)
- 排序代码测试(未完成)
- 未完成代码
- 实现买菜功能(未完成代码)
- 未完成的代码:Allchi_contraler
- [代码备份]poj1324--未完成
- 未完成的代码!
- mybatis代码流程-未完成
- Linux内核代码笔记3----进程(未完成)
- 未完成的DNF外挂代码。
- SSM框架代码流程-未完成
- springmvc 部分代码流程-未完成
- 代码注释(Code comments)
- 提高代码可维护性(1)---代码注释
- iOS代码统计(空行、注释、代码)
- 代码注释
- (14)YARN Timeline Server
- (四)主题应用
- 继承
- 最大公约数
- Android下一种打开并读取指定路径文件内容的方法
- AccelerometerPlayActivity代码注释(未完成)
- 详解synchronized与Lock的区别与使用
- 【VS开发】windows下的signal
- 微信接入
- 配置wampserver下MySQL的默认编码
- 背包问题
- Java 中常用缓存Cache机制的实现
- GFOJ problem468 出去玩 解题报告
- 批处理方式合并hex文件