0

我正在尝试学习使用传感器使用 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的扩展类,SurfaceView我在不同的线程上进行绘图:

    @Override
        public void run() {
            // TODO Auto-generated method stub
            while (isItOk) {
                if (!holder.getSurface().isValid()) {
                    continue;
                }
                canvas = holder.lockCanvas();
                canvas.drawARGB(255, 150, 150, 10);
                // canvas.drawLine(lineStartX, lineStartY, lineEndX, lineEndY,
                // paint);
                checkBoundaries();
                canvas.drawBitmap(ball, x_loc, y_loc, null);
                holder.unlockCanvasAndPost(canvas);

            }
        }

        private void checkBoundaries() {

            if (x_loc > canvas.getWidth() - ballWidth) {
                x_loc = canvas.getWidth() - ballWidth;

            }
            if (y_loc > canvas.getHeight() - ballHeight) {
                y_loc = canvas.getHeight() - ballHeight;

            }
            if (x_loc < 0) {
                x_loc = 0;

            }
            if (y_loc < 0) {
                y_loc = 0;

            }
        }

先感谢您。

4

1 回答 1

1

我认为有两个问题:

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

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

long sleepTime = refreshInterval-(System.currentTimeMillis()-frameStartTime);
如果(睡眠时间> 0){
    Thread.sleep(sleepTime);
}

(对于 50 fps,refreshInterval = 1000/50 = 20 ms)。

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

于 2013-08-25T17:06:01.060 回答