Android游戏循环中的非恒定计时

Android游戏循环中的非恒定计时,android,loops,timing,Android,Loops,Timing,我正在为Android开发一款游戏。因为这是我的第一款Android游戏,我想让它尽可能简单。我想显示一系列随机数(一次一个)。在每对数字之间应该经过一定的时间(我目前使用的是500毫秒) 问题是两个数字之间的延迟不是恒定的(无论是在模拟器上还是在运行Android 2.3.4的实际设备上)。大多数情况下,数字以恒定速率变化,但有时会出现明显的延迟(甚至超过1秒) 我包括了代码中负责呈现数字的部分。我正在使用SurfaceView,以下部分是在附加线程中实现的游戏循环的run()方法: whil

我正在为Android开发一款游戏。因为这是我的第一款Android游戏,我想让它尽可能简单。我想显示一系列随机数(一次一个)。在每对数字之间应该经过一定的时间(我目前使用的是500毫秒)

问题是两个数字之间的延迟不是恒定的(无论是在模拟器上还是在运行Android 2.3.4的实际设备上)。大多数情况下,数字以恒定速率变化,但有时会出现明显的延迟(甚至超过1秒)

我包括了代码中负责呈现数字的部分。我正在使用SurfaceView,以下部分是在附加线程中实现的游戏循环的
run()
方法:

while (!mDone) {
    long now = System.nanoTime();
    if (mLastTime == -1) mLastTime = now;
    long delta = now - mLastTime;
    if (delta > 500000000) {
        mNumberBox.update();
        mLastTime = now;
    }

    if ((w > 0) && (h > 0)) {
        Canvas canvas = mSurfaceHolder.lockCanvas();
        if (canvas != null) {
            mRenderer.drawFrame(canvas);
            mSurfaceHolder.unlockCanvasAndPost(canvas);
        }
    }
}
mNumberBox.update()
更新要绘制的数字,并且应该每500毫秒调用一次。其代码非常简单:

mCurrNumber = mRand.nextInt(9) + 1;
mrender.drawFrame()
负责在屏幕上显示数字。代码如下:

canvas.drawRoundRect(mBoxRect, 45, 45, mBoxPaint);
String numStr = String.format("%d", mCurrNumber);
Rect bounds = new Rect();
mTextPaint.getTextBounds(numStr, 0, 1, bounds);
int height = bounds.bottom - bounds.top;
canvas.drawText(numStr, canvas.getWidth() / 2, canvas.getHeight() / 2 + height / 2, mTextPaint);
我已经分析了代码,执行应用程序大约260秒。以下是我发现的结果:

  • run()
    循环迭代次数:16765
  • 每次迭代的平均时间:16毫秒
  • 所有迭代的最长时间:97毫秒
几乎100%的时间都花在
drawFrame()
上,尤其是调用
lockCanvas()
unlockCanvasAndPost()
,这是我无法避免的


最奇怪的是,所有迭代的最长时间是97毫秒,远远少于我在执行游戏时注意到的延迟。因此,不知何故,我相信问题可能不在游戏循环代码中,而可能在配置中,或者其他地方。有人有什么建议吗?

您应该设计组件来绘制数字,就这样

然后,您应该让其他类实现游戏逻辑,等待一段时间,然后将一个数字传递给UI组件,并要求它绘制数字

让UI方法等待是一个非常糟糕的主意,您的游戏将无法响应

此外,游戏逻辑组件应该进行更小的等待。等待100毫秒,每次检查在选择最后一个号码后等待的时间是否超过500毫秒。

尝试以下操作:

使用500毫秒的计时器任务,更新mNumberBox,并使曲面无效

在曲面类的onDraw()中,调用mrender.onDraw(canvas)

此解决方案不会消耗太多cpu,对电池非常友好,而且响应速度快


您还将注意到,您的延迟问题将得到解决

w
h
只是包含画布宽度和高度的两个变量。在创建视图时,它们可能不会初始化,因此为零,但在初始化之后,它们的值不会更改。因此,条件检查总是正确的。实际上,游戏循环从不阻塞(即,渲染尽可能快地发生在硬件上)。我知道这在电池消耗方面可能不是最好的,但它应该提供最好的性能。因此,基本上,循环按照您在上一段中所说的进行(除了它不会阻塞,即使是100毫秒)。