说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

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

HTML文档下载 WORD文档下载 PDF文档下载
Android加速感应器开发平衡球代码解析

作者:Android开发网


   如何使用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文件夹下找到,这个小铁球的例子可以帮助我们改造为平衡球游戏。

Google开源代码构建工具Bazel 长点心吧!为啥健身应用让你越减越肥? 微信公众号能删除单篇文章了 安卓Android手机应用开发入门书籍推荐 自动释放内存!Facebook推出强大Android图片库Fresco 《近匠》AR学校:从教育领域看增强现实机遇何在 专访Mellanox CEO Eyal Waldman:InfiniBand与以太网齐驱并进 性能更胜一筹 IM助你打造千万级App——容联•云通讯线下沙龙 乐视智能硬件再发力,超级自行车今发布 专访格灵深瞳CTO赵勇:为&quot; 计算机视觉&quot; 赋予智慧的光芒 【程序员电子刊精选】水火不容?研发人员也是产品经理! 如何打动用户?携程用户体验实践分享 【征文】Java二十周年特别策划——谈谈我与Java的那些年、这些事 Facebook的愿景以及虚拟现实的未来 iBeacons一年回顾 英特尔中国30周年之际 IDF上你需要了解的5件事 OpenCloud 2015参会者的三大特征(附列表) 友盟移动互联网趋势报告解读:垂直领域应用竞争白热化 墨腾动漫CTO吴建学:初创公司的生存之道 亿航与高德达成战略合作 LBS+引爆智能硬件软实力 《近匠》火柴手写码,输不错的验证码利器 Web、App中添加动效设计应遵循的12条原则 越狱与开源:2015移动安全峰会(MSS)纪实 开发者自白:我是如何不花一分钱收获230万应用下载量的! OpenCloud 2015报名超预期 近20位讲师会前采访提前看 硅谷公司人才招聘那些事儿——硅谷“超级面试官”董飞专访 一切为了用户体验:揭秘京东首页改版背后的故事 TIOBE 2015年4月编程语言排行榜:Java王者归来 三大主题技术峰会开幕在即 OpenCloud 2015参会者提醒 《近匠》快码,唯快不破的代码众包平台 打破边界 生态化反!乐视发布三款超级手机 ----在线程里的SOCKET为什么关不掉 请问如何有破解excel2000文件密码的工具或方法吗?300分酬谢,急等.谢谢! 在SQL*PLUS下怎样查看一个字段的属性,如是否为主关键字。 帮小弟一把,我仅有的36分了,各位 在vc中如何将字符串转化成其对应的ascii码?用什么函数? 天啊!!怎么办啊,救命啊 内存分配的一个小问题 无聊,散分。只给前面十个。 用image控件可以互相转换ico,bmp,jpg三种格式的图片吗? 请问哪有NGWS下载? ?有没有啊 以下程序的输出值是 哪位朋友知晓如果Table与DbGrid绑定后,如何实现非第一索引的排序。 请问MSDN有中文版的吗?我们这的全是英文版的 我的 Win2000 出大问题了,急盼各位大虾赐教 请问那里有VB.NET软件下载呀 什么delphi命令可以打开网页呢? 到底有没有人知道如何可以在panel中动态的调用frame或者是form呢? 哪里有windowsXP下载? 送我能给的最大分,请教很小的问题,中高手进 聊天请进(thinkingdog) 大家来谈谈 IBM都有些什么认证???什么认证现在比较吃香???谢谢!!! 打印数窗问题求助! 如何使用UrlDownloadtoFile下载文件使用进度条? 如何用在两次用getTime()中得到两个不同的时间。 一个类似于牛角尖的问题(多余的CONST),不能忽视,请各位高手详细说明!!谢谢! 怎样读写注册表,每次都不成功,气死我也~! 各位救命啊,用 TClientDataSet.Load XML 的问题。。。。 娃呀呀,pb8怎么这么难安装?jaguar组建就用了5分钟,regester window又用了10分钟,重启动后,还没完,偶不敢装了,把碟退了出来,大家是不是也这样?//牛虻 请教高手一个ado的问题. 请问一个TWebBrowser的问题 请问:系统崩溃后,找不到BOOT,系统告诉:DOS基本分区为格式化?无法引导启动! 在VB.NET的tabcontrol上放置AxMSFlexGrid控件问题,急 java3D 现在大家是用Oracle 8还是 Oracle 9??? C++问题求助! 请教一个错误的原因. 各位大侠请问Jeffrey Richter的windows核心程序设计是不是就是andvanced windows程序设计的第四版 SCJP里的那些什么300-020,020是什么意思啊? 请问一个关于document.write()方法的问题。急啊! 初学者,欢迎灌水。 Delphi6的Bug?不兼容? 为什么我用GetProfileString()却总是得不到结果 sos 请教各位大侠一个问题 delphi6中的installShield 请介绍接收端CRC校验传输内容是否正确的方法,资料或代码。谢谢! 各位大侠请问Jeffrey Richter的windows核心程序设计是不是就是andvanced windows程序设计的第四版? 谁会做软件狗?有钱赚了!!! 为什么我用QuickRep作的报表只能显示一条记录,而且columnHeaderBand上内容也显示不出来 请问在税务局开发数据库的同行么?? 大家好各位大侠请问Jeffrey Richter的windows核心程序设计是不是就是andvanced windows程序设计的第四版? 用二氧焊进行单面焊双面成型时,打底焊后,焊缝上出现裂纹,并非收弧时也出现,是何原因,如何避免? 上午12时在太阳光下的影子最长吗? 油为什么能穿透塑料袋为什么塑料袋没破 而且油还能穿透塑料袋弄的桌面上油都是油呢? 焊接符号 焊接双面焊符合怎么表示?单面焊又怎么表示呢 如何利用太阳光下的影子测量旗子的高度啊?怎么利用太阳光下的影子测旗杆的高度? 一个正方体在太阳光照射下有几种形状 请问:原电池中,若电解质溶液为0.5mol/L硫酸溶液,电极为铜片和铝片,则电流计指针为什么偏向铝?另外请问:稀HNO3与Fe反应放H2吗?若不放出H2,那该放出哪种气体? 请问这个焊接符号圆圈里的43是什么意思? 升华过程要吸热,有什么作用? Al 和Cu组成原电池 若电解质溶液为稀硫酸,则电流表的指针偏向铝还是铜?究竟电流表的偏转方向是偏向正极还是负极? 机械制图中焊接符号的表示法 用塑料袋炸出的油叫什么做油. 原电池中的电流计指针偏转方向为什么在Cu-Zn原电池间接上灵敏电流计,指针偏向Cu?电流计指针偏转方向不是应该和电流方向一样吗 形成西伯利亚地区大面积沼泽地的原因有多种,除了河水泛滥外,还可能有什么原因? 怎么做塑料除油剂配方才能改进?怎么做塑料除油剂配方才能改进,找哪家公司做比较好呢,最好设备什么的好点? 将表面去掉氧化膜的镁片与铝片用带电流表的导线连接,插入盛烧碱溶液的烧杯中,此时发现电流计指针偏转,判断此原电池的正负极,并写出电极反应式和总反应方程式.铝片做负极,镁作正极负 西西伯利亚平原的沼泽是怎么形成的 俄罗斯联邦为什么不把中国元朝时期就属于中国的领土:西伯利亚、外蒙古、等地,归还中国统治呢?为什么不把中国元朝时期就属于中国的领土:西伯利亚、外蒙古、 库页岛、唐努乌良海、 电极材料:镁铝,电解质溶液:氢氧化钠溶液,电流表指针变转方向:偏向镁,铝做负极的原因是—— 影子的方向和太阳的位置的关系太阳的变化 来的 中国和俄罗斯为什么不容易被分裂?我没有分裂中国的意思,我想问的是中国和俄罗斯都是多民族的国家,为什么这两个大国不容易分裂呢? 谁的影子最长? 阳光下任何( )的物体都有影子,影子都在( )的一面,在同一时刻,同一地点,直立的物体的影子方向都?阳光下任何( )的物体都有影子,影子都在( )的一面,在同一时刻,同一地点,直 俄罗斯中西伯利亚高原为什么没有东西伯利亚山地高? 永动机是可以实现的,如果分子永远在运动.这是可以做永动机的实验依据的啊设计了好几个方案,见教!==假设一第三类永动机:利用一种永不枯竭的能源,实现永动^^如果分子可以永动,这说 在一天当中,物体在太阳光下的影子的方向是如何变化的 用牛奶做隐形墨水的原理在白纸上用牛奶写字,写完后风干,再用打火机,在纸下面烤一下,字便显现出来.但是白纸的替他地方却没有被烤过的任何痕迹.请问这里面用了牛奶的什么原理,请详细讲 科学会把怎样的运动当作永动机如果永动机每分钟转动12转,对物理学意义 有多大? 为什么上午太阳光下物体的影子方向应为北偏西 为什么牛奶盒是长方形的?有什么原理吗? 写出下列物态变化的名称,并指出该物态变化是吸热还是放热1 夏天冰欺凌冒白气2 水结冰3 秋天的露水 用什么胶可以把塑料画现在漆墙上?就是白墙 压力容器的等级是怎么划分的什么是一类.二类.三类 太阳光照射旗杆从早晨到中午.下午之间的影子变化啥时候最长,最短,垂直?旗杆和影子垂直 焊接符号表示方法 压力容器是如何分类的 每小时太阳光照射的影子的角度是多少? 焊接符号怎么表示? 现行压力容器分类标准是什么时候开始执行的 为什么在太阳光照射下,人在地面上的影子早晚长,中午短? 这个是表示什么焊接符号呀 历史爱好者们,西伯利亚在元朝管辖时说何种语言?(肯定不再是现在的俄罗斯语言了) 为什么早上影子最长? 眼睛被太阳光照射到有影子被太阳强光反射到 求焊件符号的表示图纸焊件符号表示的意思. 我有急用 由镁、铝、氢氧化钠溶液组成的原电池,负极和正极反应式分别是? 布朗运动是液体颗粒运动还是固体颗粒运动?那 “布朗运动是悬浮在液体中的固体颗粒分子无规则运动的反映”哪错了? 这个焊接符号是啥意思?请指点. 那什么物态变化,要吸热放热的,应该怎么记?我老是记不住,求学习方法 悬浮在液体中的大颗粒固体会做布朗运动吗 太阳光下AC与A'C'是平行的,同一时刻的2根相同高度的木杆在太阳光照射下的影子一样吗?说说你的理由.要过程(初一下学期第五章三角形的复习题)最好有证明 单面焊双面成型!立焊单面焊双面成型是左右摆动在断弧还是只要在中间点一点不用摆动就断弧?不是开坡口的两块板,是类似立角焊的样子,两个板成V形组装,最好也说一下开坡口的,他们两种是 NAOH做电解液,连接好铝和镁组成原电池,正极和负极电子式分别是什么,为什么 某一时刻测的一根竹竿的影子是这根竹竿的两倍长那么此时的太阳光与地面成多少度角? Y电焊单面焊双面成型技能 镁和铝插入NAOH溶液中连接成原电池 铝表面有氧化膜为什么不必处理氧化铝和NAOH反应不是氧化还原啊 怎么构成原电池 如图,太阳光线AC与A‘C‘是平行的,同一时候两根高度相同的木杆在太阳光照射下的影子一样长吗?说说你的理由 平焊对接单面焊双面成型时,第一道焊焊枪角度是多少,第二道焊缝因离铁板平面多高? 在同一时刻两根木杆在太阳光下的影子如图所示,其中木杆ab=2米,它的影子bc=1.6米,木杆pq的影子又一部分落在了墙上,qm=1.2米,mn=0.8米,求木杆pq的长度 正方体在太阳底下的影子成什么图形?
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn