This commit is contained in:
赵鑫 2022-12-11 02:48:53 +08:00
parent 60360e70b5
commit c9bbf29b9d
12 changed files with 252 additions and 400 deletions

View File

@ -1,256 +0,0 @@
const canvasWidth = 800;
const canvasHeight = 800;
const backgroundColor = "#333333";
let vehicle;
let target;
let demo = "wander";
function setup() {
createCanvas(canvasWidth, canvasHeight);
cursor(CROSS);
vehicle = new Vehicle(0, 0);
target = new Target(canvasWidth / 2, canvasHeight / 2);
if (demo == "wander") {
vehicle.maxVelocity = 5;
vehicle.maxSteering = 3;
vehicle.velocity = createVector(1, 1);
}
}
function draw() {
background(backgroundColor);
switch (demo) {
case "seek2":
demoSeek2();
break;
case "arrive":
demoSeek(true);
break;
case "wander":
demoWander();
break;
default:
demoSeek();
}
}
class Vehicle {
constructor(x, y) {
this.position = createVector(x, y);
this.velocity = createVector(0, 0);
this.acceleration = createVector(0, 0);
this.color = "#FFFFFF";
this.size = 32;
this.maxVelocity = 6;
this.maxSteering = 0.25;
this.path = [];
this.drawPath = true;
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 = canvasWidth;
return true;
} else if (this.position.x >= canvasWidth) {
this.position.x = 0;
return true;
}
if (this.position.y < 0) {
this.position.y = canvasHeight;
return true;
} else if (this.position.y >= canvasHeight) {
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;
return true;
} else if (this.position.x > canvasWidth - this.size / 2) {
this.position.x = canvasWidth - this.size / 2;
this.velocity.x *= -1;
return true;
}
if (this.position.y <= this.size / 2) {
this.position.y = this.size / 2;
this.velocity.y *= -1;
return true;
} else if (this.position.y >= canvasHeight - this.size / 2) {
this.position.y = canvasHeight - this.size / 2;
this.velocity.y *= -1;
return true;
}
return false;
}
}
class Target extends Vehicle {
constructor(x, y) {
super(x, y);
this.position = createVector(random(canvasWidth), random(canvasHeight));
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(canvasWidth),
random(canvasHeight)
);
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();
}
/**
* 获取随机向量可指定大小
* @param {number} magnitude 向量大小
* @return {p5.Vector} vector 随机向量
*/
function randomVector(magnitude) {
let vector = p5.Vector.random2D();
if (magnitude) vector.mult(magnitude);
return vector;
}

39
1003.矢量的投影.js Normal file
View File

@ -0,0 +1,39 @@
let v0, v1, v2, v3;
function setup() {
createCanvas(600, 400);
cursor(CROSS);
v0 = createVector(200, 200);
v1 = createVector(300, 100);
}
function draw() {
v2 = createVector(mouseX, mouseY).sub(v0).div(2);
v3 = vectorProjection(v2, v1);
background(0);
stroke("#777777");
translate(v0.x, v0.y);
line(v2.x, v2.y, v3.x, v3.y);
drawVector(v1, "#FF0000");
drawVector(v2, "#00FF00");
drawVector(v3, "#FFFF00");
}
function drawVector(vector, color = "#FFFFFF") {
push();
fill(color);
stroke(color);
line(0, 0, vector.x, vector.y);
circle(0, 0, 4);
translate(vector.x, vector.y);
rotate(vector.heading());
triangle(0, 0, -4, -2, -4, +2);
pop();
}
function vectorProjection(v1, v2) {
const v = v2.copy().normalize();
const sp = v1.dot(v);
return v.setMag(sp);
}

BIN
favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -3,8 +3,8 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>p5.js example</title> <link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
<link rel="shortcut icon" href="data:" type="image/x-icon" /> <title>p5.js</title>
<style> <style>
* { * {
padding: 0; padding: 0;
@ -12,10 +12,16 @@
box-sizing: border-box; box-sizing: border-box;
background-color: gray; background-color: gray;
} }
body {
display: flex;
height: 100vh;
justify-content: center;
align-items: center;
}
</style> </style>
<script src="p5/p5.min.js"></script> <script src="p5/p5.min.js"></script>
<!-- <script src="p5/addons/p5.sound.js"></script> --> <script src="p5/addons/p5.sound.min.js"></script>
<script src="sketch.js"></script> <script src="vehicle.js"></script>
</head> </head>
<body> <body>

