"Stardust" 2D Gravity Simulator - Follow Up 1: The Planets This is a follow up for the 2D Gravity Simulator-like Game question.



Since then I have developed my javascript skills further, and now I'm using ES6 mainly. Note that even through this code uses the EaselJS library, the question is principally about its design so no EaselJS skill needed.

Also I wanna avoid posting a bigger version of the bible here, so this question is only about the game's Planet class and its properties.

The code is more well divided, but I don't know if this organization is effective, and how can changes in a planet's .physicsBody affect its graphical .skin – colors specially. Any tips and ratings on how I'm using class inheritance are really appreciated.

Also, is there any part that could use a more ES6-ish approach?

Planet class:

class Planet {
    constructor (x, y, radius, color) {
        this.physicsBody = new CircleBody(x, y, radius);
        this.skin = new CircleSkin(x, y, radius, color);
    }
    update (scene) {
        // This part is responsible for changing a planet's radius and animating the transition. I have no idea if this should in fact be made here or elsewhere.
        if (this.physicsBody.radius !== this.skin.radius) {
            this.skin.scaleX = this.skin.scaleY = this.skin.radius / this.physicsBody.radius;
            this.skin.radius = this.physicsBody.radius;
            this.skin.redraw();
            createjs.Tween.get(this.skin, {override: true}).to({scaleX: 1, scaleY: 1}, 1000, createjs.Ease.elasticOut);
        }
        if (!this.physicsBody.destroyed) {
            this.skin.x = this.physicsBody.x;
            this.skin.y = this.physicsBody.y;
        } else scene.removeChild(this);
    }
}


CircleBody class:

class CircleBody extends PhysicsBody {
    constructor (x, y, radius) {
        super(x, y);
        this.radius = radius;
    }
    get area () {
        return this._area;
    }
    set area (newValue) {
        this._area = newValue;
        this._radius = Math.sqrt(newValue / Math.PI / 4);
    }
    get radius () {
        return this._radius;
    }
    set radius (newValue) {
        this._radius = newValue;
        this._area = 4 * Math.PI * newValue * newValue;
    }
    get mass () {
        return this.area * this.density;
    }
}


PhysicsBody class:

class PhysicsBody {
    constructor (x, y) {
        this.x = x;
        this.y = y;

        this.px = x;
        this.py = y;

        this.vx = 0;
        this.vy = 0;

        this.density = 1;

        this.affectedByGravity = true;
        this.static = false;
        this.collision = null;
        this.destroyed = false;
    }
    get dynamic () {
        return !this.static;
    }
    set dynamic (newValue) {
        this.static = !newValue;
    }
    get velocity () {
        return new Vector(this.vx, this.vy);
    }
    clearCollisions () {
        this.collision = null;
    }
}


CircleSkin class:

class CircleSkin extends Skin {
    constructor (x, y, radius, color) {
        super(x, y, color);
        this.radius = radius;
        this.redraw();
    }
    redraw (resolution) {
        var r = this.radius;
        this.graphics.clear();
        this.graphics.f(this.color).dc(0, 0, r);
        //this.cache(-r, -r, r * 2, r * 2, resolution || 1);
    }
}


Skin class:

class Skin extends createjs.Shape {
    constructor (x, y, color) {
        super();
        this.x = x;
        this.y = y;
        this.color = color;
    }
}


And finally, this is the class usage in engine:

for (var i = 0; i &lt; 1024; ++i) {
    var x = Utils.getRandomInt(0, innerWidth),
        y = Utils.getRandomInt(0, innerHeight);
    var myPlanet = new Planet(x, y, 2, Utils.getRandomItem(colors));
    myPlanet.physicsBody.n = i;
    myScene.addChild(myPlanet);
}


Utils and Vector dependencies are out of scope and I think their method names are pretty clear so no declaration needed here.
Btw I like the idea of the game/demo! 

It would be nice to see a case where a binary star emerges.

Back to code review:

In Class CicleBody

 get mass () {
         return this.area * this.density;
 }


the this.area - did you intentianally wanted to hit the getter of area or perhaps will be better to use the internal this._area?

PhysicsBody class:

As naming goes, the usual convention is to name functions so they reflect what's going on in the code. In that context, I would have that as a function createVelocity() to indicate that in fact you're creating an object.

 get velocity () { // better name: createVelocityVector()
     return new Vector(this.vx, this.vy);
 }


That is important for the performance conscious programmers cause every extra new object or function call might have impact on the performance.

CircleSkin class:

class CircleSkin extends Skin {
    constructor (x, y, radius, color) {
        super(x, y, color);
        this.radius = radius;
        this.redraw(); // &lt;------?!!
    }


It is not usual to have canvas work inside of a object constructor.
Normally you'd have the draw logic invoked by the render timer.
Normally as the JS games are implemented with two continuous timers: 

1) core timer - this timer runs the game logic.

2) render timer - this timer runs every ~300 ms, reads the some shared data structure, updated by the core timer, and renders it to the canvas. This way you guarantee 30 fps and your game feels smooth and responsive.

redraw (resolution) {
        var r = this.radius;
        this.graphics.clear();
        this.graphics.f(this.color).dc(0, 0, r);
        //this.cache(-r, -r, r * 2, r * 2, resolution || 1);
    }
}


From the alone is not clear what are resolution and graphics.

graphics feels like enhanced canvas.context2d, if yes, in my opinion is better to pass it as parameter. This way you can easily reuse the code with different graphic context.

My version of that method would look something along the lines:

render(graphics) {
  var r = this.radius;
  graphics.clear();
  graphics.f(this.color).dc(0, 0, r);
}


You mentioned you are using EasyJS .. I am not familiar with that library but it cannot be too different than the above mentioned structure. Perhaps the library is implementing the timers for you and is providing you with this.variable for a canvas like object.

That's okay, however, I would recommend you to open the hood and read the code of the library - you will need to understand in order to be able to write code with good performance.   

I wrote a review for a similar question, have a look : https://codereview.stackexchange.com/a/135326/111698.
Hope it helps you.

-- side note --

Ha-Ha on Utils.getRandomInt(0, innerWidth)
I think everyone has implemented a version of that in his code. 
Perhaps, they could add that to the Math lib :)