Reputation: 384
Currently trying to create attraction effect on 3D cubes using createVector function. The attraction designed to trigger when mouse pressed but currently it's stating the error:
Uncaught TypeError: Cannot read property 'copy' of undefined
The code:
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);
}
}
}
unsure what detail to add further. Unsure what detail to add further. Unsure what detail to add further. Unsure what detail to add further. Unsure what detail to add further. Unsure what detail to add further. Unsure what detail to add further.
Upvotes: 1
Views: 170
Reputation: 2609
a
for argument of Cubes.attraction
which is expecting an object with a pos
vector field (a Cubes ?)this.x
/ this.y
, which aren't changed by update
. Use the this.pos
vector insteadattraction
on every cube with mouse coordinates as vector argumentCube
rather than 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>
Upvotes: 1