Search code examples
javascriptmathlogic

simulating gravity with error (cos and sin)


I have a problem with my code, I want to make an orbit around my planet but my code doesn't work and I don't know why, it's probably my lack of knowledge on the subject, can you help me?

I think the error happens between line 138 to 155. specifically with the cos and sin functions.

the letters are white for better visualization without the image put the letters as red

HTML code:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
   <canvas id="canvas"></canvas>
    <script src="app.js"></script>
</body>
</html>

CSS code:

* {
    margin: 0;
    padding: 0;
}

html, body {
    width: 100%;
    height: 100%;
}

canvas {
    display: block;
}

JS code:

const planeta = new Image();   
planeta.src = 'planeta.webp';
const fundo = new Image();   
fundo.src = 'fundo.jpg';

let mousemove = null;
let play = true;

const balls = [
    {
        posX: 700,
        posY: 400,
        velocityX: 0,
        velocityY: 0,
        accelerationX: 0,
        accelerationY: 0
    }
];

(function() {
    const canvas = document.getElementById('canvas');
    const context = canvas.getContext('2d');

    window.addEventListener('resize', resizeCanvas, false);
    
    window.addEventListener('mousemove', e => {
        mousemove = e;
    });

    document.addEventListener("keydown", function(event) {
      if(event.code === 'Space') {
        play = !play;
      }
    })

    resizeCanvas(canvas, context);

    loop(canvas, context);

  })();

  function loop(canvas, context) {

    const width = context.canvas.width / 2;
    const height = context.canvas.height / 2;

    window.requestAnimationFrame(function() {
        loop(canvas, context);
    });

    
    context.clearRect(0, 0, width, height);
    resizeCanvas(canvas, context);
    if (mousemove !== null) {
      context.font = "20px Arial";
      context.fillText("X: " + (mousemove.clientX - width) + " Y: " + (height - mousemove.clientY), mousemove.clientX + 20, mousemove.clientY);
    }
    

  }

  function resizeCanvas(canvas, context) {
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    callDrawings(context); 
  }

  function callDrawings(context) {
    drawBackground(context);
    drawColumns(context);
    drawNumbers(context);
    drawImages(context);
    drawArcs(context);
  }

  function drawBackground(context) {
    
    const width = context.canvas.width;
    const height = context.canvas.height;

    context.beginPath();

    context.drawImage(fundo, 0, 0, width, height);

    context.closePath();
    context.stroke();

  }

  function drawImages(context) {

    const width = context.canvas.width / 2;
    const height = context.canvas.height / 2;

    context.beginPath();

    context.drawImage(planeta, width - 250, height - 250, 500, 500)

    context.closePath();
    context.stroke();

  }

  function formatBallInfo(context, ball, width, height, distance) {
    let text = "";
    text += "posX: " + ball.posX + "\n";
    text += "posY: " + ball.posY + "\n";
    text += "velocityX: " + ball.velocityX + "\n";
    text += "velocityY: " + ball.velocityY + "\n";
    text += "accelerationX: " + ball.accelerationX + "\n";
    text += "accelerationY: " + ball.accelerationY + "\n";
    text += "distance: " + distance;

    const lineheight = 15;
    const lines = text.split('\n');

    context.beginPath();
    for (let i = 0; i < lines.length; i++) {
      context.fillText(lines[i], width + ball.posX + 30, height - ball.posY + (i*lineheight));
    }
    context.closePath();
    context.stroke();

  }

  function drawArcs(context) {

    const width = context.canvas.width / 2;
    const height = context.canvas.height / 2;

    balls.forEach(ball => {
        context.beginPath();
        context.arc(width + ball.posX, height - ball.posY, 15, 0, 2 * Math.PI);
        context.fill();
        context.closePath();
        context.stroke();
        
        let distance = Math.sqrt(Math.pow(ball.posX, 2) + Math.pow(ball.posY, 2));

        if(play) {
          let cos = Math.cos(ball.posX / distance);
          let sin = Math.sin(ball.posY / distance);
  
          let forceX = gravitationalForce(2000, distance) * cos;
          let forceY = gravitationalForce(2000, distance) * sin;
  
          ball.accelerationX = forceX;
          ball.accelerationY = forceY;
  
          ball.velocityX = ball.velocityX + ball.accelerationX;
          ball.velocityY = ball.velocityY + ball.accelerationY;
  
          ball.posX = ball.posX + ball.velocityX;
          ball.posY = ball.posY + ball.velocityY;
        }

        formatBallInfo(context, ball, width, height, distance);
        
    });
     
  }

  function drawColumns(context) {

    const width = context.canvas.width;
    const height = context.canvas.height;

    context.beginPath();
    context.strokeStyle = "white";

    context.moveTo(width / 2, 0);
    context.lineTo(width / 2, width);

    context.moveTo(width, height / 2);
    context.lineTo(0, height / 2);

    context.lineWidth = 2;

    context.closePath();

    context.stroke();
  }

  function drawNumbers(context) {

    context.beginPath();
    context.fillStyle = "white";
    const width = context.canvas.width;
    const height = context.canvas.height;
    const widthDividedByTwo = context.canvas.width / 2;
    const heightDividedByTwo = context.canvas.height / 2;
    const spacing = 30;

    // right
    counter = 0;
    while(true) {
        counter += 1;
        if(widthDividedByTwo + counter * spacing < width) {
            context.fillText(counter, widthDividedByTwo + counter * spacing, heightDividedByTwo + 30);
        } else {
            break;
        }
    }

    // left
    counter = 0;
    while(true) {
        counter += 1;
        if(widthDividedByTwo - counter * spacing > 0) {
            context.fillText("-"+counter, widthDividedByTwo - counter * spacing, heightDividedByTwo + 30);
        } else {
            break;
        }
    }

    //down
    counter = 0;
    while(true) {
        counter += 1;
        if(heightDividedByTwo + counter * spacing < height) {
            context.fillText("-"+counter, widthDividedByTwo - 30, heightDividedByTwo + counter * spacing);
        } else {
            break;
        }
    }

    //up
    counter = 0;
    while(true) {
        counter += 1;
        if(heightDividedByTwo - counter * spacing > 0) {
            context.fillText(counter, widthDividedByTwo - 30, heightDividedByTwo - counter * spacing);
        } else {
            break;
        }
    }

    context.closePath();
    context.stroke();

  }

  // planet = 2000
  // planet = 1
  // 2000 * 1 = 2000 = m
  function gravitationalForce(m, d) {
    //const g = 6.67 * 10E-11
    const f = m / (d * d);
    return f;
  }

Solution

  • I discovered that my cos and sin functions were wrong

    // let cos = Math.cos(ball.posX / distance);
    // let sin = Math.sin(ball.posY / distance);
    
    let cos = ball.posX / distance;
    let sin = ball.posY / distance;
    

    And I changed the signs here

    // ball.posX = ball.posX + ball.velocityX;
    // ball.posY = ball.posY + ball.velocityY;
    
    ball.posX = ball.posX - ball.velocityX;
    ball.posY = ball.posY - ball.velocityY;