122 lines
4.1 KiB
HTML
122 lines
4.1 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="zh">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
|
|
<link rel="stylesheet" href="/css/style.css" />
|
|
<title>引力模拟</title>
|
|
<script src="/p5/p5.min.js"></script>
|
|
<script src="/p5/addons/p5.sound.min.js"></script>
|
|
<script src="/lib/utils.js"></script>
|
|
<script>
|
|
const planets = [];
|
|
const plantsNumber = 10;
|
|
let sun;
|
|
|
|
function setup() {
|
|
createCanvas(1728, 972);
|
|
noStroke();
|
|
colorMode(HSB);
|
|
cursor(CROSS);
|
|
frameRate(60);
|
|
sun = createVector(width / 2, height / 2);
|
|
for (let i = 0; i < plantsNumber; i++) {
|
|
const planet = new Planet(random(width), random(height));
|
|
planet.vel = p5.Vector.random2D();
|
|
planets.push(planet);
|
|
}
|
|
}
|
|
|
|
function draw() {
|
|
background(0);
|
|
drawGrid(32);
|
|
|
|
for (let i = 0; i < plantsNumber; i++) {
|
|
planets[i].update();
|
|
planets[i].drawPath();
|
|
}
|
|
for (let i = 0; i < plantsNumber; i++) {
|
|
planets[i].show();
|
|
}
|
|
fill("#FFFF77");
|
|
circle(sun.x, sun.y, 8);
|
|
|
|
textInfo("引力模拟", "2022-12-12");
|
|
}
|
|
|
|
class Planet {
|
|
constructor(x, y) {
|
|
this.pos = createVector(x, y);
|
|
this.vel = createVector(0, 0);
|
|
this.acc = createVector(0, 0);
|
|
this.color = color(random(0, 255), 255, 255);
|
|
this.path = [];
|
|
}
|
|
update() {
|
|
this.acc = p5.Vector.sub(sun, this.pos);
|
|
const dist = this.acc.mag() / 10;
|
|
this.acc.normalize().div(dist * dist);
|
|
this.vel.add(this.acc);
|
|
this.pos.add(this.vel);
|
|
this.path.push(this.pos.copy());
|
|
if (this.path.length > 1024) this.path.shift();
|
|
}
|
|
drawPath() {
|
|
push();
|
|
noFill();
|
|
let h = hue(this.color);
|
|
stroke(color(h, 255, 32));
|
|
strokeWeight(1);
|
|
beginShape();
|
|
this.path.forEach((v, i) => {
|
|
vertex(v.x, v.y);
|
|
});
|
|
endShape();
|
|
pop();
|
|
}
|
|
show() {
|
|
push();
|
|
translate(this.pos.x, this.pos.y);
|
|
|
|
push();
|
|
rotate(this.vel.heading());
|
|
const vel = this.vel.copy().mult(10);
|
|
vel.limit(50);
|
|
stroke("#007700");
|
|
line(0, 0, vel.mag(), 0);
|
|
line(vel.mag(), 0, vel.mag() - 2, 2);
|
|
line(vel.mag(), 0, vel.mag() - 2, -2);
|
|
pop();
|
|
|
|
push();
|
|
rotate(this.acc.heading());
|
|
const dir = this.acc.copy().mult(1000);
|
|
dir.limit(50);
|
|
stroke("#770000");
|
|
line(0, 0, dir.mag(), 0);
|
|
line(dir.mag(), 0, dir.mag() - 2, 2);
|
|
line(dir.mag(), 0, dir.mag() - 2, -2);
|
|
pop();
|
|
|
|
noStroke();
|
|
fill(this.color);
|
|
circle(0, 0, 4);
|
|
pop();
|
|
}
|
|
}
|
|
|
|
function mouseClicked() {}
|
|
|
|
function switchFullscreen() {
|
|
let fs = fullscreen();
|
|
fullscreen(!fs);
|
|
}
|
|
</script>
|
|
</head>
|
|
|
|
<body>
|
|
<main></main>
|
|
</body>
|
|
</html>
|