用画布的java delta时间问题

时间:2015-01-25 11:02:21

标签: java android canvas

我正在尝试使用画布和位图制作一个小游戏我希望我的游戏在所有设备上运行相同我发现增量时间是最佳实践,但出于某种原因,当我尝试将其实现到我的代码中时有显示问题,例如我试图在天空中移动我的coluds但是当我添加delta他们都消失了我不知道我做错了所以请sombody帮助我继承代码

private float c1x = 0.0f;
private float c2x = cloudWidth;
private float c3x = cloudWidth * 2;
private float cloudSpeed = 0.1f;
private long curentTime;
private long lastTime = 0;
private double delta;

@Override
public void run(){
    while(running){
        if(!holder.getSurface().isValid()){
            continue;
        }

        curentTime = System.nanoTime();
        delta = curentTime - lastTime;
        lastTime = curentTime;

        cloudMovement();

        canvas = holder.lockCanvas();
        canvas.drawBitmap(bg, 0, 0, null);
        canvas.drawBitmap(sun, 20, 20, null);

        canvas.drawBitmap(cloud1, c1x, c1y, null);
        canvas.drawBitmap(cloud2, c2x, c2y, null);
        canvas.drawBitmap(cloud3, c3x, c3y, null);

        holder.unlockCanvasAndPost(canvas);
    }

}

private void cloudMovement(){

    if(c1x <= 0 - cloudWidth){
        c1x = w;
        c1y = y.nextInt(rand);
    }
    if(c2x <= 0 - cloudWidth){
        c2x = w;
        c2y = y.nextInt(rand);
    }
    if(c3x <= 0 - cloudWidth){
        c3x = w;
        c3y = y.nextInt(rand);
    }
    c1x-=cloudSpeed * delta;
    c2x-=cloudSpeed * delta;
    c3x-=cloudSpeed * delta;
}

1 个答案:

答案 0 :(得分:2)

您可以使用全局FPS机制来强制游戏中的稳定FPS:)

如果您跟踪FPS,游戏将在任何设备上以相同的方式运行,您不需要在所有更新过程中包含delta-times。

这是我在旧项目中使用的FpsTracker的代码片段:

private static final long SECOND = 1000;
private static final long TARGET_FPS = 40;
private static final long FRAME_PERIOD = SECOND / TARGET_FPS;

private long time = System.currentTimeMillis();

/**
 * 
 * @param startTime
 * @return <code>true</code> if the interval between startTime and the time
 *         when this method was called is smaller or equal to the given
 *         frame period.
 * 
 *         Will return <code>false</code> if the interval was longer.
 */
public boolean doFpsCheck(long startTime) {

    if (System.currentTimeMillis() - time >= SECOND) {
        time = System.currentTimeMillis();
    }

    long sleepTime = FRAME_PERIOD
            - (System.currentTimeMillis() - startTime);

    if (sleepTime >= 0) {
        try {
            Thread.sleep(sleepTime);
        } catch (InterruptedException e) {
            //TODO handle this properly
            e.printStacktrace()
        }
        return true;
    } else {
        return false;
    }
}

如果此方法返回false,则表示您的操作所花费的时间比您为一帧提供的时间长。您可以通过检查doFpsCheck返回参数来对此作出反应。

在您的代码中实现此内容将如下所示:

@Override
public void run()
{
    while(running)
    {
        if(!holder.getSurface().isValid())
        {
            continue;
        }

        startTime = System.currentTimeMillis();

        cloudMovement();

        canvas = holder.lockCanvas();
        canvas.drawBitmap(bg, 0, 0, null);
        canvas.drawBitmap(sun, 20, 20, null);

        canvas.drawBitmap(cloud1, c1x, c1y, null);
        canvas.drawBitmap(cloud2, c2x, c2y, null);
        canvas.drawBitmap(cloud3, c3x, c3y, null);

        holder.unlockCanvasAndPost(canvas);

        doFpsCheck(startTime);
    }

}

顺便说一下 - 将游戏循环划分为专业子流程是一种好习惯,一个是更新过程,另一个是绘制过程。 对于许多不同的位图,您应该考虑将字段和功能提取到包含draw(Canvas c)update()方法的单独类中。所以你不会在你的主要班级上获得一万亿个字段。