Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Общие вопросы > пояснение игрового цикла


Автор: isalex678 12.10.2011, 13:25
Поясните игровой цикл.
за что отвечают переменные:
averagePassedTime, naiveTiming
для чего надо alpha и какое её назначение
Thread.sleep(8); почему 8?
многое непонятно.
где почитать на русском про игровые циклы.

Код

public class test2 {

    public static final int TICKS_PER_SECOND = 24;
    
    VolatileImage image = createVolatileImage(320, 240);
    Graphics g = getGraphics();
    Graphics og = image.getGraphics();

    int lastTick = -1;
    int renderedFrames = 0;
    int fps = 0;
    double time = System.nanoTime() / 1000000000.0;
    double now = time;
    double averagePassedTime = 0;
    boolean naiveTiming = true;

    while (running) {
        double lastTime = time;
        time = System.nanoTime() / 1000000000.0;
        double passedTime = time - lastTime;

        if (passedTime < 0) naiveTiming = false; 
        // Stop relying on nanotime if it starts skipping around in time 
        // (ie running backwards at least once). This sometimes happens on dual core amds.
        averagePassedTime = averagePassedTime * 0.9 + passedTime * 0.1;

        if (naiveTiming) {
            now = time;
        } else {
            now += averagePassedTime;
        }

        int tick = (int) (now * TICKS_PER_SECOND);
        if (lastTick == -1) lastTick = tick;
        while (lastTick < tick) {
            scene.tick();
            lastTick++;

            if (lastTick % TICKS_PER_SECOND == 0) {
                fps = renderedFrames;
                renderedFrames = 0;
            }
        }

        float alpha = (float) (now * TICKS_PER_SECOND - tick);

        sound.clientTick(alpha);
        scene.render(og, alpha);

        og.setColor(Color.BLACK);
        drawString(og, "FPS: " + fps, 5, 5, 0);

        g.drawImage(image, 0, 0, 640, 480, null);
        renderedFrames++;
        Thread.sleep(8);
    }
    
}



зачем надо было запускать дополнительный поток ?
подставляю this.run() - без него работает (может автор что то хотел сказать)

Код

public void start()
{
    if (!running)
    {
        running = true;
        new Thread(this, "Game Thread").start();
    }
}





Автор: Nofate 12.10.2011, 15:03
Ну там же все расписано в комментариях. 
В начала каждого прохода цикла, мы замеряем время, прошедшее с предыдущего прохода. Т.е., грубо говоря, на сколько должно продвинуться игровое время. Если замеренная величина меньше ноля (судя по комментариям автора это случается на двухъядерных процах от AMD), то отказываемся от "наивного" замера времени и ориентириуемся на среднее время выполнения цикла (а именно на взвешенную сумму среднего времени и измеренного времени в соотношении). 

Дальше секунды переводятся в тики, идет судя по всему отрисовка сцены, выводится FPS. Alpha - это количество тиков, на которое проматывается игровое время.

Thread.sleep(8) добавляет в каждый цикл задержку и, таким образом, ограничивает минимальное время выполнения цикла. Это делается для того, чтобы не перерисовывать сцену слишком часто и снижает нагрузку на процессор. Число 8 автор, скорее всего, подобрал эмпирически. Я, например, для некритичных обновлений нередко использую 100-200 мс.

Про использование потока сказать что-то конкретное трудно вне контекста остальной программы. Но, видимо, раз автор его использовал, значит зачем-то это было нужно, не так ли?

Читать про игровые циклы особо нечего. Все, как правило, идет по стандартной схеме: вычисляем прошедшее время, обновляем состояние игровых объектов и подсистем (физика, геймплей, гуй,  звук, мышиноклавиатурный ввод), рисуем очередной кадр.   

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)