按下鼠标时的矢量吸引力
Vector attraction when mouse pressed
目前正在尝试使用 createVector 函数在 3D 立方体上创建吸引力效果。景点设计为在按下鼠标时触发,但目前显示错误:
Uncaught TypeError: Cannot read property 'copy' of undefined
代码:
let cubes = [];
function setup() {
createCanvas(windowWidth, windowHeight, WEBGL);
backCol = color(243, 243, 243);
for (let i = 0; i < 10; i++) {
for (let j = 0; j < 10; j++) {
let xPos = map(i, 0, 9, 50, width - 50);
let yPos = map(j, 0, 9, 50, height - 50);
cubes.push(new Cubes(xPos, yPos));
}
}
}
function draw() {
background(backCol);
noFill();
for (let cube of cubes) {
cube.update();
}
attracting();
}
function attracting() {
for (let a = 0; a < cubes.length; a++) {
cubes[a].attraction(mouseX,mouseY);
}
}
class Cubes {
constructor(x, y) {
this.x = x;
this.y = y;
this.size = 30;
this.stroke = 70;
this.gap = 150;
this.shift1 = color(96);
this.shift2 = color(244);
//vector variables
this.pos = createVector(x, y);
this.vel = createVector();
this.acc = createVector();
}
update() {
this.shape();
this.test_Color();
//attraction values
this.vel.add(this.acc);
this.vel.limit(5);
this.pos.add(this.vel);
this.acc.mult(0);
}
shape() {
push();
stroke(this.stroke);
this.test_Color();
translate(this.x - width / 2, this.y - height / 2, 0);
this.test_rotation()
box(this.size);
pop();
}
test_Color() {
fill(this.shift1);
}
test_rotation() {
rotateX(frameCount / 60);
rotateY(frameCount / 60);
}
attraction(target) {
//all cubes supposed to attract towards the mouse when pressed
if (mouseIsPressed) {
let force = p5.Vector.sub(target.pos,this.pos);
let d = force.mag();
d = constrain(d, 1, 25);
var G = 50;
var strength = G / (d * d);
force.setMag(strength);
if (d < 20) {
force.mult(10);
}
this.vel.add(force);
}
}
}
不确定要进一步添加什么细节。不确定要进一步添加什么细节。不确定要进一步添加什么细节。不确定要进一步添加什么细节。不确定要进一步添加什么细节。不确定要进一步添加什么细节。不确定要进一步添加什么细节。
- 您正在使用索引
a
作为 Cubes.attraction
的参数,它需要一个具有 pos
向量场的对象(一个立方体?)
- 您正在尝试使用
this.x
/ this.y
来定位您的立方体,update
不会更改它们。使用 this.pos
向量代替
- 您可以通过检查是否只按下一次鼠标进行优化,然后仅在每个立方体上调用
attraction
并将鼠标坐标作为向量参数
- 在物理学中,力驱动加速度,而不是速度。我改变了那个,但也许这是你故意的。
- 您应该将 class 名称更改为
Cube
而不是 Cubes
let cubes = [];
function setup() {
/* max(...) here is just for rendering with minimum size in the snippet */
createCanvas(max(windowWidth, 800), max(windowHeight, 600), WEBGL);
backCol = color(243, 243, 243);
for (let i = 0; i < 10; i++) {
for (let j = 0; j < 10; j++) {
let xPos = map(i, 0, 9, 50, width - 50);
let yPos = map(j, 0, 9, 50, height - 50);
cubes.push(new Cubes(xPos, yPos));
}
}
}
function draw() {
background(backCol);
noFill();
for (let cube of cubes) {
cube.update();
}
attracting();
}
function attracting() {
/* changed to check for mouse pressed once for all cubes */
if (mouseIsPressed) {
/* generating mouse position vector once for all cubes */
const mousePosVect = new p5.Vector(mouseX, mouseY);
for (let a = 0; a < cubes.length; a++) {
cubes[a].attraction(mousePosVect);
}
}
}
class Cubes {
constructor(x, y) {
/* Removed useless and confusing this.x, this.y */
this.size = 30;
this.stroke = 70;
this.gap = 150;
this.shift1 = color(96);
this.shift2 = color(244);
//vector variables
this.pos = createVector(x, y);
this.vel = createVector();
this.acc = createVector();
}
update() {
this.test_Color();
//attraction values
this.vel.add(this.acc);
this.vel.limit(5);
this.pos.add(this.vel);
this.acc.mult(0);
this.shape();
}
shape() {
push();
stroke(this.stroke);
this.test_Color();
/* Used this.pos instead of this.x, this.y for positioning */
translate(this.pos.x - width / 2, this.pos.y - height / 2, 0);
this.test_rotation();
box(this.size);
pop();
}
test_Color() {
fill(this.shift1);
}
test_rotation() {
rotateX(frameCount / 60);
rotateY(frameCount / 60);
}
attraction(targetVector) {
//all cubes supposed to attract towards the mouse when pressed
/* Set target argument to vector,
* moved the `if (mouseIsPressed)` condition outside */
let force = p5.Vector.sub(targetVector,this.pos);
let d = force.mag();
d = constrain(d, 1, 25);
var G = 50;
var strength = G / (d * d);
force.setMag(strength);
if (d < 20) {
force.mult(10);
}
/* changed to add force to acceleration
* instead of velocity (physically accurate) */
this.acc.add(force);
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>P5 cube attractor</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.min.js" integrity="sha512-gQVBYBvfC+uyor5Teonjr9nmY1bN+DlOCezkhzg4ShpC5q81ogvFsr5IV4xXAj6HEtG7M1Pb2JCha97tVFItYQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
</head>
<body>
<!--h1>P5 test</h1-->
</body>
</html>
目前正在尝试使用 createVector 函数在 3D 立方体上创建吸引力效果。景点设计为在按下鼠标时触发,但目前显示错误:
Uncaught TypeError: Cannot read property 'copy' of undefined
代码:
let cubes = [];
function setup() {
createCanvas(windowWidth, windowHeight, WEBGL);
backCol = color(243, 243, 243);
for (let i = 0; i < 10; i++) {
for (let j = 0; j < 10; j++) {
let xPos = map(i, 0, 9, 50, width - 50);
let yPos = map(j, 0, 9, 50, height - 50);
cubes.push(new Cubes(xPos, yPos));
}
}
}
function draw() {
background(backCol);
noFill();
for (let cube of cubes) {
cube.update();
}
attracting();
}
function attracting() {
for (let a = 0; a < cubes.length; a++) {
cubes[a].attraction(mouseX,mouseY);
}
}
class Cubes {
constructor(x, y) {
this.x = x;
this.y = y;
this.size = 30;
this.stroke = 70;
this.gap = 150;
this.shift1 = color(96);
this.shift2 = color(244);
//vector variables
this.pos = createVector(x, y);
this.vel = createVector();
this.acc = createVector();
}
update() {
this.shape();
this.test_Color();
//attraction values
this.vel.add(this.acc);
this.vel.limit(5);
this.pos.add(this.vel);
this.acc.mult(0);
}
shape() {
push();
stroke(this.stroke);
this.test_Color();
translate(this.x - width / 2, this.y - height / 2, 0);
this.test_rotation()
box(this.size);
pop();
}
test_Color() {
fill(this.shift1);
}
test_rotation() {
rotateX(frameCount / 60);
rotateY(frameCount / 60);
}
attraction(target) {
//all cubes supposed to attract towards the mouse when pressed
if (mouseIsPressed) {
let force = p5.Vector.sub(target.pos,this.pos);
let d = force.mag();
d = constrain(d, 1, 25);
var G = 50;
var strength = G / (d * d);
force.setMag(strength);
if (d < 20) {
force.mult(10);
}
this.vel.add(force);
}
}
}
不确定要进一步添加什么细节。不确定要进一步添加什么细节。不确定要进一步添加什么细节。不确定要进一步添加什么细节。不确定要进一步添加什么细节。不确定要进一步添加什么细节。不确定要进一步添加什么细节。
- 您正在使用索引
a
作为Cubes.attraction
的参数,它需要一个具有pos
向量场的对象(一个立方体?) - 您正在尝试使用
this.x
/this.y
来定位您的立方体,update
不会更改它们。使用this.pos
向量代替 - 您可以通过检查是否只按下一次鼠标进行优化,然后仅在每个立方体上调用
attraction
并将鼠标坐标作为向量参数 - 在物理学中,力驱动加速度,而不是速度。我改变了那个,但也许这是你故意的。
- 您应该将 class 名称更改为
Cube
而不是Cubes
let cubes = [];
function setup() {
/* max(...) here is just for rendering with minimum size in the snippet */
createCanvas(max(windowWidth, 800), max(windowHeight, 600), WEBGL);
backCol = color(243, 243, 243);
for (let i = 0; i < 10; i++) {
for (let j = 0; j < 10; j++) {
let xPos = map(i, 0, 9, 50, width - 50);
let yPos = map(j, 0, 9, 50, height - 50);
cubes.push(new Cubes(xPos, yPos));
}
}
}
function draw() {
background(backCol);
noFill();
for (let cube of cubes) {
cube.update();
}
attracting();
}
function attracting() {
/* changed to check for mouse pressed once for all cubes */
if (mouseIsPressed) {
/* generating mouse position vector once for all cubes */
const mousePosVect = new p5.Vector(mouseX, mouseY);
for (let a = 0; a < cubes.length; a++) {
cubes[a].attraction(mousePosVect);
}
}
}
class Cubes {
constructor(x, y) {
/* Removed useless and confusing this.x, this.y */
this.size = 30;
this.stroke = 70;
this.gap = 150;
this.shift1 = color(96);
this.shift2 = color(244);
//vector variables
this.pos = createVector(x, y);
this.vel = createVector();
this.acc = createVector();
}
update() {
this.test_Color();
//attraction values
this.vel.add(this.acc);
this.vel.limit(5);
this.pos.add(this.vel);
this.acc.mult(0);
this.shape();
}
shape() {
push();
stroke(this.stroke);
this.test_Color();
/* Used this.pos instead of this.x, this.y for positioning */
translate(this.pos.x - width / 2, this.pos.y - height / 2, 0);
this.test_rotation();
box(this.size);
pop();
}
test_Color() {
fill(this.shift1);
}
test_rotation() {
rotateX(frameCount / 60);
rotateY(frameCount / 60);
}
attraction(targetVector) {
//all cubes supposed to attract towards the mouse when pressed
/* Set target argument to vector,
* moved the `if (mouseIsPressed)` condition outside */
let force = p5.Vector.sub(targetVector,this.pos);
let d = force.mag();
d = constrain(d, 1, 25);
var G = 50;
var strength = G / (d * d);
force.setMag(strength);
if (d < 20) {
force.mult(10);
}
/* changed to add force to acceleration
* instead of velocity (physically accurate) */
this.acc.add(force);
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>P5 cube attractor</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.min.js" integrity="sha512-gQVBYBvfC+uyor5Teonjr9nmY1bN+DlOCezkhzg4ShpC5q81ogvFsr5IV4xXAj6HEtG7M1Pb2JCha97tVFItYQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
</head>
<body>
<!--h1>P5 test</h1-->
</body>
</html>