Как уменьшить отставание в моем Java 2D платформер? - PullRequest
1 голос
/ 24 января 2012

Я делаю 2-й платформер в Swing Java, и мне интересно, как уменьшить отставание от него.Я имею в виду, что это не слишком плохо, но заметно, что иногда оно замедляется.У меня есть таймер Swing, тикающий со скоростью 12 миллисекунд, функция цикла и функция рисования.

public void cycle() {
    if (guy.getJumpState() == false) {
        if (canExecuteMovement(0, 4)) {
            onGround = false;
            if (guy.getY() > 300) {
                // if you are in the middle, move the platforms.
                for (int i = 0; i < platformCount; i++) {
                    platform[i].setY(platform[i].getY() - 4);
                }
            } else {
                // or just move the guy if not.
                guy.moveY(4);
            }
        } else {
            onGround = true;
        }
    } else {
        if (canExecuteMovement(0, -8)) {
            if (guy.getY() < 300) {
                // if you are in the middle, move the platforms.
                for (int i = 0; i < platformCount; i++) {
                    platform[i].setY(platform[i].getY() + 8);
                }
            } else {
                // or just move the guy if not.
                guy.moveY(-8);
            }
            jumpCount++;
            if (jumpCount >= 15) {
                jumpCount = 0;
                guy.setJumpState(false);
            }
        } else {
            jumpCount = 0;
            guy.setJumpState(false);
        }
    }

    if (guy.getDirection() == "left") {
        if (canExecuteMovement(-3, 0)) {
            if (guy.getX() < 450) {
                // if you are in the middle, move the platforms.
                for (int i = 0; i < platformCount; i++) {
                    platform[i].setX(platform[i].getX() + 3);
                }
            } else {
                // or just move the guy if not.
                guy.moveX(-3);
            }
        }
    } else if (guy.getDirection() == "right") {
        if (canExecuteMovement(3, 0)) {
            if (guy.getX() > 450) {
                // if you are in the middle, move the platforms.
                for (int i = 0; i < platformCount; i++) {
                    platform[i].setX(platform[i].getX() - 3);
                }
            } else {
                // or just move the guy if not.
                guy.moveX(3);
            }
        }
    }
}


public void paint(Graphics g) {
    super.paint(g); // something important
    Graphics2D g2d = (Graphics2D) g;

    // draw platforms
    for (int i = 0; i < platformCount; i++) {
        if (platform[i].getX() > -50 && platform[i].getX() < 950 && platform[i].getY() > -50 && platform[i].getY() < 650) {
            g2d.drawImage(platform[i].getImage(), platform[i].getX(), platform[i].getY(), this);
        }
    }

    // draw guy
    g2d.drawImage(guy.getImage(), guy.getX(), guy.getY(), this);

    // destroy unneeded processes
    Toolkit.getDefaultToolkit().sync();
    g.dispose();
}

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

Ответы [ 3 ]

2 голосов
/ 24 января 2012

Некоторые бесполезные мысли (прошло уже много лет с тех пор, как я делал анимацию в Swing), и вы не опубликовали какой-либо скомпилированный код.

  • Вы пытались сделать paintComponent () --- краска делает много других вещей.И тогда, возможно, вам нужно добавить repaint () для функции галочки.Каждый раз, когда я перезагружаю краску, она превращается в беспорядок.
  • Также попробуйте увеличить время тика - вы тратите меньше времени на повторный расчет
  • Также я предполагаю, что вы делаете тики по таймерам.
  • Понятия не имею, почему вы располагаете графический объект
  • Также попробуйте просто сбросить синхронизацию (я сделал анимации, которые работают на многих oeses без него) Toolkit.getDefaultToolkit().sync()

Если это не помогает использовать профилировщик, чтобы найти узкое место. Visual VM довольно хорош.Кроме того, Visual VM является частью jdk в течение некоторого времени - просто перейдите в папку bin и запустите jvisualvm.

EDIT: (проблемы с потоками)

  • Некоторые люди предложили использовать темы --- которые я diasgree.Если вы хотите поработать вне EDT, пожалуйста, используйте SwingWorker
  • Я предполагаю, что вы не звоните paint(), а просто звоните repeaint().Если вы звоните paint() (какую бы черную магию вы ни делали, чтобы она работала), пожалуйста, просто позвоните repaint(), чтобы запланировать ремонт в соответствующее время.
1 голос
/ 10 июля 2012

Я бы создал ваши переменные вне метода, чтобы он не создавался при каждом вызове этого метода.Лучший способ программирования игр - это повторное использование вещей вместо разрушения и создания, потому что уничтожение и создание стоят много вычислительной мощности.

Graphics2D g2d = (Graphics2D) g; <---declare it outside your method.

А также попытайтесь найти избыточные условия,Я видел один, где вы говорите (если направление вправо, то ..., иначе, если направление налево ...);просто сказать (если направление прямо тогда ... еще ...).Условные выражения не стоят дорого, но когда вы вызываете это условное 1000 раз в секунду, я думаю, что это складывается.(хотя, но я делаю это на всякий случай и для того, чтобы сделать вещи текучими)

Где вы говорите setjumpstate(false) это избыточно, потому что, несмотря ни на что, оно выполняется - просто переместите его за пределы условного.

1 голос
/ 24 января 2012

Прежде всего, этот бит здесь является проблемой:

// destroy unneeded processes
Toolkit.getDefaultToolkit().sync();
g.dispose();

В общем, удаление ресурса, который вы не создали, вероятно, плохая идея. В этом конкретном случае Graphics, переданный в paint(), вероятно, используется всеми другими компонентами в иерархии, поэтому это может привести к действительно странным результатам.

Звонок Toolkit.sync() вот, я думаю, ваша попытка устранить разрыв, который вы видели при перемещении вещей в фоновом режиме. Но все, что он делает, это сбрасывает любые ожидающие инструкции по рисованию. Это не имеет никакого эффекта, потому что вы, вероятно, рисуете в компонент Swing с обратной буферизацией, который будет отрисован полностью позже.

Правильный способ устранить разрыв - это выполнять любые обновления в потоке событий, чтобы вы не изменяли данные экрана во время их рисования. Одним из простых способов реализовать это было бы, чтобы ваш таймер просто вызывал repaint() и имел метод paint() вызывать цикл (), прежде чем что-либо делать.

Для борьбы с задержкой одним из решений может быть разрешение переменной частоты кадров. Вместо того, чтобы перемещать все на фиксированное расстояние в каждом кадре, рассчитайте время с последнего кадра и переместите все соответствующим образом.

...