Class function looping/setInterval issues

Ok, I’m trying to do something rather tricky here in p5.

Take a look at my shudder class inside my Trees class:

function draw() {
background(0, 111, 10);
trees.trunk();
trees.leaves();
trees.shudder();
}

class Trees {
constructor(x, y) {
this.x = x,
this.y = y,
this.l = this.x - 2,
this.r = this.y + 2,
this.a = 0
}
trunk() {
noStroke();
fill(126, 60, 1);
rect(this.x + 3, this.y, 14, 40);
triangle(this.x + 10, this.y + 30, this.x - 4, this.y + 40, this.x + 24, this.y + 40);
}
leaves() {
fill(71, 215, 45);
ellipse(this.x + 3, this.y - 5, 25);
ellipse(this.x + 10, this.y - 15, 25);
ellipse(this.x + 17, this.y - 5, 25);
}
shudder() {
let d = dist(mouseX, mouseY, this.x, this.y);
if (d < 50) {
this.a = 4;
if (this.x < this.l || this.x > this.r) {
this.a = this.a * -1;
}
} else {
this.a = 0;
}
this.x = this.x + this.a;
}
}

As you can see I’m making this tree shudder back and forth when I click on it which is working! However, I’m trying to simulate it shaking as if it’s being stuck with an axe three times. i.e I’d like it to start juddering half a second, then stop, start, stop, start and then permanently stop.

I’ve tried my best as you can see here:

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

But no dice. I get this in the console:

I realise it might be the fact that the class is called inside a loop might be screwing it up.
the counter is just so I can see what’s going on inside the setInterval function.
Do I have to make another function and call it in a non-looping function to make setInterval work nicely?

I should mention I’m using the p5 Library but I don’t think it would affect this too much apart from the mouseX and mouseY pre-defined functions.

Can anybody solve this puzzle?

Many Thanks!

Am I not using this. correctly? You mean This.a?

I have corrected to the following:

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;
}

But Still that doesn’t solve my problem :confused:

const intervals = setInterval(function () {
  counter++;
  this.a = 4; // <- The this keyword here isn't of datatype Trees!
  // ...

The function arg passed to setInterval() has its this either undefined or the same as window. :fearful:

Passing a fat arrow => lambda instead would lock its this to the same current context as method Trees::shudder() though: :bulb:

shudder() {
  const d = dist(mouseX, mouseY, this.x, this.y);
  let counter = 0;
  if (d < 50) {
    const intervals = setInterval(() => {
      ++counter;
      this.a = 4; // <- The this keyword here is now of datatype Trees!
      // ...

I had put this.a = 0; in the constructor so I just assumed it was working like any other variable.
Would my attempt at coding this work if I switched to the speed variable I just created?

Sorry, I don’t have time to deep study your code now.
I was just pointing out a famous common JS this bug.

this.a isn’t a variable but a property of class Trees.
At least as long as we make sure that this points out to the current Trees reference whenever we call a Trees method.

:open_mouth: This is sort of working!

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;
  }

Conole.log works if I click inside my mouseX, mouseY radius and click out again. If I leave it toggled on though it just does that weird thing in the picture I showed you.

The animation has stopped now though. Any ideas why?