плавная анимация в играх - PullRequest
3 голосов
/ 01 мая 2011

Как мне создать "плавную" анимацию?Я разрабатываю игру на Android.Я знаю, что способ создания плавной анимации по умолчанию не самый лучший:

perFrame() {
    time = highrestime();
    frameTime = time - lastTime;
    lastTime = time;

    // now you could use frameTime as delta. this will lead to not real
    // smooth animations
}

Я прочитал некоторые документы на эту тему.Особенно, если вы используете физическое моделирование.Знаменитая статья выглядит следующим образом: http://gafferongames.com/game-physics/fix-your-timestep/ Я создал базовый класс, который выглядит следующим образом:

public class TimeSystem {
private long mCurrentTime;
private long mAccumulator;
private Simulation mSimulation; 
private Renderer mRenderer;

private static float mSimulationDelta = 1000f / 60f;

public TimeSystem(Simulation simulation, Renderer renderer) {
    mCurrentTime = System.currentTimeMillis();
    mAccumulator = 0;

    mSimulation = simulation;
    mRenderer = renderer;
}

public void notifyNextFrame() {
    long newTime;
    long frameTime;

    newTime =  System.currentTimeMillis();
    frameTime = newTime - mCurrentTime;
    mCurrentTime = newTime;

    if(frameTime > 250)
        frameTime = 250;

    mAccumulator += frameTime;

    // while full steps of simulation steps can be simulated
    while(mAccumulator >= mSimulationDelta) {
        mSimulation.simulate(mSimulationDelta);
        mAccumulator -= mSimulationDelta;
    }

    // render
    mRenderer.render(frameTime / 1000.0f); // frameTime in seconds
}

public interface Simulation
{
    void simulate(float delta);
}

public interface Renderer
{
    void render(float delta);
}
}

Я действительно не эксперт в разработке игр, но я надеюсь, что понимаю основы этогостатья..simulate вызывается так часто, как это необходимо для фиксированного временного шага.Проблема в том, что анимация в сложной системе все еще не является плавной.FPS в моей программе составляет около 60FPS.

Заявка на тестирование написана на Java для Android:

    public float x = 40;
public float y = 40;
public float xmove = 0.1f;
public float ymove = 0.05f;

public void simulate(float delta) {
    x += xmove * delta;
    y += ymove * delta;

    if(xmove > 0)
    {
        if(x > 480)
            xmove = -xmove;
    }
    else if(xmove < 0)
    {
        if(x < 0)
            xmove = -xmove;
    }

    if(ymove > 0)
    {
        if(y > 480)
            ymove = -ymove;
    }
    else
    {
        if(y < 0)
            ymove = -ymove;
    }

    RandomSleep(8);
}

Random rnd = new Random();

public void doDraw(Canvas canvas, float delta) {
    Paint paint = new Paint();

    paint.setColor(Color.BLACK);
    paint.setStyle(Paint.Style.FILL);
    paint.setTextSize(30);

    canvas.drawColor(Color.BLUE);
    canvas.drawCircle(x, y, 10, paint);
    canvas.drawText("" + FPSConverter.getFPSFromSeconds(delta), 40, 40, paint);

    RandomSleep(5);
}

public void RandomSleep(int maxMS)
{
    try {
        Thread.sleep((int)(rnd.nextDouble()*maxMS));
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

Случайных снов в сумме будет макс.13 мс.Что кажется экстремальным, но с данной системой вы не должны чувствовать разницу.(Я пытаюсь смоделировать мою игровую систему, чтобы выяснить, почему анимации в моем реальном игровом движке не являются плавными; поэтому я использую наихудший сценарий)

РЕДАКТИРОВАТЬ: Если нет прямого ответа, может кто-то можетуказать, как я могу узнать, где может быть "ошибка".Что я могу сделать, чтобы проанализировать эти вещи правильно?

Ответы [ 2 ]

8 голосов
/ 15 мая 2011

Итак, наконец!Через две недели я нашел простое решение!Проблема заключалась в том, что я использовал System.currentTimeMillis ();Похоже, что разрешение этого таймера недостаточно высокое для плавной анимации.Я переписал класс таймера, и теперь он работает отлично.Для всех, кто сталкивался с подобной проблемой и хотел бы использовать мой код:

public class TimeSystem
{
private long mOldTime;
private long mAccumulator;
private long mNewTime;
private long mFrameTime;

private Simulation mSimulation;
private Renderer mRenderer;

private static final long mSimulationDelta = 1000 * 1000 / 10;
private static final float mSimulationDeltaInMilliseconds = mSimulationDelta / 1000;
private static final long mMaxFrameTime = mSimulationDelta;


public TimeSystem(Simulation simulation, Renderer renderer)
{
    mSimulation = simulation;
    mRenderer = renderer;

    mAccumulator = 0;
    mOldTime = System.nanoTime();
}

public void notifyNextFrame()
{
    mNewTime = System.nanoTime();
    mFrameTime = mNewTime - mOldTime;
    mOldTime = mNewTime;

    // if FPS is to slow don't produce even more CPU usage
    if (mFrameTime > mMaxFrameTime)
        mFrameTime = mMaxFrameTime;

    mAccumulator += mFrameTime;

    // while full steps of simulation steps can be simulated
    while (mAccumulator >= mSimulationDelta)
    {
        mSimulation.simulate(mSimulationDeltaInMilliseconds);
        mAccumulator -= mSimulationDelta;
    }

    // render
    mRenderer.render(mFrameTime / 1000f*1000f);
}

public interface Simulation
{
    void simulate(float delta);
}

public interface Renderer
{
    void render(float delta);
}
}

Я, если вам нравится, можете свободно голосовать :) Спасибо.

0 голосов
/ 01 мая 2011

Я думаю, что в этой строке есть опечатка: frameTime = lastTime - время; должно быть frameTime = время - lastTime; хотя я думаю, что в вашем реальном коде такой проблемы нет, иначе все было бы не так.

Один вопрос, который приходит на ум, сколько времени занимает ваш шаг моделирования? Вы уверены, что это не узкое место? Может, симуляция просто не поспевает за вашим рендерером?

...