首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >P5.js中的基本轨道行星

P5.js中的基本轨道行星
EN

Code Review用户
提问于 2019-01-19 03:57:59
回答 2查看 2.1K关注 0票数 4

我大约一周前就开始学习JavaScript了,我想要一些关于我的代码的意见和建议。这个程序只是创建了一个画布,实例化了围绕太阳运行的5个行星,每个行星都有不同的速度、颜色和大小。

它使用p5.js库,代码可以在p5.js网络编辑器中运行。(在运行脚本之前,您可能希望在粘贴代码之后展开右侧的预览面板。)

代码位于不同的文件中(类Orbiter、额外的数学函数和主代码),但我将把它放在这里一次:

代码语言:javascript
运行
复制
// Converts from degrees to radians.
Math.radians = function(degrees) {
    return degrees * Math.PI / 180;
  };

// Converts from radians to degrees.
Math.degrees = function(radians) {
    return radians * 180 / Math.PI;
  };


class Orbiter {

    constructor(rad, orbitAlt, x = 0, y = 0, orbitAngle = 0, orbitAngleMod = 1, colorR=255, colorG=255, colorB=255, colorA=255){
        this.orbitAngle = orbitAngle; // Angle formed by the radius of the orbit and the x plane.
        this.orbitAngleMod = orbitAngleMod; // Increment/decrement of  orbitAngle
        this.rad = rad; // Radius
        this.orbitAlt = orbitAlt; // Distance to the orbited object's position (Alt for altitude)

        // Position
        this.x = x;
        this.y = y;

        // Color variables
        this.colorR = colorR;
        this.colorG = colorG;
        this.colorB = colorB;
        this.colorA = colorA;
    }

    orbit(object){
        this.x = object.x + this.orbitAlt * cos(Math.radians(this.orbitAngle));
        this.y = object.y + this.orbitAlt * sin(Math.radians(this.orbitAngle));
        this.orbitAngle = this.orbitAngle + this.orbitAngleMod;

        // Reset the angle to 0 after a complete revolution to avoid an ever increasing value.
        if(this.orbitAngle >= 360){
            this.orbitAngle = 0;
        }
    }

    display(){
        noStroke();
        fill(this.colorR, this.colorG, this.colorB, this.colorA);
        return ellipse(this.x, this.y, this.rad, this.rad);
    }


}

let planets = [];
let sun = new Orbiter(100, 0);

function setup(){
    createCanvas(windowWidth-3, windowHeight-3);
    frameRate(144);

    // Set up the Sun's colors and coordinates
    sun.colorR = 255;
        sun.colorG = 200;
        sun.colorB = 0;
    sun.x = windowWidth/2;
    sun.y = windowHeight/2;

    // Instantiate 5 planets
    for(i = 0; i < 5; i++){
        planets[i] = new Orbiter(5 + i * 15, 110 + i*70);
        planets[i].orbitAngleMod= 1.4 - i/7;
        planets[i].orbitAngle= i*5;

        planets[i].colorR = i * 50 + 5;
        planets[i].colorG = 255 - planets[i].colorR;
        planets[i].colorB = 255 - planets[i].colorR;
    }
}

function draw(){
    background(0, 10, 40);

    for(planet of planets){
        planet.orbit(sun);
        planet.display();
    sun.display()
    }

}
代码语言:javascript
运行
复制
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.3/p5.js"></script>

如果您能给我一些关于我的代码结构的反馈,无论它是否符合JavaScript最佳实践,或者如果您在代码中看到任何您认为是错误的或者应该以不同的方式编写的话,我将非常感激。

EN

回答 2

Code Review用户

发布于 2019-02-22 22:03:35

使用p5.js和JavaScript

Math是标准JavaScript库的一部分。您不应该用自己的代码来污染它的命名空间,因为它可能会干扰页面上的其他JavaScript代码。在本例中,Math.degrees()从未被使用过,您可以只使用p5.js的radians()函数而不是编写Math.radians()

Orbiter的构造函数非常笨重,最多有10个参数。你可以把他们中的大部分消灭掉。此外,您应该将颜色指定为单个p5.Color对象,而不是指定四个单独的参数。

