带加速度传感器的移动球应用程序看起来不平滑和连续

时间:2013-08-24 21:52:52

标签: java android user-interface

我正在尝试学习使用传感器制作Android游戏。我要做的是使用加速度传感器使球在屏幕上移动。实际上,我做了一些其中的一部分。当x和y的加速度改变时,球在屏幕中移动。但我的问题是它看起来并不顺畅。看起来球在连续路径中没有在屏幕上绘制。我为这个应用程序使用SurfaceView类,并且我在与主线程不同的线程上创建了绘图。
部分代码来自我的MainActivity类,它与传感器相关:

@Override
    public void onSensorChanged(SensorEvent event) {
        // TODO Auto-generated method stub
        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
            long actualTime = System.currentTimeMillis();
            long delta_t = actualTime - lastUpdate;

            lastUpdate = actualTime;

            ax = event.values[0];
            ay = event.values[1];

            if (ax > 0) {
                isleft = true;
                delta_x = (float) (0.005 * ax * delta_t * delta_t);

            }
            if (ax < 0) {
                isleft = false;
                delta_x = (float) (-0.005 * ax * delta_t * delta_t);

            }
            if (ay > 0) {
                isdown = true;
                delta_y = (float) (0.005 * ay * delta_t * delta_t);

            }
            if (ay < 0) {
                isdown = false;
                delta_y = (float) (-0.005 * ay * delta_t * delta_t);

            }

            getBallPos();
        }

    }

    private void getBallPos() {
        delta_x /= 10000;
        delta_y /= 10000;

        for (int i = 1; i <= 10000; i++) {
            if (isleft)
                ballview.setX_loc(ballview.getX_loc() - delta_x);

            if (!isleft)
                ballview.setX_loc(ballview.getX_loc() + delta_x);

            if (isdown)
                ballview.setY_loc(ballview.getY_loc() + delta_y);

            if (!isdown)
                ballview.setY_loc(ballview.getY_loc() - delta_y);
        }

    }

部分代码来自扩展BallGame的{​​{1}}类,我在不同的主题上绘图:

SurfaceView

提前谢谢。

1 个答案:

答案 0 :(得分:1)

我认为有两个问题:

首先,您要用onSensorChanged方法更新球的位置。该方法由系统调用,并不保证调用以恒定频率完成。在这种情况下,球的运动取决于这些调用。我认为更好的方法是将最后的axay存储为变量,这两个onSensorChanged方法可以访问这些变量来写入值和绘制线程以供读取。然后你可以在绘图线程中计算球位置,这可以用恒定频率重绘画布。

这给我们带来了第二个问题,即在循环时绘制线程。它不受控制画布重绘的频率。对系统来说是一个很大的负担。更好的方法是选择刷新率(例如每秒50帧)并以此频率更新绘图。它可以在while循环结束时完成,其中可以调用Thread.sleep()函数。您可以在while循环开始时测量帧绘制何时开始long frameStartTime = System.currentTimeMillis(),然后在while循环结束时调用:

long sleepTime = refreshInterval-(System.currentTimeMillis()-frameStartTime );
if (sleepTime > 0) {
    Thread.sleep(sleepTime);
}

(50 fps是refreshInterval = 1000/50 = 20 ms)。

此调用在帧刷新间隔减去用于绘制球的时间的时间内休眠线程。当您选择足够的刷新率时,系统负载会降低,并且将有更多时间重新绘制。