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

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

120万操作/秒Redis Cloud 集群单一服务器非基准测试程序 2014微信开发者大会顺利结束 TOP10优秀微信开发商名单公布 【最佳实践】通过DevOps确保可靠和有效的信息安全 2048 Hello World:跨平台快速应用开发Python框架Kivy Forrester:关于私有云的10个事实 2014年8月操作系统份额:Win 8.x大涨,Linux继续下跌 0代码、不编程—交互式网页设计工具VXPLO 揭秘Instagram Hyperlapse背后的技术 【CTO俱乐部在线教育研讨会】用互联网技术深入创新教育产品 降低门槛!Hybrid应用开发框架LigerMobile 下一代IT革命:微服务器和雾计算 使用Mongo Connector和Elasticsearch实现模糊匹配 时隔8个月,物联网联盟AllSeen如今怎样? 《近匠》简网:开发零门槛 快速建原生App MDCC免费展位申请超预期 大会内容初曝光 在服务器与交换机定制之后,谷歌着手量子计算机CPU设计 电信天翼开放平台鲍占斌:优质能力 分成比例高 艾格拉斯副总裁王晓波:手游定价如何设计 Xcode 6 Beta 7发布:语法定、内库改,Swift何时完善? 干货来袭:由22个联邦机构分享的6482个数据集 Phablet出货量今年将超移动PC,明年再超平板 如何提高Web服务端并发效率的异步编程技术? 改改改!让应用通过审核出人头地的10个方法 正益无线CEO王国春:AppCan如何获得50万开发者青睐 在收购Xtreme Labs之后,Pivotal推出PaaS移动服务 .NET开发者必备的11款免费工具 .NET开发不可错过的25款高效工具 Docker最佳实践!尽在2014 Container技术大会 pflua:用Lua编写的高性能网络包过滤工具箱 掌上明珠张磊:如何设计手游付费体系 云游科技何千军:游戏开发和后端逻辑经验 公司严重拖欠薪金,请问到劳动局追讨工资是否可行[up有分] 一个人,35岁与30岁有什么差别? myjdbc.jar 虽然别人谈过很多了,还是想再请教怎样学习vc 2003成都美女节 求助!有关文件(2) 关于刷新问题(定位)的,急用!! 试贴 下载问题,我发现一个奇怪的问题。中文名的文件的下载。。。 ADOQUERY无法更新数据集 帮我看看,怎么编译不通过 各位板主:折腾了我三天的问题还未解决。 delphi qreport byte& 是什么类型? IBM DDYS-TO9170M SCSI 硬盘,如何看它的CACHE,写者10000转的,不知道是不是? IBM DDYS-TO9170M SCSI 硬盘,如何看它的CACHE,写者10000转的,不知道是不是? 急!我在传输参数到SQL的过程中,服务器提示“AAA”需要参数但没有参数,请各位高手给个意见!在线等! 弹出窗口的问题--在线 串口工作有误了,MSComm32控件的问题?? 想知道有必要先学C 再C++ 再Visual C 吗? gqxs (小龙)请进,看到你去年的一个关于注册的帖子,我也出了像你一样的问题,请大家都来看看。 DBDateTime控件在哪里可以找到? 那为能够帮我解释一下SQLBindCol函数,特别是参数。 如何操作recordset,使其能够手动付值!即用 window nt和window 2000 server能不能象windows professional那样设成重启后自动登录。 关于语音视频聊天室 高手进入 来者得分 通过GUID枚举设备的问题请教! 代码不懂请指教 如何用javascript控制表单提交? (急急-在线等)一个复选框的问题 如何让服务器知道前来访问的客户机物理内存大小? 急,急,帮我看看。一个初级问题。 用思科1721路由器代理上网和连接网络电话功能够用吗? 请问用嵌入式系统开发的成本大约是多少? 如何获取两个日期之间相隔的天数? PB中如何操作文件。 在线等急盼tomcat启动问题 我的奔4电脑不能装oracle8。1。7 java 与oracle数值类型转换问题 请教“数字权利管理”(digital rights management)和P3P的实现问题? IBM DDYS-TO9170M SCSI 硬盘,如何看它的CACHE,写者10000转的, 数据插入速度问题 一个关于自定义类的问题,请帮助! 如何使用DBchart? DELPHI+CORBA 求救!!!! 请问java中如何获得windows的系统目录? 大家看看这台服务是出了什么问题?帮帮忙!!! 一个想把控件内容打印出来的小问题! 如何查看表中各字段的长度? 谁能给出一个ASP.NET应用存储过程的例子 self::node()是否就是 . 高分求救::关于分类显示的问题. 请问180n“^”是什么意思, 十年寒窗无人问,后一句是什么? 60*3=180,180除以3=60,180除以60=3,你能发现什么? 十年寒窗, 语文好多多音字. 从百草园到三味书屋 ade怎么读? I work in a bookstore的提问是什么用do 还 is 从百草园到三味书屋的Ade,读什么? 从百草园到三味书屋 I work in a spacesuit什么意思 go down是什么意思拜托各位了 3Q 德国政府:默克尔被窃听手机泄密可能性美国10月份消费者信心降至今年以来新女子参加富豪相亲会 反问记者你不爱钱央视马年春晚首次审看节目 共有28个故宫凶杀案嫌犯在协和医院抢救 已度过山西平顺回应“官员粗口门”:已对涉事德国政府:默克尔被窃听手机泄密可能性意大利媒体称英美合作监控意通讯 政府欧安组织将向阿富汗派遣团队帮助选举美国耐用品订货9月份环比上升3.7%欧盟承诺为企业发展提供便利维埃拉变形记“很高兴能亲口对你们说一声感谢”智博会下月开幕 去看新款机器人我区投1306万元 治理福里河山洪沟黄晓威:我是个有梦的跑者开网店卖城口老腊肉 他首月做成上百笔新鸥鹏教育城·巴南 打造“中国教育到重庆最美江湾享受玫瑰人生大货车抵住门面几个月 餐馆无法开业老雍山谷10套全装房 5年免费试住重病住院时 他仍常念叨着工作极品魔头都市之超能人生帝术幻世录之地下城与勇士骨妖网游之芥子须弥大明总裁未来软件万世天主综漫之热火异界之极品老大桂林公园旅游丹山赤水旅游姚江源头旅游烟霞三洞旅游皇城根遗址公园旅游中国美术馆旅游小和山旅游小月湾旅游大佛寺旅游永福寺旅游化觉巷清真大寺旅游
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