domihein
domihein

Reputation: 23

p5JS - JS Array Push not working as intended

I do get some strange behavior on my JS code. Everytime I push an object into an array, each element in the array gets modified and set to the new object I pushing into the array.

Im setting the object p to x = 0 and y = 0 in the setup function at the beginning.

In the draw loop, I push p into the pTrace array and call the function nextMove(). This function changes the values in p. Then the draw function runs again after a Mouseclick.

let cols = 3;
let rows = 3;

//Position
let p;
//History of Positions
let pTrace = [];

//Moveset for p
let allMoves = [
  { x: 0, y: -1 },
  { x: 1, y: 0 },
  { x: 0, y: 1 },
  { x: -1, y: 0 },
];

//Valid moves based on position
let nextMoves = [];

function setup() {
  createCanvas(400, 400);
  p = {
    x: 0,
    y: 0
  };
}

function draw() {
  background(150);
  frameRate(1);
  
  //Save position in history
  pTrace.push(p);
  
  //Move p to next position based on valid moves
  nextMove();
  console.log(p);
  
  
  noLoop();
}


//Get an array of valid moves for the p position
function nextMove() {
  nextMoves = [];
  if(p.y > 0) {
    nextMoves.push(allMoves[0]);
  }
  if(p.x < cols-1) {
    nextMoves.push(allMoves[1]);
  }
  if(p.y < rows-1) {
    nextMoves.push(allMoves[2]);
  }
  if(p.x > 0) {
    nextMoves.push(allMoves[3]);
  }
  let nM = random(nextMoves);
  p.x += nM.x;
  p.y += nM.y;
}


//rerun draw loop
function mousePressed() {
  draw();
}

Maybe you can help me with this and find my error. Thanks in advance, have a great day!

Upvotes: 1

Views: 328

Answers (1)

milt_on
milt_on

Reputation: 527

That's because objects in Javascript are passed by reference. You are always changing the same object p and then push it to the pTrace array.

You want to pass a copy of the p object and push that copy to your array.

You can copy your object for example by using the spread operator { ...p } or by using Object.assign({}, p)

Something like this should work (now a copy is pushed into the pTrace array:

let cols = 3;
let rows = 3;

//Position
let p;
//History of Positions
let pTrace = [];

//Moveset for p
let allMoves = [
  { x: 0, y: -1 },
  { x: 1, y: 0 },
  { x: 0, y: 1 },
  { x: -1, y: 0 },
];

//Valid moves based on position
let nextMoves = [];

function setup() {
  createCanvas(400, 400);
  p = {
    x: 0,
    y: 0
  };
}

function draw() {
  background(150);
  frameRate(1);
  
  //Save position in history
  pTrace.push({ ...p }); // push a copy
  
  //Move p to next position based on valid moves
  nextMove();
  console.log(p);
  
  
  noLoop();
}


//Get an array of valid moves for the p position
function nextMove() {
  nextMoves = [];
  if(p.y > 0) {
    nextMoves.push(allMoves[0]);
  }
  if(p.x < cols-1) {
    nextMoves.push(allMoves[1]);
  }
  if(p.y < rows-1) {
    nextMoves.push(allMoves[2]);
  }
  if(p.x > 0) {
    nextMoves.push(allMoves[3]);
  }
  let nM = random(nextMoves);
  p.x += nM.x;
  p.y += nM.y;
}


//rerun draw loop
function mousePressed() {
  draw();
}

Upvotes: 1

Related Questions