Я делаю модель солнечной системы, используя только p5. js и без box2D, хотя язык / платформа не имеет значения для этого вопроса. Кроме того, все числа и переменные, используемые для описания проблемы, не на 100% точны, но поведение такое же.
Я использовал формулу Ньютона (F = G Mm / r ^ 2) для определения взаимной гравитации между двумя объектами, скажем, A и B. Теперь, чтобы привлечь A к B, я делю эту взаимную гравитацию на массу A, чтобы найти центростремительное ускорение на A, а затем умножаю это на единичный вектор, указывающий на B. При применении этого отношения к обоим A и B, они оба испытывают притяжение друг к другу, обратно пропорциональное их массе.
Теперь, если я оставлю их обоих, чтобы они взаимодействовали друг с другом с массой A = 1000 единиц и массой B = 10 единиц , как и ожидалось, A не тянется и остается неподвижным, но B ускоряется в направлении A. Теперь происходит то, что, когда B достигает центра и летит в противоположном направлении, он уходит дальше, чем расстояние, на которое я поместил его изначально. Это продолжает расти во время каждого цикла ускорения и в какой-то момент исчезает с экрана. Похоже, это нарушение закона сохранения энергии или какой-то серьезный недостаток в моей физике.
Хорошо, перейдем ко второй проблеме, у нас те же объекты и массы. Разница в том, что я даю B (более легкий объект) начальную скорость некоторого значения, скажем, x в положительном направлении оси x. Теперь я помещаю B перпендикулярно оси x A и позволяю им взаимодействовать. на этот раз B движется по эллиптической орбите с двумя проблемами. во-первых, A (более тяжелый объект) не находится в одном из фокусов эллипса, а вместо этого находится в точном его центре, а во-вторых, со временем сама орбита начинает вращаться. Я чувствую, что это вращение вызвано предоставленной начальной скоростью, и чтобы было понятно, скорость применяется только изначально и не применяется к каждому кадру. Траектория этой орбиты выглядит следующим образом:
введите описание изображения здесь
Также обратите внимание, что максимальная протяженность каждой орбиты немного больше, чем предыдущая. Это в значительной степени предыдущая проблема, смешанная с этим.
Следующее, что я сейчас пытаюсь сделать, это применить постоянную тангенциальную скорость к движению вместе с центростремительным гравитационным ускорением. Сообщите мне, будет ли это полезно или весь мой подход нужно изменить.
Также это мой код для симуляции:
var constG;
var axisX;
var planets = [];
function setup() {
createCanvas(500, 500);
//createCanvas(displayWidth, displayHeight);
//fullscreen(true);
constG = 0.0001;//6.67 * pow(10, -11);
axisX = createVector(1, 0);
}
function draw() {
background(0, 5);
for (var planet of planets) {
planet.update();
planet.display();
}
for (var i = 0; i < planets.length; i++){
var selfPlanet = planets[i];
for (var j = 0; j < planets.length; j++){
if (j == i){
continue;
}
var otherPlanet = planets[j];
var gravitalAcc = calcGravitalAcc(selfPlanet, otherPlanet);
selfPlanet.applyForce(gravitalAcc);
}
}
if (planets.length > 0){
planets[0].radius = 15;
planets[0].mass = 100; // this just makes the first planet heavy so that i
planets[0].vel.mult(0); // can test stuff while making it the sun.
planets[0].speed = 0;
}
}
function mousePressed() {
planets.push(new CelestialBody(mouseX, mouseY, 7));
}
function calcGravitalAcc(self, other){
var tempVec = p5.Vector.sub(other.pos, self.pos);
return tempVec.normalize().mult(constG * (other.mass)/pow(tempVec.mag(), 2))
}
и это класс Celestialbody, просто любой типичный класс по простому физическому моделированию:
class CelestialBody {
constructor(x, y, radius) {
this.pos = createVector(x, y);
this.radius = radius;
this.color = color(255);
this.mass = 1;
this.speed = 1;
this.vel = createVector(1, 0) //p5.Vector.random2D();
this.vel.setMag(this.speed);
this.acc = createVector(0, 0);
}
display() {
fill(this.color);
stroke(this.color);
circle(this.pos.x, this.pos.y, this.radius * 2);
}
update() {
this.pos.add(this.vel);
this.vel.add(this.acc);
this.acc.mult(0);
}
applyForce(vForce){
this.acc.add(vForce);
}
}