首页 > 解决方案 > 鼠标按下时的矢量吸引力

问题描述

目前正在尝试使用 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);  
    }
  }
}

不确定要进一步添加什么细节。不确定要进一步添加什么细节。不确定要进一步添加什么细节。不确定要进一步添加什么细节。不确定要进一步添加什么细节。不确定要进一步添加什么细节。不确定要进一步添加什么细节。

标签: javascriptp5.js

解决方案


  • 您正在使用索引a作为参数,Cubes.attraction该参数期望具有pos矢量场的对象(多维数据集?)
  • 您正在尝试使用this.x/来定位您的多维数据集this.y,而update. 改用this.pos向量
  • 您可以通过仅检查一次鼠标按下来进行优化,然后才attraction以鼠标坐标作为矢量参数调用每个立方体
  • 在物理学中,力驱动加速度,而不是速度。我改变了,但也许是你故意的。
  • 您应该将您的班级名称更改为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>


推荐阅读