143
sketch.js
View File

@ -1,145 +1,8 @@
function setup() { function setup() {
createCanvas(400, 600); cursor(CROSS);
// 画线 createCanvas(600, 600);
// stroke("#00FF00");
// line(50, 50, 150, 150);
// 画(椭)圆
// stroke("#FF0000");
// circle(300, 100, 100);
// ellipse(300, 100, 100, 100);
// 画矩形
// stroke("#FFFF00");
// square(75, 275, 50);
// rect(50, 250, 100, 100);
// 画三角形
// stroke("#0000FF");
// triangle(100, 250, 50, 350, 150, 350);
// 辅助线
// stroke("#DDDDFF");
// for (let x = 0; x < width; x += 25) {
// line(x, 0, x, height);
// }
// for (let y = 0; y < height; y += 25) {
// line(0, y, width, y);
// }
} }
function draw() { function draw() {
noStroke(); background(64);
stroke("#333333");
// 天空
background("lightblue");
// 地面
fill("lightgreen");
rect(0, 275, width, height);
// 太阳
fill("#FF0000");
circle(100, 100, 75);
// 光
let a = frameCount % 50;
for (let i = 0; i < 8; i++) {
push();
translate(100, 100);
rotate((i / 4) * PI);
triangle(-5, 50 + a, 5, 50 + a, 0, 65 + a);
pop();
}
// 烟囱
fill("#7733CC");
rect(275, 125, 25, 100);
// 房顶
fill("#DD66FF");
triangle(250, 150, 150, 200, 350, 200);
// 墙
fill("#FFDDAA");
rect(175, 200, 150, 100);
// 窗户
fill("#FFFF66");
let b = map(a, 0, 50, -10, 10);
if (b > 0) {
ellipse(225, 225, 25 + b);
ellipse(275, 225, 25 - b);
} else {
ellipse(225, 225, 25 - b);
ellipse(275, 225, 25 + b);
}
// 门
fill("#DD33CC");
rect(235, 250, 30, 50);
bird(200, 75);
bird(300, 50);
// 树叶
fill("#66AA00");
triangle(100, 340, 40, 400, 160, 400);
fill("#AAFF00");
triangle(100, 325, 50, 375, 150, 375);
fill("#66AA00");
triangle(100, 305, 60, 350, 140, 350);
// 树干
fill("#FFDDAA");
rect(85, 400, 30, 50);
// 小路
fill("#DD66FF");
ellipse(275, 350, 50, 25);
fill("#7733CC");
ellipse(288, 400, 75, 35);
fill("#66AA00");
ellipse(300, 460, 100, 50);
fill("#FF9933");
ellipse(325, 550, 125, 70);
// 蘑菇
fill("#FF0000");
arc(175, 475, 50, 50, PI, 0, PIE);
fill("#FFDDAA");
circle(157, 470, 8);
circle(165, 462, 8);
circle(175, 457, 8);
circle(175, 470, 8);
circle(185, 462, 8);
circle(193, 470, 8);
fill("#FF9933");
rect(165, 475, 20, 20);
noStroke();
fill(0);
text("作品:基础图形绘画练习一", 50, 550);
text("作者:赵海洋爸爸 三(8)班", 50, 570);
}
function bird(x, y) {
push();
let a = frameCount % 10;
noFill();
stroke(0);
translate(x, y);
fill("#FFDDAA");
arc(0, 0, 50, 50, 0, PI, PIE);
ellipse(30, -10, 30);
fill("#FFFFFF");
ellipse(28, -10, 10);
fill("#333333");
ellipse(28, -10, 5);
fill("#FF3333");
triangle(40, -15, 40, -5, 60, -10);
fill("#FFFF66");
triangle(-20, -20 + a * 2, -10, 5, 10, -5);
pop();
} }

200
vehicle.js Normal file
View File

