This commit is contained in:
赵鑫 2022-12-11 21:52:13 +08:00
parent b2534c7efd
commit 072a92ec54
9 changed files with 287 additions and 70 deletions

View File

@ -33,7 +33,7 @@ function drawVector(vector, color = "#FFFFFF") {
}
function vectorProjection(v1, v2) {
const v = v2.copy().normalize();
const sp = v1.dot(v);
return v.setMag(sp);
const v2n = v2.copy().normalize();
const sp = v1.dot(v2n);
return v2n.setMag(sp);
}

29
4.太阳公公.js Normal file
View File

@ -0,0 +1,29 @@
function setup() {
createCanvas(400, 400);
stroke("#FFFF00");
strokeWeight(8);
angleMode(DEGREES);
frameRate(60);
noCursor();
}
function draw() {
background("skyblue");
// 移动原点坐标
push();
translate(mouseX, mouseY);
const a = 1 + (frameCount % 30);
// 画太阳
fill("#FFCC00");
circle(0, 0, 100);
noFill();
arc(-20, 0, 20, 20, -135, -45);
arc(20, 0, 20, 20, -135, -45);
arc(0, 10, 40, 40, 45, 135);
// 画阳光
for (let i = 0, n = 36; i < n; i++) {
line(0, -60 - a * 10, 0, -80 - a * 10);
rotate(360 / n);
}
pop();
}

View File

@ -21,7 +21,7 @@
</style>
<script src="p5/p5.min.js"></script>
<script src="p5/addons/p5.sound.min.js"></script>
<script src="vehicle.js"></script>
<script src="4.太阳公公.js"></script>
</head>
<body>

49
particle.js Normal file
View File

@ -0,0 +1,49 @@
class Particle {
constructor(x, y) {
this.mass = 1;
this.position = createVector(x, y);
this.velocity = createVector(0, 0);
this.gravity = createVector(0, 10); // G = 9.81
this.hue = 0;
this.saturation = 0;
this.brightness = 100;
this.alpha = 1;
this.size = 8;
this.lifetime = 0;
}
move(force) {
if (this.position.y > 600) return;
// 计算加速度
const acceleration = createVector(0, 0);
acceleration.add(this.gravity);
if (force) acceleration.add(force.div(this.mass));
// 计算时间差
const duration = deltaTime / 1000;
this.lifetime += duration;
// 计算速度差及位移
const deltaVelocity = acceleration.mult(duration);
const averageVelocity = deltaVelocity.copy().div(2).add(this.velocity);
const movement = averageVelocity.mult(duration);
// 更新速度及位置
this.velocity.add(deltaVelocity);
this.position.add(movement);
const report = {
time: this.lifetime.toFixed(3),
height: (height - this.position.y).toFixed(3),
velocity: this.velocity.mag().toFixed(3),
};
print(report);
}
show() {
noStroke();
fill(this.hue, this.saturation, this.brightness, this.alpha);
circle(this.position.x, this.position.y, this.size);
}
}
class Particles {
constructor() {}
show() {}
}

14
particle_demo.js Normal file
View File

@ -0,0 +1,14 @@
let particle;
function setup() {
cursor(CROSS);
colorMode(HSB);
createCanvas(600, 600);
particle = new Particle(width / 2, height / 2);
}
function draw() {
background(64);
particle.move();
particle.show();
}

17
sketch-template.js Normal file
View File

@ -0,0 +1,17 @@
function setup() {
cursor(CROSS);
createCanvas(600, 600);
}
function draw() {
background(64);
}
function drawGrid() {
push();
stroke(0, 64);
strokeWeight(1);
for (let x = 0; x < width; x += 10) line(x, 0, x, height);
for (let y = 0; y < height; y += 10) line(0, y, width, y);
pop();
}

View File

@ -1,8 +1,29 @@
function setup() {
cursor(CROSS);
createCanvas(600, 600);
createCanvas(400, 400);
stroke("#FFFF00");
strokeWeight(8);
angleMode(DEGREES);
frameRate(60);
noCursor();
}
function draw() {
background(64);
background("skyblue");
// 移动原点坐标
push();
translate(mouseX, mouseY);
const a = 1 + (frameCount % 30);
// 画太阳
fill("#FFCC00");
circle(0, 0, 100);
noFill();
arc(-20, 0, 20, 20, -135, -45);
arc(20, 0, 20, 20, -135, -45);
arc(0, 10, 40, 40, 45, 135);
// 画阳光
for (let i = 0, n = 36; i < n; i++) {
line(0, -60 - a * 10, 0, -80 - a * 10);
rotate(360 / n);
}
pop();
}

View File

