0
\$\begingroup\$

How can I move an object in a heart shaped pattern? I have a move(x, y) function that I can use to move the object, but how to I make a function that will move the object in a heart shaped pattern, with something like a setInterval?

\$\endgroup\$
3
\$\begingroup\$

You can find a mathematical equation that looks best to you on your own. A good starting point would be here: wolfram

As far as implementing it, here is some sample code I drew up that models a cardioid (relatively heart-shaped, though I'm sure you can find something better). The equation is : r = a + a * sin(angle) where the angle is in radians and a is the amplitude. It's equation is polar (you get the radius from the angle), so I do a little conversion to get x and y coords from it (sorry, this was maybe a bad example to pick :p ).

var c = document.getElementById("c");
var ctx = c.getContext("2d");

var arr = [];

var center = {x: 100, y: 50};

var start = 0;
var stop = Math.PI * 2; //radians

var resolution = 60; //how many points to connect
var step = stop/resolution; //angle increment per point

ctx.beginPath();
for(var i = 0; i < resolution+1; i++) {
  var angle = step * i;
  var r = 50 + 50 * Math.sin(angle);
  var point = {
    x: center.x + r * Math.cos(angle),
    y: center.y + r * Math.sin(angle)
  }
  if(i !== 0) ctx.lineTo(point.x, point.y); //connecting points
  else ctx.moveTo(point.x, point.y); //starting point
  arr.push(point); //create an array of points
}

ctx.stroke();
<canvas id="c" style="border:1px solid black"></canvas>

Anyway, now you can send points.x and points.y to your move function each frame by using that array arr. Let me know if you have any questions.

Quick Update:

Ok, I was thinking about this again and realized that my quick method for drawing out a cardioid is not the most optimal method for you to actually update your object's position... so I made another short example - this time I made a cardioid function so each frame you update the position by calling this function (instead of getting the next element in an array). I used requestAnimationFrame because it's more awesome than setInterval - but that's a separate topic. Anyway, the code is heavily commented, so take a read and let me know if I should explain anything more.

var c = document.getElementById("c");
    var ctx = c.getContext("2d");

    var center = {x: 100, y: 35};

    var start = 0;
    var stop = Math.PI * 2; //360 degrees in radians

    var player = { x: 0, y: 0, r: 5 };

    function cardioid(time) { // time range is 0 to 1
        var angle = (stop - start) * time; //get angle based on time
        var r = 50 + 50 * Math.sin(angle); // The cardioid equation with amplitude of 50
        var point = { //convert from the polar equation to x and y coords.
            x: center.x + r * Math.cos(angle),
            y: center.y + r * Math.sin(angle)
        }
        return point;
    }

    const TOTALTIME = 2; //seconds
    var timer = 0;

    var last = 0;
    function main(ms) { //this is an example loop
        requestAnimationFrame(main);

        const t = ms / 1000;
        dt = t - last; // time between last frame and this frame (delta time)
        last = t;

        timer += dt; // add to the timer

        ctx.clearRect(0,0,c.width,c.height); //clear canvas
        
        //update player position
        if(timer <= TOTALTIME) {
            var position = cardioid(timer/TOTALTIME); //force the range to be from 1 to 0 even though the totaltime is > 1
            player.x = position.x;
            player.y = position.y;
        } else {
            timer = 0; //reset
        }
        //draw

        ctx.beginPath();
        ctx.arc(player.x, player.y, player.r, 0, 2*Math.PI); //made player a circle
        ctx.fillStyle = '#ff0000';
        ctx.fill();
}
requestAnimationFrame(main);
        
<canvas id="c" style="border:1px solid black"></canvas>

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.