Reputation: 390
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
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