NoC (W04): An Imaginary Environment
The Galaxy
p5js Link: the Galaxy (p5js.org)
Idea: In the Poem 😉
Starry Sky Staring at the universe, Stars hanging in the sky. Humans are always curious about the night: That far, To the outside.
Hope my poem can bring you the feeling that the universe brings to me >_<
Coding 01: Let the Stars Shinning
The faraway stars bring us the light from decades ago, telling the ancient stories of the universe to us. The shining stars are the first thing that I want to write in this mini project.
To make the star shine, the most important thing is to control its brightness. I’ve come up with two ways. The first one is using the HSL color code and the other way is to control its transparency. Since the changing of transparency will bring a sense of mystery, I choose this method.
In order to make the star easy to control, I write the class for the sky. In this case, it’s easier to make every star follow the rules of shifting the transparency. And it’s clearer to store their positions and colors.
class Star { constructor() { this.pX = random(width); this.pY = random(height); this.brightness = random(255); this.color = [random(100, 255), random(100, 255), random(100, 255)]; } display() { push(); noStroke(); fill(this.color[0], this.color[1], this.color[2], this.brightness); circle(this.pX, this.pY, 2); pop(); } update() { this.brightness += random(-50, 50); } } function star() { for (let i = 0; i < stars.length; i++) { let s = stars[i]; stars[i].update(); s.display(); } }
In the code, I make the transparency not that continuous to simulate the shining effect. And it seems quite fascinating:
Coding 02: the Big Black Hole
Actually, in the first version of this project, the center of the canvas is a fixed star. However, I want to bring this project a sense of mystery and unknown. Also because I was really shocked and indulge when the big black hole Gargantua was shown up in the film Interstellar. So I changed it into a black hole. This will not only change the visual effect of the project but also is paying tribute o the film.
In order to draw the black hole, I separate it into three parts.
The inner part is quite easy. Just a pure black circle. And outside the circle is two layer halo. The first one is a linear color from gold to white while the second one is gold but has a linear transparency:
fill(0, 0, 0); circle(planets[0].pos.x, planets[0].pos.y, 240); for (let i = 0; i <= 20; i++) { strokeWeight(3); noFill(); stroke(205, 155, 137, i * 2); circle(planets[0].pos.x, planets[0].pos.y, 260 - i); } for (let i = 0; i <= 5; i++) { strokeWeight(3); noFill(); stroke(205 + 5 * i, 155 + 13 * i, 137 + 15 * i, 120 + i * 20); circle(planets[0].pos.x, planets[0].pos.y, 240 - 2 * i); }
Making these halos can make the hole has the visual effect that looks like melting the planet:
Coding 03: Supporting Casts has its Turn
The planets become the supporting casts in front of such an extraordinary black hole.
As for coding the planet, the first thing is adapting the ES6 class model. I passed four variables into the class. They are Diameter, Mass, Orbit Height, and Planet Type. They are all the basic parameters for a planet. After skipping all the physical nouns, I should talk a little bit more about the Type here.
Since I want to simply apply the gravitation to all the planets including the black hole, I directly put the black hole into the planet object. And I use the type to differentiate different objects.
Type == 0 means this object is a black hole. It doesn’t have an orbit height and won’t move its position (Although it’s not that realistic since the black hole should be influenced by the planet as well, the still black hole can bring this project a higher aesthetics level).
Type == 2 means this object is an initial planet. It will appear above the black hole together and do the orbit movement around the black hole.
Type == 1 means this object is a manually placed planet. The start position will be the position of the mouse when the user presses the mouse button and it will have a start velocity according to its oriental relationship with the black hole.
The initialization of the velocity is a great example here:
if (this.type == 0) { this.vel = createVector(0, 0); } else if (this.type == 1) { this.vel = createVector(mouseX - width / 2, mouseY - height / 2); this.vel.rotate(-PI / 2); this.vel.normalize(); this.vel.mult(((G * centerMass) / this.orbit) ** 0.5); } else { this.vel = createVector(-(((G * centerMass) / this.orbit) ** 0.5), 0); }
As for the physical parameters, we can use several Formulas to calculate the vector of its position, velocity, and acceleration.
Coding 04: Our Universe is full of Formula
Firstly, I apply Newton’s law of universal gravitation on every planet and make them able to attract each other.
applyGravitationalAttractionBetween(others) { for (let other of others) { // let vector = p5.Vector.sub(other.pos, this.pos); // let distance = vector.mag(); if (this != other) { let vector = p5.Vector.sub(other.pos, this.pos); let distance = vector.mag(); vector.normalize(); // direction let magnitude = (G * this.mass * other.mass) / (distance * distance); vector.mult(magnitude); this.addForce(vector); } } }
Since we have Newton’s law of universal gravitation and the Formula of Centripetal force, we can easily compute the velocity of a certain orbit height according to the variables that I have passed in.
this.vel = createVector(-(((G * centerMass) / this.orbit) ** 0.5), 0);
In this case, wherever the user clicks, the planet will be able to do a circular motion around the black hole.
Except they are interrupted by…
In order to make the scene more realistic, I add the collision into the rules.
The collision is not directly using kinetic energy and momentum which is quite too complicated to calculate at the moment. I directly make them repel each other to achieve a similar effect of collision and bouncing:
checkCollosionWith(others) { for (let other of others) { if (this != other) { let vector = p5.Vector.sub(other.pos, this.pos); let distance = vector.mag(); if (distance < this.dia / 2 + other.dia / 2) { let force1 = vector.copy(); force1.mult(-1 * other.vel.mag()); // 10%; this.addForce(force1); let force2 = vector.copy(); force2.mult(1 * this.vel.mag()); // 10%; other.addForce(force2); } } } }
And afterward, we reached the final work:
Reflection: It’s Fun to be God
Using the physical formulas to create an environment is just like recreating the realistic on my own. In this world, I can determine what a black hole looks like, and where the planets start their life. The most exciting and amazing part is that I can adjust the fixed constant in a math equation or physical formula. I gain the ability to modify the world. However, the project will be perfect(I think) if I can simulate the collision using kinetic energy and momentum.
Anyway, now I can tell: God not only plays the dice but also write codes.
2/28/23 Update:
Add gravitational lens effect to the background stars