Tom Burris
Tom Burris

Reputation: 390

JavaScript Breaks After Page Refresh

School project: classmate and I are programming "Agar.io" ourselves, (for practice). Doing well, testing different things, then we get a problem we can't figure out. Seemingly "randomly" the JavaScript doesn't fully execute when opened with a variety of browsers. Aside from the occasional random non-execution on page load, every time you refresh the page, the JavaScript breaks the same as before. It only works after completely closing the browser before re-opening the page. 1: Why is this happening now and wasn't before? 2: How can we fix it? Source code with comments below, thanks, -Tom

var pixelconversion = 100 * Math.PI; //conversion from made-up "mass" (really area), to area in pixels, which will be converted to a radius
var circleX = 400;
var circleY = 250;
var mouseX = 400;
var mouseY = 250;
var mass = 30;
var radius = 20; //just to make it global

function start() {

  drawCircles();
  var interval = setInterval(mainloop, 50);
}

function mainloop() {

  math();

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

  ctx.clearRect(0, 0, 801, 501); //clears the canvas
  drawCircles();
  sleep(100); //more efficient than having the set interval at 150 instead
}

function getCoordinates(e) { //gets the cursors coordinates

  mouseX = e.clientX;
  mouseY = e.clientY;
}

function math() {

  var movement = mass / 4; //arbitrary "4", will be replaced with: 1/mass * someConversion

  radius = Math.sqrt((mass * pixelconversion) / Math.PI); //from area in "mass" to area in pixels, to radius in pixels


  var difY = Math.abs(mouseY - circleY) //finds the difference of each
  var difX = Math.abs(mouseX - circleX) //for "A" and "B" of the triangle

  var c = Math.sqrt(Math.pow(difX, 2) + Math.pow(difY, 2)); //pythagareon theorem to find diagonal distance from mouse to circle
  var scale = movement / c; //use scale to find "A" and "B" of smaller triangle

  if (mouseX > circleX) { //if and else statements are for "movement" in the right direction, (towards the mouse)
    circleX = circleX + difX * scale; //aditional if statements will be added to (next comment)
  } else {
    circleX = circleX - difX * scale; //stop the circle from going back and forth past the cursor
  }

  if (mouseY > circleY) {
    circleY = circleY + difY * scale; //the differce * scale is vital; (fourth comment up)
  } else {
    circleY = circleY - difY * scale;
  }

}

function drawCircles() {

  var can = document.getElementById("canvas");
  var ctx = can.getContext("2d");
  ctx.beginPath();
  ctx.arc(circleX, circleY, radius, 0, 2 * Math.PI); //draws the circle
  ctx.closePath();
  ctx.lineWidth = 5; //just for style
  ctx.fillStyle = 'green';
  ctx.fill();
  ctx.strokeStyle = 'darkgreen'; //just for style
  ctx.stroke();

}

function sleep(milliseconds) { //"homemade" "sleep" "command"
  var start = new Date().getTime();
  for (var i = 0; i < 1; i++) {
    if ((new Date().getTime() - start) > milliseconds) {
      break;
    }
  }
}
<body onload="start()">
  <canvas id="canvas" height="501" width="801" onmousemove="getCoordinates(event)"></canvas>
</body>

Upvotes: 2

Views: 1393

Answers (1)

Jaromanda X
Jaromanda X

Reputation: 1

this line

var scale = movement / c; //use scale to find "A" and "B" of smaller triangle

c can be zero - which makes scale NaN which breaks everything

try this

var scale = c ? movement / c : 0;

I've also added a snippet that demonstrates how smooth requestAnimationFrame is compared to bodgy sleep function

        var pixelconversion = 100 * Math.PI; //conversion from made-up "mass" (really area), to area in pixels, which will be converted to a radius
        var circleX = 400;
        var circleY = 250;
        var mouseX = 400;
        var mouseY = 250;
        var mass = 30;
        var radius = 20; //just to make it global

        function start() {
          document.getElementById("canvas").addEventListener('mousemove', getCoordinates);
          mainloop();
        }

        function mainloop() {

          math();
          drawCircles();
          requestAnimationFrame(mainloop);
        }

        function getCoordinates(e) { //gets the cursors coordinates
          mouseX = e.clientX;
          mouseY = e.clientY;
        }

        function math() {

          var movement = mass / 4; //arbitrary "4", will be replaced with: 1/mass * someConversion

          radius = Math.sqrt((mass * pixelconversion) / Math.PI); //from area in "mass" to area in pixels, to radius in pixels

          var difY = Math.abs(mouseY - circleY) //finds the difference of each
          var difX = Math.abs(mouseX - circleX) //for "A" and "B" of the triangle

          var c = Math.sqrt(Math.pow(difX, 2) + Math.pow(difY, 2)); //pythagareon theorem to find diagonal distance from mouse to circle
          
          var scale = c ? movement / c : 0; //use scale to find "A" and "B" of smaller triangle

          if (mouseX > circleX) { //if and else statements are for "movement" in the right direction, (towards the mouse)
            circleX = circleX + difX * scale; //aditional if statements will be added to (next comment)
          } else {
            circleX = circleX - difX * scale; //stop the circle from going back and forth past the cursor
          }

          if (mouseY > circleY) {
            circleY = circleY + difY * scale; //the differce * scale is vital; (fourth comment up)
          } else {
            circleY = circleY - difY * scale;
          }
        }

        function drawCircles() {
          var can = document.getElementById("canvas");
          var ctx = can.getContext("2d");
          ctx.clearRect(0, 0, 801, 501); //clears the canvas
          ctx.beginPath();
          ctx.arc(circleX, circleY, radius, 0, 2 * Math.PI); //draws the circle
          ctx.closePath();
          ctx.lineWidth = 5; //just for style
          ctx.fillStyle = 'green';
          ctx.fill();
          ctx.strokeStyle = 'darkgreen'; //just for style
          ctx.stroke();
        }
window.addEventListener('load', start);
<canvas id="canvas" height="501" width="801"></canvas>

I'll leave it to you to figure out why the circle dances like a kid watching a japanese cartoon

as per request in comment:

The Window.requestAnimationFrame() method tells the browser that you wish to perform an animation and requests that the browser call a specified function to update an animation before the next repaint. The method takes as an argument a callback to be invoked before the repaint.

You should call this method whenever you're ready to update your animation onscreen. This will request that your animation function be called before the browser performs the next repaint. The number of callbacks is usually 60 times per second, but will generally match the display refresh rate in most web browsers as per W3C recommendation. The callback rate may be reduced to a lower rate when running in background tabs or in hidden s in order to improve performance and battery life.

The callback method is passed a single argument, a DOMHighResTimeStamp, which indicates the current time when callbacks queued by requestAnimationFrame begin to fire. Multiple callbacks in a single frame, therefore, each receive the same timestamp even though time has passed during the computation of every previous callback's workload. This timestamp is a decimal number, in milliseconds, but with a minimal precision of 1ms (1000 µs).

Source: https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame

Upvotes: 1

Related Questions