@ -0,0 +1,200 @@
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.wander();
vehicle1.move();
vehicle1.turn();
vehicle1.drawPath();
vehicle1.show();
}
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);
vehicle2.move();
vehicle1.move();
vehicle2.turn();
vehicle1.turn();
vehicle1.drawPath();
vehicle2.show();
vehicle1.show();
}
/**
* 返回可指定大小的随机二维向量
* @param {number} magnitude 向量大小
* @return {p5.Vector} vector 随机二维向量
*/
function randomVector(magnitude) {
let vector = p5.Vector.random2D();
return magnitude ? vector.mult(magnitude) : vector;
}
class Vehicle {
constructor(x, y, color) {
this.color = color;
this.position = createVector(x, y);
this.path = [];
this.pathes = [];
this.velocity = createVector(0, 0);
this.heading = this.velocity.heading();
this.acceleration = createVector(0, 0);
this.maxVelocity = 5;
this.maxAcceleration = 1;
}
seek(target, slowdownDistance = 100) {
const desired = p5.Vector.sub(target.position, this.position);
const distance = desired.mag();
const magnitude =
slowdownDistance > 0 && distance <= slowdownDistance
? map(distance, 0, slowdownDistance, 0, this.maxVelocity)
: this.maxVelocity;
desired.setMag(magnitude);
const steering = p5.Vector.sub(desired, this.velocity);
this.acceleration.add(steering);
}
flee(target, fleeDistance = 100) {
const desired = p5.Vector.sub(this.position, target.position);
const distance = desired.mag();
const magnitude =
!fleeDistance || fleeDistance <= 0
? this.maxVelocity
: distance <= fleeDistance
? map(distance, 0, fleeDistance, this.maxVelocity, 0)
: 0;
desired.setMag(magnitude);
const steering = p5.Vector.sub(desired, this.velocity);
this.acceleration.add(steering);
}
wander() {
const target = this.velocity.copy();
target.setMag(50).add(this.position);
// stroke(128);
// const x1 = target.x + -25 * cos(PI / 2 + this.heading);
// const y1 = target.y + -25 * sin(PI / 2 + this.heading);
// const x2 = target.x + 25 * cos(PI / 2 + this.heading);
// const y2 = target.y + 25 * sin(PI / 2 + this.heading);
// line(x1, y1, x2, y2);
const offset = map(noise(Date.now() / 1000), 0, 1, -50, 50);
const x = offset * cos(PI / 2 + this.heading);
const y = offset * sin(PI / 2 + this.heading);
target.add(x, y);
// noStroke();
// fill("#F063A4");
// circle(target.x, target.y, 5);
const steering = target.sub(this.position);
this.acceleration.add(steering);
}
move() {
this.acceleration.limit(this.maxAcceleration);
this.velocity.add(this.acceleration);
if (this.velocity.mag() > 0) this.heading = this.velocity.heading();
this.velocity.limit(this.maxVelocity);
this.position.add(this.velocity);
this.acceleration.set(0, 0);
this.path.push(this.position.copy());
}
turn() {
let x = this.position.x;
let y = this.position.y;
while (x < 0 || x >= width) x = (x + width) % width;
while (y < 0 || y >= height) y = (y + height) % height;
const edgeCrossed = x != this.position.x || y != this.position.y;
if (edgeCrossed) {
this.pathes.push(this.path);
this.path = [];
}
this.position.x = x;
this.position.y = y;
}
// bounce() {
// if (this.position.x <= this.size / 2) {
// this.position.x = this.size / 2;
// this.velocity.x *= -1;
// return true;
// } else if (this.position.x > canvasWidth - this.size / 2) {
// this.position.x = canvasWidth - this.size / 2;
// this.velocity.x *= -1;
// return true;
// }
// if (this.position.y <= this.size / 2) {
// this.position.y = this.size / 2;
// this.velocity.y *= -1;
// return true;
// } else if (this.position.y >= canvasHeight - this.size / 2) {
// this.position.y = canvasHeight - this.size / 2;
// this.velocity.y *= -1;
// return true;
// }
// return false;
// }
drawPath() {
push();
noFill();
stroke(50);
strokeWeight(1);
// if (this.pathes.length >= 10) this.pathes.shift();
[...this.pathes, this.path].forEach((path) => {
beginShape();
path.forEach((v) => vertex(v.x, v.y));
endShape();
});
pop();
}
show() {
push();
translate(this.position.x, this.position.y);
rotate(this.heading);
stroke(this.color);
fill(this.color);
triangle(0, 0, -10, 2.5, -10, -2.5);
pop();
}
}