Почему моя анимация не работает теперь, когда я добавил переменную счетчика и интервалы? - PullRequest
0 голосов
/ 22 февраля 2019

У меня есть функция анимации в классе.

Анимация состоит в том, что дерево быстро «вздрагивает» взад и вперед вдоль оси x, как будто его ударило топором.

Что бы я хотел, чтобы произошло:

Когда я нажимаю на дерево, анимация должна начинаться, останавливаться, запускаться, останавливаться, запускаться и затем окончательно останавливаться.На мой взгляд, соотношение между запущенной и остановленной анимацией будет где-то около 2 секунд, а 8 секунд остановлено.Границы, в которых находится анимация, очень малы (см. Последнее утверждение if) со скоростью 4. Поэтому дерево просто очень быстро подпрыгивает между двумя, создавая впечатление «дрожи».

Функция находится внутри класса, который вызывается в функции setup ().Однако tree.shudder () вызывается внутри функции draw (), которая является функцией зацикливания.

Это код с одной итерацией / циклом рабочей анимации:

shudder() {
  let d = dist(mouseX, mouseY, this.x, this.y);
  let speed = 0;
  if (d < 50) {
    speed = 4;
    if (this.x < this.l || this.x > this.r) {
      speed = speed * -1;
    }
  } else {
  speed = 0;
  }
  this.x = this.x + speed;
}

Анимацияработал, пока я не попытался автоматизировать запуск и остановку дрожания.Когда я добавил переменную counter и функции setInterval / clearInterval, дрожание больше не работает.

Я использую библиотеку p5.

Кто-нибудь может понять, почему моя анимация перестала работать здесь?

function setup() {
  createCanvas(windowWidth, windowHeight);
  trees = new Trees(200, 200);
}

function draw() {
  trees.shudder();
}

shudder() {
  let d = dist(mouseX, mouseY, this.x, this.y);
  let counter = 0;
  let speed = 0;
  if (d < 50) {
    let interval = setInterval(() => {
      speed = 4;
      counter++;
      console.log(counter);
      if (this.x < this.l || this.x > this.r) {
        speed = speed * -1;
      }
      if (counter === 3) {
        clearInterval(interval)
      }
    }, 1000)
  } else {
    speed = 0;
  }
  this.x = this.x + speed;
}

В console.log, если я нажимаю на дерево и пропускаю 60 кадров, это происходит:

60trees.js:31 1
trees.js:31 2
trees.js:31 1
trees.js:31 2
2trees.js:31 1
2trees.js:31 2

и работает бесконечно ...

Однако, еслиЯ нажимаю на дерево и щелкаю до того, как пройдет 60 кадров, и я получаю то, что хочу:

26trees.js:31 1
26trees.js:31 2
26trees.js:31 3

Любая помощь будет очень признательна!

1 Ответ

0 голосов
/ 23 февраля 2019

Некоторые проблемы:

  • setInterval выполняется, когда d < 50, что означает, что он будет выполняться несколько раз подряд, без учета того, что он уже выполнен.Таким образом, вы получаете несколько таймеров, срок действия которых истекает примерно в одно и то же время.

  • counter и speed, которые вы изменяете в обратном вызове setInterval, относятся к переменным, так как онибыли, когда вызывался setInterval, и не влияли на последующие вызовы shudder, где эти переменные являются экземплярами новых переменных.

  • Вы проверяете только раз в секунду, чтобы увидеть,this.x все еще в пределах границ.Это лучше делать в каждом кадре во время анимации.

  • Плохо выглядит setInterval в функции, которая вызывается для каждого кадра.Это может работать, но вы должны быть очень осторожны, как вы делаете вещи.

Я бы пошел на шаблон, где вы рассчитываете время окончания анимации и просто считывает текущеевремя, чтобы увидеть, если вы еще там.Также убедитесь, что вы поддерживаете состояние (в this) о скорости и т. Д.

Примерно так:

shudder() {
    if (!this.steps) { // not yet (ever) animated?
        this.speed = 0;
        let d = dist(mouseX, mouseY, this.x, this.y);
        if (d < 50) {
            // Adapt these numbers to set the time at which animation should pause/restart:
            this.steps = [0, 500, 1000, 1500, 2000, 2500].map(i => Date.now() + i);
        }
    } else if (this.steps[0] < Date.now()) { // duration completed?
        this.speed = 4 - Math.abs(this.speed); // Toggle between animate and pause
        this.steps.shift(); // Remove a step, since that duration has completed
    }
    if (this.x < this.l || this.x > this.r) this.speed = -this.speed;
    this.x += this.speed;
}
...