javascripthtmlcssanimationmouse

Why this JavaScript function sometimes takes good value and works, and sometimes not? Probably a problem with refresh rate of the page


I'm trying to animate a snake composed of segments. These segments should retreat when the mouse is stopped. So I'm calculating the distance and when the mouse is stopped, I'm changing the position and also the opacity value. Sometimes it works in a good and smooth way, sometimes not. The segment created is a part of the snake, that is composed by 10 segments. Every segment follows the path of the cursor inside of the screen, one behind the previous one. It works pretty fine in this, the problem occurs when the execution goes after the else if, when not everytime all the segments are updated to the correct value.

This is the code of the function:

function animateSnake() {
    let previousX = mouseX;
    let previousY = mouseY;


    segments.forEach((segment, index) => {
        const dx = previousX - segment.x;
        const dy = previousY - segment.y;
        const distance = Math.sqrt(dx * dx + dy * dy);

        if (distance >= segmentSize) {
            const angle = Math.atan2(dy, dx);
            segment.x = previousX - Math.cos(angle) * segmentSize;
            segment.y = previousY - Math.sin(angle) * segmentSize;
        }else if (Date.now() - lastMouseMoveTime > 300) {
            const head = segments[0];
            const angleToHead = Math.atan2(head.y - segment.y, head.x - segment.x);
            if (index != 0) {
                segment.x += Math.cos(angleToHead) * segmentSize / 2;
                segment.y += Math.sin(angleToHead) * segmentSize / 2;
                segment.element.style.opacity = 0;
            }
        }else {
            if (index != 0){
                segment.element.style.opacity = 1;
            }
        }

        segment.element.style.transform = `translate(${segment.x}px, ${segment.y}px)`;

        previousX = segment.x;
        previousY = segment.y;
    });


    requestAnimationFrame(animateSnake);
}

I tried to debug but I could only see that the value were highlighted, but not changed.


Solution

  • It's difficult to determine what your snake is like. It's unclear whether it is moving, like changing position, rotating or so, but whatever your snake looks alike, however you want to move your snake, if it's only a translation (moving it inside a 2D pane), then it's safe to assume that all the segments would make the same move, so you could calculate and add dx and dy for your first segment and add those values to all the other segments too. If you want to only move the segments that are close to your mouse pointer, then you could move it like you do in your loop, but beware that the subsequent segments will need to 1. be connected to the previous segment and 2. distanced from your mouse and 3. not overlap with any of your former segments.

    It's unclear what was not very smooth in your test cases, hopefully this answer addressed that problem. If not, then make sure to add a snippet to your question where the problem reproduces and instructions on how we should test it and explain your core concept, like what a segment is, what its size is, whether a snake part takes the entirety of a segment, etc etc.