From 072a92ec54d07eff82a5044088290b4f9b493e74 Mon Sep 17 00:00:00 2001 From: Zhao Xin <7176466@qq.com> Date: Sun, 11 Dec 2022 21:52:13 +0800 Subject: [PATCH] update --- 1003.矢量的投影.js | 6 +-- 4.太阳公公.js | 29 +++++++++++ index.html | 2 +- particle.js | 49 ++++++++++++++++++ particle_demo.js | 14 ++++++ sketch-template.js | 17 +++++++ sketch.js | 27 ++++++++-- vehicle.js | 120 +++++++++++++++++++++------------------------ vehicle_demo.js | 93 +++++++++++++++++++++++++++++++++++ 9 files changed, 287 insertions(+), 70 deletions(-) create mode 100644 4.太阳公公.js create mode 100644 particle.js create mode 100644 particle_demo.js create mode 100644 sketch-template.js create mode 100644 vehicle_demo.js diff --git a/1003.矢量的投影.js b/1003.矢量的投影.js index c495966..08a5b31 100644 --- a/1003.矢量的投影.js +++ b/1003.矢量的投影.js @@ -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); } diff --git a/4.太阳公公.js b/4.太阳公公.js new file mode 100644 index 0000000..e299eb5 --- /dev/null +++ b/4.太阳公公.js @@ -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(); +} diff --git a/index.html b/index.html index 6633ed0..261a851 100644 --- a/index.html +++ b/index.html @@ -21,7 +21,7 @@ - + diff --git a/particle.js b/particle.js new file mode 100644 index 0000000..9cdf442 --- /dev/null +++ b/particle.js @@ -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() {} +} diff --git a/particle_demo.js b/particle_demo.js new file mode 100644 index 0000000..9faafd0 --- /dev/null +++ b/particle_demo.js @@ -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(); +} diff --git a/sketch-template.js b/sketch-template.js new file mode 100644 index 0000000..7a8f5a7 --- /dev/null +++ b/sketch-template.js @@ -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(); +} diff --git a/sketch.js b/sketch.js index a2615b3..e299eb5 100644 --- a/sketch.js +++ b/sketch.js @@ -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(); } diff --git a/vehicle.js b/vehicle.js index 3dc667b..1226620 100644 --- a/vehicle.js +++ b/vehicle.js @@ -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); +} diff --git a/vehicle_demo.js b/vehicle_demo.js new file mode 100644 index 0000000..0efefb8 --- /dev/null +++ b/vehicle_demo.js @@ -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(); +}