我正在尝试调用一个名为 Planets 的行星数组,但每当我使用 j 调用数组中的对象时,如 Planets[j]; X 和 Y 元素以看似随机的间隔变为 NaN/无穷大。每当我使用 i 调用对象时,如在 Planets[i] 中; X 和 Y 元素完全没问题。我做错了什么?
我尝试将嵌套的 for 循环缩小为 while 循环,将变量从 var 更改为 let 等,并将冲突的变量名称(例如 generatePlanets() 中的 tempPlanet 更改为 hempPlanet 以避免与 iterate() 冲突
let cv = document.getElementById("canvas");
let context = cv.getContext("2d");
let wh = window.innerHeight;
let ww = window.innerWidth;
cv.width = ww;
cv.height = wh;
cv.style.background = "#ffff12";
const numPlanets = 10;
const gridSize = 500;
const maxMass = 50
const gFactor = 0.667;
const timeScale = 1;
let Planets = [];
class Planet {
Mass = 0;
X = 0;
Y = 0;
VelX = 0;
VelY = 0;
constructor(X, Y, Mass, VelX, VelY) {
var Mass = Mass;
var X = X;
var Y = Y;
var VelX = VelX;
var VelY = VelY;
}
getMass() {
return this.Mass;
}
getX() {
return this.X;
}
getY() {
return this.Y;
}
getVelX() {
return this.VelX;
}
getVelY() {
return this.VelY;
}
}
function generateMass(maxMass) {
// ensures mass is above 1
mass = Math.round((Math.random() * (maxMass - 1)) + 1);
return mass;
}
function generateCoordinate(gridSize) {
let coordinate = Math.round(Math.random() * gridSize);
return coordinate;
}
function generatePlanets(numPlanets, maxMass, gridSize) {
for (i = 0; i < numPlanets; i++) {
let hempPlanet = new Planet();
mass = generateMass(maxMass);
x = generateCoordinate(gridSize);
y = generateCoordinate(gridSize);
hempPlanet.Mass = mass;
hempPlanet.X = x;
hempPlanet.Y = y
Planets[i] = hempPlanet;
}
}
function calculateDistance(x1, x2, y1, y2) {
if (x1 > x2) {
bigX = x1;
littleX = x2;
} else {
bigX = x2;
littleX = x1;
}
if (y1 > y2) {
bigY = y1;
littleY = y2;
} else {
bigY = y2;
littleY = y1;
}
return Math.sqrt((bigX - littleX) ^ 2 + (bigY - littleY) ^ 2);
}
function iterate(Planets) {
// Velocity = delta s / delta time
// Velocity = prevpos - pos / timestep
let i = 0;
let j = 0;
while (i < numPlanets) {
// newtonian gravity = m1*m2*g/dist^2
//unfortunately it will goober out if dist is less than one
//so safer equation is m1*m2*g/(dist^2+5)
// can increase the +5 to anything to make it safer but slower and less accurate
let planet = Planets[i];
let planetMass = planet.getMass();
let planetX = planet.getX();
let planetY = planet.getY();
let planetVelX = planet.getVelX();
let planetVelY = planet.getVelY();
let addedPosX = 0;
let addedPosY = 0;
var tempPlanet = Planets[j];
if (tempPlanet !== planet) {
console.log(tempPlanet)
let tempPlanetMass = tempPlanet.getMass();
let tempPlanetX = tempPlanet.getX();
let tempPlanetY = tempPlanet.getY();
let tempPlanetVelX = tempPlanet.getVelX();
let tempPlanetVelY = tempPlanet.getVelY();
let distance = calculateDistance(tempPlanetX, planetX, tempPlanetY, planetY);
let distX = (planetX - tempPlanetX);
let distY = (planetY - tempPlanetY);
let addedDist = distX + distY;
let xMultiplier = distX / addedDist; //change in x position when multiplied by gravity
let yMultiplier = distY / addedDist; //change in y position when multiplied by gravity
let gravity = (planetMass + tempPlanetMass * gFactor) / (distance ^ 2 + 5);
let gravityX = gravity * xMultiplier;
let gravityY = gravity * yMultiplier;
addedPosX += gravityX;
addedPosY += gravityY;
}
Planets[i].X = addedPosX + planetX;
Planets[i].Y = addedPosY + planetY;
j++;
if (j % numPlanets == 0) {
i++;
j = 0;
}
}
}
function drawPlanets(Planets) {
for (i = 1; i < numPlanets; i++) {
let planet = Planets[i];
let planetX = planet.x;
let planetY = planet.y;
context.fillRect(planetX - 5, planetX, planetY - 5, planetY);
}
}
function main() {
generatePlanets(numPlanets, maxMass, gridSize);
iterate(Planets);
drawPlanets(Planets);
}
main()
<canvas id="canvas"></canvas>
我自己发现的。我在行星对象内用于 X 和 Y 坐标的变量名称是“x”和“y”,出于某种原因,javascript 有时将其读取为 NaN 或无穷大。这可以通过将变量名称更改为其他名称来解决。