Raiden
Raiden

Reputation: 411

Oscillation function

Trying to create a function that can dynamically oscillate properties of an object. I've already managed to create it outside of a function, but I can't make it work in one. It's because of the angle variable, which increases each frame. Here's an example to make an object oscillate x and y props in a circle.

Example fiddle.

Initialization...

var obj = new Ball(arguments...),
    target = {
      x: 100,
      y: 100
    },
    angle = 0,
    radius = 50,
    speed = 0.1;

Loop...

// clear canvas
obj.x = target.x + Math.cos(angle) * radius;
obj.y = target.y + Math.sin(angle) * radius;
angle += speed;
// rAF

That works just fine, but when I try to make it reusable and turn it into a function, it doesn't work.

function oscillate(obj, target, angle, radius, speed) {
  obj.x = target.x + Math.cos(angle) * radius;
  obj.y = target.y + Math.sin(angle) * radius;
  angle += speed;
}

How do I make it work in a function?

Upvotes: 0

Views: 968

Answers (1)

Oriol
Oriol

Reputation: 288590

That's because angle is not passed by reference. JS does not have pass by reference.

You can just modify the outer variable by not declare a local one:

var map = document.getElementById('map'),
    fx = map.getContext('2d');
var ball = {
      x: 50,
      y: 50,
      radius: 50
    },
    target = {
      x: map.width / 2,
      y: map.height / 2,
    },
    angle = 0,
    radius = 50,
    speed = 0.1;
ball.draw = function(fx) {
  fx.beginPath();
  fx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);
  fx.fill();
};
function oscillate(obj, target, radius, speed) {
  obj.x = target.x + Math.cos(angle) * radius;
  obj.y = target.y + Math.sin(angle) * radius;
  angle += speed;
}
(function update() {
  fx.clearRect(0, 0, map.width, map.height);
  oscillate(ball, target, radius, speed)
  ball.draw(fx);
  requestAnimationFrame(update);
}());
<canvas id='map'></canvas>

Alternatively, pass an object:

var map = document.getElementById('map'),
    fx = map.getContext('2d');
var ball = {
  x: 50,
  y: 50,
  radius: 50
},
data = {
  obj: ball,
  target: {
    x: map.width / 2,
    y: map.height / 2,
  },
  angle: 0,
  radius: 50,
  speed: 0.1
};
ball.draw = function(fx) {
  fx.beginPath();
  fx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);
  fx.fill();
};
function oscillate(data) {
  data.obj.x = data.target.x + Math.cos(data.angle) * data.radius;
  data.obj.y = data.target.y + Math.sin(data.angle) * data.radius;
  data.angle += data.speed;
}
(function update() {
  fx.clearRect(0, 0, map.width, map.height);
  oscillate(data)
  ball.draw(fx);
  requestAnimationFrame(update);
}());
<canvas id='map'></canvas>

Upvotes: 3

Related Questions