应该有一个windowResized()处理程序,以便可以优雅地调整窗口(或堆栈片段)的大小。

物理与动画

卫星绕其轨道被称为主要的的物体。我建议您将参数命名为orbit()方法。

你的行星的角速度是由planets[i].orbitAngleMod= 1.4 - i/7给出的,这不符合物理定律。根据开普勒第三定律T^2 \propto r^3 (其中Tr是轨道周期和半径),所以\omega \propto r^{-\frac{3}{2}}。因此,你们的内行星并不像他们应该的那样快,你们的外部行星也没有像他们应该的那样慢。

if(this.orbitAngle >= 360){ this.orbitAngle = 0; }处理革命的完成可能会导致一些小故障.模块操作将更合适。

我看不出初始化行星初始角到i * 5的意义--相对于x轴,最多4°的偏移量几乎是不可见的。

代码语言:javascript
运行
复制
class Orbiter {
    constructor(sizeRadius, orbitRadius, orbitAngle=0) {
        this.sizeRadius = sizeRadius;
        this.orbitRadius = orbitRadius;
        this.orbitAngle = 0; // degrees relative to x axis

        // 2000 is an arbitrary animation speed (which also depends on the frame rate)
        // The -1.5 exponent is due to Kepler's 3rd Law
        this.orbitAngleDelta = 2000 * Math.pow(orbitRadius, -1.5);
        this.x = this.y = 0;
        this.color = 'white';
    }

    orbit(primary) {
        this.x = primary.x + this.orbitRadius * cos(radians(this.orbitAngle));
        this.y = primary.y + this.orbitRadius * sin(radians(this.orbitAngle));
        this.orbitAngle = (this.orbitAngle + this.orbitAngleDelta) % 360;
    }

    display() {
        noStroke();
        fill(this.color);
        return ellipse(this.x, this.y, this.sizeRadius, this.sizeRadius);
    }
}

let planets = [];
let sun = new Orbiter(100, 0);

function setup() {
    createCanvas(windowWidth - 3, windowHeight - 3);
    frameRate(144);

    sun.x = windowWidth / 2;
    sun.y = windowHeight / 2;
    sun.color = color(255, 200, 0);

    // Instantiate 5 planets
    for (i = 0; i < 5; i++) {
        planets[i] = new Orbiter(5 + 15 * i, 110 + 70 * i);
        let red = i * 50 + 5;
        planets[i].color = color(red, 255 - red, 255 - red);
    }
}

function windowResized() {
    resizeCanvas(windowWidth - 3, windowHeight - 3);
    sun.x = windowWidth / 2;
    sun.y = windowHeight / 2;
}

function draw() {
    background(0, 10, 40);
    sun.display()
    for (planet of planets) {
        planet.orbit(sun);
        planet.display();
    }
}
代码语言:javascript
运行
复制
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.3/p5.js"></script>
票数 5
EN

Code Review用户

发布于 2019-01-23 02:54:24

对我来说很好。但我不是JS专家。;)

有一件事“跳”了我:

代码语言:javascript
运行
复制
if(this.orbitAngle >= 360){
    this.orbitAngle = 0;
}

相反,我会做:

代码语言:javascript
运行
复制
while (this.orbitAngle>360) this.orbitAngle-=360;
while (this.orbitAngle<0) this.orbitAngle+=360;

如果你能提供一个像小提琴这样的游乐场,那就太好了。

@Jamal让我编辑:

  • 当orbitAngles减少时,您的代码会忽略这种情况。
  • 如果orbitAngle超过360,您将其设置为0,但这可能是不正确的。如果你的orbitAngle是365.1呢?将其设置为0是错误的,因为5.1将是正确的值。递减值也是如此。-5.9应该变成350.1,而不是像360。

这就是为什么我建议了一个版本,您可以通过添加/减法360来更正这个值。

如果有人滥用代码并输入非常高的值来改变角度,您最终可能会得到orbitAngle>720,所以只减320是不够的。

另一个建议可能是使用模块化--现在我已经考虑过了。;)

票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/211796

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档