0

I'm trying to animate an array of circles using HTML canvas. I also try to save the circle's previous information in order to be able to determin the velocity vectors for later use. However i can't seem to save the previous circles in a global variable. Logging out the circle array and the previous array gives back the same values even if the circle's position changed.

class Vector {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }
  static subst(vector1, vector2){
    return new Vector(vector1.x - vector2.x, vector1.y - vector2.y)
  }
   
  static divd(vector, scalar){
    return new Vector(vector.x/scalar,vector.y/scalar)
  }
}

class Circle {
  constructor(x,y, radius,color,isGrabbed) {
    this.pos = new Vector(x,y)
    this.radius = radius;
    this.color = color;
    this.velocity = new Vector(0,0);
    this.isGrabbed = isGrabbed;
  }

  draw(ctx){
    ctx.beginPath();
    ctx.arc(this.pos.x, this.pos.y, this.radius, 0, Math.PI*2)
    ctx.fillStyle = this.color;
    ctx.fill()
  }

  update(prevPos){
    this.velocity = Vector.subst(this.pos, prevPos)
    console.log(this.velocity)
  }
}

let circles = []
circles.push(new Circle(300, 400, 70, "red", false))
circles.push(new Circle(500, 300, 70, "green", false))
circles.push(new Circle(800, 600, 70, "yellow", false))


let previous = [] // variable for the previous circle array
function update(){
    ctx.clearRect(0,0, canvas.width, canvas.height)


    // iterating through the array of circles and drawing them onto the canvas

    for(let i = 0; i< circles.length; i++){
        circles[i].pos.x +=10; // changes the circle's x-position on every animation frame
        if(previous.length>0){
            circles[i].update(previous[i].pos)
            console.log(previous[i].pos.x,circles[i].pos.x) // both values are the same
        }
    }


    // saving the previous array of circles
    
    for(let i = 0; i< circles.length; i++){
        previous[i] = circles[i]

    }
    requestAnimationFrame(update)
 }
luek baja
  • 1,475
  • 8
  • 20
Gabo
  • 1

1 Answers1

0

I did not understand the code completely, but you question circle array and the previous array gives back the same values has an answer.

This line previous[i] = circles[i] has error. It does not copy the Circle, it uses the old one (link a reference to an object), so if you change new value, the old one will be changed also.

You can try to really copy the circle. Here is an example:

// saving the previous array of circles
for (let i = 0; i< circles.length; i++) {
    let clone = Object.assign( Object.create( Object.getPrototypeOf(circles[i])), circles[i]);
    previous[i] = clone;
}

But if I was doing this code, I would keep the "velocity" or "previous" inside the object itself.

So this would be restricted: circles[i].pos.x +=10;. Instead we will use setter:

class Circle {
  ...
  setPos(newPos) {
    this.velocity = Vector.subst(newPos, this.pos);
    this.pos.x = newPos.x;
    this.pos.y = newPos.y;
  },
  // this is not needed anymore:
  //update(prevPos){
  //   this.velocity = Vector.subst(this.pos, prevPos)
  //   console.log(this.velocity)
  //}
}

...
// So this line: circles[i].pos.x +=10; will be converted to:
circles[i].setPos(new Vector(circles[i].x + 10, circles[i].y));

P.S. setPos(newPos) can be changed to setPos(x,y), so it will simplify the code a bit.

Anton
  • 2,669
  • 1
  • 7
  • 15
  • Thanks a lot for the answer. Though i had to use: let clone = JSON.parse(JSON.stringify(circles[i])) – Gabo Sep 24 '20 at 14:06
  • @Gabo hmm... Ok, but JSON.parse will not keep the classes, only the fields. – Anton Sep 24 '20 at 14:21