This commit is contained in:
赵鑫 2022-12-07 00:18:36 +08:00
parent f910249538
commit 12b2f663bc

View File

@ -0,0 +1,234 @@
// let width = 800;
// let height = 800;
let vehicle;
let target;
let demo = "wander";
function setup() {
createCanvas(width, height);
vehicle = new Vehicle();
target = new Target();
if (demo == "wander") {
vehicle.maxVelocity = 10;
vehicle.maxSteering = 5;
vehicle.velocity = p5.Vector.random2D().mult(vehicle.maxVelocity);
}
}
function draw() {
background("#333333");
switch (demo) {
case "seek2":
demoSeek2();
break;
case "arrive":
demoSeek(true);
break;
case "wander":
demoWander();
break;
default:
demoSeek();
}
}
class Vehicle {
constructor() {
this.position = createVector(0, 0);
this.velocity = createVector(0, 0);
this.acceleration = createVector(0, 0);
this.size = 32;
this.color = "#FFFFFF";
this.maxVelocity = 8;
this.maxSteering = 0.5;
this.path = [];
this.pathes = [];
}
seek(target, arrive = false) {
let steering = p5.Vector.sub(target.position, this.position);
let desiredVelocity = this.maxVelocity;
if (arrive) {
let slowdownDistance = this.size * 3;
let distance = steering.mag();
if (distance < slowdownDistance) {
desiredVelocity = map(distance, 0, 100, 0, this.maxVelocity);
}
}
steering.setMag(desiredVelocity);
steering.sub(this.velocity);
return steering;
}
flee(target) {
let steering = this.seek(target).mult(-1);
return steering;
}
wander() {
let wanderPoint = this.velocity.copy();
wanderPoint.setMag(100);
wanderPoint.add(this.position);
// stroke(255);
// let x1 = wanderPoint.x + -25 * cos(PI / 2 + this.velocity.heading());
// let y1 = wanderPoint.y + -25 * sin(PI / 2 + this.velocity.heading());
// let x2 = wanderPoint.x + 25 * cos(PI / 2 + this.velocity.heading());
// let y2 = wanderPoint.y + 25 * sin(PI / 2 + this.velocity.heading());
// line(x1, y1, x2, y2);
noStroke();
fill("#F063A4");
let offset = map(noise(Date.now() / 1000), 0, 1, -50, 50);
let x = offset * cos(PI / 2 + this.velocity.heading());
let y = offset * sin(PI / 2 + this.velocity.heading());
wanderPoint.add(x, y);
circle(wanderPoint.x, wanderPoint.y, 8);
let steering = wanderPoint.sub(this.position);
return steering;
}
update(steering) {
if (steering) {
steering.limit(this.maxSteering);
this.acceleration.add(steering);
}
this.velocity.add(this.acceleration);
this.velocity.limit(this.maxVelocity);
this.position.add(this.velocity);
this.acceleration.set(0);
}
show() {
noFill();
if (this.pathes.length >= 10) this.pathes.shift();
stroke(255);
strokeWeight(2);
[...this.pathes, this.path].forEach((path, i) => {
let c = map(i, 0, this.pathes.length, 127, 255);
let w = map(i, 0, this.pathes.length, 1, 5);
stroke(c);
strokeWeight(w);
beginShape();
path.forEach((v) => vertex(v.x, v.y));
endShape();
});
// stroke(255);
// strokeWeight(4);
// beginShape();
// this.path.forEach((v) => {
// vertex(v.x, v.y);
// });
// endShape();
push();
noStroke();
fill(this.color);
translate(this.position.x, this.position.y);
rotate(this.velocity.heading());
triangle(
this.size / 2,
0,
-this.size / 2,
-this.size / 4,
-this.size / 2,
this.size / 4
);
pop();
}
edges() {
if (this.position.x < 0) {
this.position.x = width;
return true;
} else if (this.position.x >= width) {
this.position.x = 0;
return true;
}
if (this.position.y < 0) {
this.position.y = height;
return true;
} else if (this.position.y >= height) {
this.position.y = 0;
return true;
}
return false;
}
bounce() {
if (this.position.x <= this.size / 2) {
this.position.x = this.size / 2;
this.velocity.x *= -1;
} else if (this.position.x > width - this.size / 2) {
this.position.x = width - this.size / 2;
this.velocity.x *= -1;
}
if (this.position.y <= this.size / 2) {
this.position.y = this.size / 2;
this.velocity.y *= -1;
} else if (this.position.y >= height - this.size / 2) {
this.position.y = height - this.size / 2;
this.velocity.y *= -1;
}
}
}
class Target extends Vehicle {
constructor() {
super();
this.position = createVector(random(width), random(height));
this.color = "#F063A4";
this.size = 32;
this.maxVelocity = 6;
this.maxSteering = 1;
}
show() {
push();
stroke(255);
strokeWeight(1);
fill(this.color);
circle(this.position.x, this.position.y, this.size);
pop();
}
}
function demoSeek(arrive) {
target.position.x = mouseX;
target.position.y = mouseY;
let steering = vehicle.seek(target, arrive);
vehicle.update(steering);
target.show();
vehicle.show();
}
function demoWander() {
let steering = vehicle.wander();
vehicle.update(steering);
if (vehicle.edges()) {
vehicle.pathes.push(vehicle.path);
vehicle.path = [];
}
if (frameCount % 1 == 0) vehicle.path.push(vehicle.position.copy());
vehicle.show();
}
function demoSeek2() {
let distance = p5.Vector.dist(vehicle.position, target.position);
if (distance < target.size / 2) {
target.position = createVector(random(width), random(height));
target.acceleration = createVector(0, 0);
target.velocity = createVector(0, 0);
}
let seekSteering = vehicle.seek(target);
let fleeSteering = target.flee(vehicle);
vehicle.update(seekSteering);
target.update(fleeSteering);
target.bounce();
target.show();
vehicle.show();
}