@ -1,60 +1,3 @@
let vehicle1;
let vehicle2;
function setup() {
cursor(CROSS);
createCanvas(600, 600);
vehicle1 = new Vehicle(300, 300, "#CCCCCC");
vehicle2 = new Vehicle(300, 300, "#CC3333");
vehicle2.velocity = randomVector(5);
}
function draw() {
// 追逐鼠标();
// 逃避鼠标();
// 小车追逐();
小车巡游();
}
function 追逐鼠标() {
background(64);
vehicle1.seek({ position: createVector(mouseX, mouseY) });
vehicle1.move();
vehicle1.turn();
vehicle1.drawPath();
vehicle1.show();
}
function 逃避鼠标() {
background(64);
vehicle1.flee({ position: createVector(mouseX, mouseY) });
vehicle1.move();
vehicle1.turn();
vehicle1.drawPath();
vehicle1.show();
}
function 小车追逐() {
background(64);
vehicle1.seek(vehicle2, 20);
vehicle2.move();
vehicle1.move();
if (vehicle2.turn()) vehicle2.velocity = randomVector(random(2, 5));
vehicle1.turn();
vehicle1.drawPath();
vehicle2.show("point");
vehicle1.show();
}
function 小车巡游() {
background(64);
vehicle1.wander();
vehicle1.move();
vehicle1.turn();
vehicle1.drawPath();
vehicle1.show();
}
/**
* 返回可指定大小的随机二维向量
* @param {number} magnitude 向量大小
@ -73,12 +16,12 @@ class Vehicle {
this.velocity = createVector(0, 0);
this.heading = this.velocity.heading();
this.acceleration = createVector(0, 0);
this.maxVelocity = 5;
this.maxVelocity = 6;
this.maxAcceleration = 0.25;
}
seek(target, slowdownDistance = 100) {
const desired = p5.Vector.sub(target.position, this.position);
const desired = p5.Vector.sub(target, this.position);
const distance = desired.mag();
const magnitude =
slowdownDistance > 0 && distance <= slowdownDistance
@ -90,7 +33,7 @@ class Vehicle {
}
flee(target, fleeDistance = 100) {
const desired = p5.Vector.sub(this.position, target.position);
const desired = p5.Vector.sub(this.position, target);
const distance = desired.mag();
const magnitude =
!fleeDistance || fleeDistance <= 0
@ -127,6 +70,32 @@ class Vehicle {
this.acceleration.add(steering);
}
follow(path, ahead = 50) {
// find future point of vehicle
const future = p5.Vector.add(
this.position,
this.velocity.copy().mult(ahead)
);
// noStroke();
// fill("#FF0000");
// circle(future.x, future.y, 5);
// find project point on the path
const v1 = p5.Vector.sub(future, path.start);
const v2 = p5.Vector.sub(path.end, path.start);
const project = path.start.copy().add(vectorProjection(v1, v2));
noStroke();
fill("#00FF00");
circle(project.x, project.y, 5);
// find the distance between project point and future point
const distance = future.dist(project);
// if the distance larger than path width then seek the project point
if (distance > path.width) this.seek(project, -1);
}
move() {
this.acceleration.limit(this.maxAcceleration);
this.velocity.add(this.acceleration);
@ -174,12 +143,12 @@ class Vehicle {
// return false;
// }
drawPath(color = 128) {
drawPath(length = 1024) {
push();
noFill();
stroke(color);
stroke(255, 64);
strokeWeight(1);
if (this.path.length >= 10240) this.path.shift();
if (this.path.length >= length) this.path.shift();
beginShape();
this.path.forEach((v) => {
if (!v) {
@ -204,3 +173,28 @@ class Vehicle {
pop();
}
}
class Path {
constructor(x1, y1, x2, y2, width = 20) {
this.start = createVector(x1, y1);
this.end = createVector(x2, y2);
this.width = width;
}
show() {
push();
stroke(255, 64);
strokeWeight(this.width * 2);
line(this.start.x, this.start.y, this.end.x, this.end.y);
stroke(255);
strokeWeight(1);
line(this.start.x, this.start.y, this.end.x, this.end.y);
pop();
}
}
function vectorProjection(v1, v2) {
const v2n = v2.copy().normalize();
const sp = v1.dot(v2n);
return v2n.setMag(sp);
}

93
vehicle_demo.js Normal file
View File

@ -0,0 +1,93 @@
let vehicle1;
let vehicle2;
let path;
function setup() {
cursor(CROSS);
createCanvas(600, 600);
vehicle1 = new Vehicle(300, 300, "#CCCCCC");
vehicle1.velocity = createVector(6, 0);
vehicle2 = new Vehicle(300, 300, "#CC3333");
vehicle2.velocity = randomVector(6);
path = new Path(0, 300, 600, 300, 20);
}
function draw() {
// 追逐鼠标();
// 逃避鼠标();
// 小车追逐();
// 小车巡游();
小车巡线();
// 道路追逐();
}
function 追逐鼠标() {
background(64);
vehicle1.seek(createVector(mouseX, mouseY));
vehicle1.move();
vehicle1.turn();
vehicle1.drawPath();
vehicle1.show();
}
function 逃避鼠标() {
background(64);
vehicle1.flee(createVector(mouseX, mouseY));
vehicle1.move();
vehicle1.turn();
vehicle1.drawPath();
vehicle1.show();
}
function 小车追逐() {
background(64);
vehicle1.seek(vehicle2.position, 20);
vehicle2.move();
vehicle1.move();
if (vehicle2.turn()) vehicle2.velocity = randomVector(random(2, 5));
vehicle1.turn();
vehicle1.drawPath();
vehicle2.show("point");
vehicle1.show();
}
function 小车巡游() {
background(64);
vehicle1.wander();
vehicle1.move();
vehicle1.turn();
vehicle1.drawPath();
vehicle1.show();
}
function 小车巡线() {
background(0);
path.end.y = mouseY;
vehicle1.follow(path, 20);
vehicle1.move();
vehicle1.turn();
path.show();
vehicle1.drawPath();
vehicle1.show();
}
/**
* 未完成
*/
function 道路追逐() {
background(0);
// path.end.y = mouseY;
vehicle2.follow(path, 50);
vehicle1.seek(vehicle2.position, 100);
vehicle2.flee(vehicle1.position, 100);
vehicle2.move();
vehicle1.move();
vehicle2.turn();
vehicle1.turn();
path.show();
vehicle2.drawPath();
vehicle1.drawPath();
vehicle2.show();
vehicle1.show();
}