I have the following code that i've roughly redone from someone else to help learn javascript. I am getting the following error:
Uncaught TypeError: flock.addBoid is not a function
at setup (boids.js:15)
at boids.js:1
The function in question is called at the beginning in setup() and defined shortly after in the section labeled FLOCK. It is definitely not misspelled and these are the only occurrences of addBoid in the document. I'll include the whole document in case its relevant but the problem should just lie in the beginning.
I am not looking for any advice about my code other than the source and solution to this error, thanks.
setup();
draw();
//////////////////// SETUP ///////////////////////
var flock;
var ctx;
var c;
function setup(){
c = document.getElementById("boidCanvas");
ctx = c.getContext("2d");
flock = new Flock();
for(var i = 0; i < 100; i++){
var b = new Boid(ctx.width / 2, ctx.height / 2);
flock.addBoid(b);
}
}
function draw() {
ctx.fillStyle = "Blue";
ctx.fillRect(0,0,c.width,c.height);
//flock.run()
}
//////////////////// FLOCK ///////////////////////
function Flock(){
this.boids = [];
}
Flock.prototype.run = function(){
for(var i = 0; i < this.boids.length; i++){
this.boids[i].run(this.boids);
}
}
Flock.prototype.addBoid = function(b){
this.boids.push(b);
}
//////////////////// BOID ///////////////////////
function Boid(setx,sety){
this.acceleration = { x:0, y:0 };
this.velocity = { x:Math.floor(Math.random()*3)-1, y:Math.floor(Math.random()*3)-1 };
this.position = { x:setx, y:sety };
this.r = 3;
this.maxSpeed = 3;
this.maxForce = .05;
}
Boid.prototype.run = function(boids){
this.evaluate(boids);
this.update();
this.wrap();
this.render();
}
// force is a vector [x,y]
Boid.prototype.applyForce = function(force){
this.acceleration.x += force[0];
this.acceleration.y += force[1];
}
Boid.prototype.evaluate = function(boids){
var seperate = this.seperate(boids);
var align = this.align(boids);
var cohesion = this.cohesion(boids);
// Arbitrary Weights
seperate *= 1.5;
align *= 1.0;
cohesion *= 1.0;
this.applyForce(seperate);
this.applyForce(align);
this.applyForce(cohesion);
}
Boid.prototype.update = function(){
//update velocity
this.velocity += this.acceleration;
//fix velocity to max speed
var normal = normalize([this.velocity.x, this.velocity.y]);
this.velocity = constantMult(normal, this.maxSpeed);
//update position
this.position.x += this.velocity.x;
this.position.y += this.velocity.y;
//reset acceleration;
this.acceleration.x = 0;
this.acceleration.y = 0;
}
// target is a vector [x,y]
Boid.prototype.seek = function(target){
var desired = sub(target, [this.position.x, this.position.y]);
var normal = normalize(desired);
desired = constantMult(normal, this.maxSpeed);
var steer = sub(desired,[this.velocity.x, this.velocity.y])
normal = normalize(steer);
steer[0] = normal[0] * this.maxForce;
steer[1] = normal[1] * this.maxForce;
return steer;
}
Boid.prototype.render = function(){
var triangle = drawTriangle(this.velocity);
for(var i = 0; i < triangle.length; i++){
triangle[i] = constantMult(triangle[i], this.r);
}
for(i = 0; i < triangle.length; i++){
triangle[i] = add(triangle[i], this.position);
}
ctx.beginPath();
ctx.moveTo(triangle[0][0], triangle[0][1]);
for(i = 1; i < triangle.length; i++){
ctx.lineTo(triangle[i][0], triangle[i][1]);
}
ctx.closePath();
ctx.fillStyle = "White";
ctx.fill();
}
Boid.prototype.wrap = function(){
if(this.position.x < -this.r)
this.position.x = c.width + this.r;
else if(this.position.x > c.width + this.r)
this.position.x = -this.r;
if(this.position.y < -this.r)
this.position.y = c.height + this.r;
else if(this.position.y > c.height + this.r)
this.position.y = -this.r;
}
Boid.prototype.seperate = function(boids){
var desiredSeperation = 25.0;
var steer = [0,0];
var count = 0;
for(var i = 0; i < boids.length; i++){
var difference = sub(this.position, boids[i].position);
var d = Math.sqrt(Math.pow(difference[0],2), Math.pow(difference[1],2));
if(d < desiredSeperation){
var normalDiff = normalize(difference);
normalDiff = constantMult(normalDiff, 1/d);
steer = add(steer, normalDiff);
count++;
}
}
if(count > 0){
steer = constantMult(steer, 1/count);
steer = normalize(steer);
steer = constantMult(steer, this.maxSpeed);
steer = sub(steer, this.velocity);
steer = normalize(steer);
steer = constantMult(steer, this.maxForce);
}
return steer;
}
Boid.prototype.align = function(boids){
var neighborDistance = 50;
var sum = [0,0];
var count = 0;
for(var i = 0; i < boids.length; i++){
var difference = sub(this.position, boids[i].position);
var dist = Math.sqrt(Math.pow(difference[0],2), Math.pow(difference[1],2));
if(dist < neighborDistance){
sum = sum(sum, boids[i].velocity);
count++;
}
}
if(count > 0){
sum = constantMult(sum, 1/count);
sum = normalize(sum);
sum = constantMult(this.maxSpeed);
var steer = sub(sum, this.velocity);
steer = normalize(steer);
steer = constantMult(steer, this.maxForce);
return steer;
}
else
return [0,0];
}
Boid.prototype.cohesion = function(boids){
var neighborDistance = 50;
var sum = [0,0];
var count = 0;
for(var i = 0; i < boids.length; i++){
var difference = sub(this.position, boids[i].position);
var dist = Math.sqrt(Math.pow(difference[0],2), Math.pow(difference[1],2));
if(dist < neighborDistance){
sum = add(sum, boids[i].position);
count++;
}
}
if(count > 0){
sum = constantMult(sum, 1/count);
return this.seek(sum);
}
else
return [0,0];
}
//////////////////// HELPERS ///////////////////////
// returns the vector with the same direction as v but with magnitude 1 in the form [x,y]
// v is a vector in the form [x,y]
function normalize(v){
var magnitude = Math.sqrt(Math.pow(v[0],2) + Math.pow(v[1],2))
var normalX = v[0] / magnitude;
var normalY = v[1] / magnitude;
return [normalX, normalY];
}
function add(a,b){
var x = a[0]+b[0];
var y = a[1]+b[1];
return [x,y];
}
// returns a-b, [ax-bx, ay-by]
function sub(a,b){
var x = a[0]-b[0];
var y = a[1]-b[1];
return [x,y];
}
function mult(a,b){
var x = a[0]*b[0];
var y = a[1]*b[1];
return [x,y];
}
function constantMult(a, n){
for(var i = 0; i < a.length; i++){
a[i] *= n;
}
}
// creates an unscaled issoceles triangle centered at the origin
// returns a list of 3 lists, each containing the coordinates of a vertex, the first being the tip
// ie. [ [x1,y1], [x2,y2], [x3,y3] ]
// heading is a vector describing the direction of the triangle in the form [x,y]
// heading does not need to be normalized
function drawTriangle(heading){
heading = normalize(heading);
var v1 = [1,0];
var v2 = [-1, .5];
var v3 = [-1,-.5];
var thetaX = Math.acos(heading[0]);
var thetaY = Math.asin(heading[1]);
var theta;
if(thetaX >= 0)
theta = (Math.PI / 2) - thetaY;
else
theta = (Math.PI / 2) - thetaX;
function rotate(v){
var xp = (v[0] * Math.cos(theta)) - (v[1] * Math.sin(theta));
var yp = (v[1] * Math.cos(theta)) + (v[0] * Math.sin(theta));
return [xp, yp];
}
v1 = rotate(v1);
v2 = rotate(v2);
v3 = rotate(v3);
return [v1,v2,v3];
}
Move the functions setup(); and draw(); to the end of the JavaScript file. The issue was that the function addBoid() was not hoisted to the top, making it undefined by setup(); and draw();.
You function declaration gets hoisted on the top of block.
function Flock(){
this.boids = [];
}
when you add properties to prototype those properties are not eligible for hoisting, its like accessing variables (let declared cause var is eligible for hoisting) before declaring them.
Flock.prototype.run = function(){
for(var i = 0; i < this.boids.length; i++){
this.boids[i].run(this.boids);
}
}
Flock.prototype.addBoid = function(b){
this.boids.push(b);
}
Add above lines before you call flock.addBoid i.e. move setup and draw call to the end of Javascript
//////////////////// SETUP ///////////////////////
var flock;
var ctx;
var c;
//////////////////// FLOCK ///////////////////////
function Flock(){
this.boids = [];
}
Flock.prototype.run = function(){
for(var i = 0; i < this.boids.length; i++){
this.boids[i].run(this.boids);
}
}
Flock.prototype.addBoid = function(b){
this.boids.push(b);
}
function setup(){
c = document.getElementById("boidCanvas");
ctx = c.getContext("2d");
flock = new Flock();
for(var i = 0; i < 100; i++){
var b = new Boid(ctx.width / 2, ctx.height / 2);
flock.addBoid(b);
}
}
function draw() {
ctx.fillStyle = "Blue";
ctx.fillRect(0,0,c.width,c.height);
//flock.run()
}
//////////////////// BOID ///////////////////////
function Boid(setx,sety){
this.acceleration = { x:0, y:0 };
this.velocity = { x:Math.floor(Math.random()*3)-1, y:Math.floor(Math.random()*3)-1 };
this.position = { x:setx, y:sety };
this.r = 3;
this.maxSpeed = 3;
this.maxForce = .05;
}
Boid.prototype.run = function(boids){
this.evaluate(boids);
this.update();
this.wrap();
this.render();
}
// force is a vector [x,y]
Boid.prototype.applyForce = function(force){
this.acceleration.x += force[0];
this.acceleration.y += force[1];
}
Boid.prototype.evaluate = function(boids){
var seperate = this.seperate(boids);
var align = this.align(boids);
var cohesion = this.cohesion(boids);
// Arbitrary Weights
seperate *= 1.5;
align *= 1.0;
cohesion *= 1.0;
this.applyForce(seperate);
this.applyForce(align);
this.applyForce(cohesion);
}
Boid.prototype.update = function(){
//update velocity
this.velocity += this.acceleration;
//fix velocity to max speed
var normal = normalize([this.velocity.x, this.velocity.y]);
this.velocity = constantMult(normal, this.maxSpeed);
//update position
this.position.x += this.velocity.x;
this.position.y += this.velocity.y;
//reset acceleration;
this.acceleration.x = 0;
this.acceleration.y = 0;
}
// target is a vector [x,y]
Boid.prototype.seek = function(target){
var desired = sub(target, [this.position.x, this.position.y]);
var normal = normalize(desired);
desired = constantMult(normal, this.maxSpeed);
var steer = sub(desired,[this.velocity.x, this.velocity.y])
normal = normalize(steer);
steer[0] = normal[0] * this.maxForce;
steer[1] = normal[1] * this.maxForce;
return steer;
}
Boid.prototype.render = function(){
var triangle = drawTriangle(this.velocity);
for(var i = 0; i < triangle.length; i++){
triangle[i] = constantMult(triangle[i], this.r);
}
for(i = 0; i < triangle.length; i++){
triangle[i] = add(triangle[i], this.position);
}
ctx.beginPath();
ctx.moveTo(triangle[0][0], triangle[0][1]);
for(i = 1; i < triangle.length; i++){
ctx.lineTo(triangle[i][0], triangle[i][1]);
}
ctx.closePath();
ctx.fillStyle = "White";
ctx.fill();
}
Boid.prototype.wrap = function(){
if(this.position.x < -this.r)
this.position.x = c.width + this.r;
else if(this.position.x > c.width + this.r)
this.position.x = -this.r;
if(this.position.y < -this.r)
this.position.y = c.height + this.r;
else if(this.position.y > c.height + this.r)
this.position.y = -this.r;
}
Boid.prototype.seperate = function(boids){
var desiredSeperation = 25.0;
var steer = [0,0];
var count = 0;
for(var i = 0; i < boids.length; i++){
var difference = sub(this.position, boids[i].position);
var d = Math.sqrt(Math.pow(difference[0],2), Math.pow(difference[1],2));
if(d < desiredSeperation){
var normalDiff = normalize(difference);
normalDiff = constantMult(normalDiff, 1/d);
steer = add(steer, normalDiff);
count++;
}
}
if(count > 0){
steer = constantMult(steer, 1/count);
steer = normalize(steer);
steer = constantMult(steer, this.maxSpeed);
steer = sub(steer, this.velocity);
steer = normalize(steer);
steer = constantMult(steer, this.maxForce);
}
return steer;
}
Boid.prototype.align = function(boids){
var neighborDistance = 50;
var sum = [0,0];
var count = 0;
for(var i = 0; i < boids.length; i++){
var difference = sub(this.position, boids[i].position);
var dist = Math.sqrt(Math.pow(difference[0],2), Math.pow(difference[1],2));
if(dist < neighborDistance){
sum = sum(sum, boids[i].velocity);
count++;
}
}
if(count > 0){
sum = constantMult(sum, 1/count);
sum = normalize(sum);
sum = constantMult(this.maxSpeed);
var steer = sub(sum, this.velocity);
steer = normalize(steer);
steer = constantMult(steer, this.maxForce);
return steer;
}
else
return [0,0];
}
Boid.prototype.cohesion = function(boids){
var neighborDistance = 50;
var sum = [0,0];
var count = 0;
for(var i = 0; i < boids.length; i++){
var difference = sub(this.position, boids[i].position);
var dist = Math.sqrt(Math.pow(difference[0],2), Math.pow(difference[1],2));
if(dist < neighborDistance){
sum = add(sum, boids[i].position);
count++;
}
}
if(count > 0){
sum = constantMult(sum, 1/count);
return this.seek(sum);
}
else
return [0,0];
}
//////////////////// HELPERS ///////////////////////
// returns the vector with the same direction as v but with magnitude 1 in the form [x,y]
// v is a vector in the form [x,y]
function normalize(v){
var magnitude = Math.sqrt(Math.pow(v[0],2) + Math.pow(v[1],2))
var normalX = v[0] / magnitude;
var normalY = v[1] / magnitude;
return [normalX, normalY];
}
function add(a,b){
var x = a[0]+b[0];
var y = a[1]+b[1];
return [x,y];
}
// returns a-b, [ax-bx, ay-by]
function sub(a,b){
var x = a[0]-b[0];
var y = a[1]-b[1];
return [x,y];
}
function mult(a,b){
var x = a[0]*b[0];
var y = a[1]*b[1];
return [x,y];
}
function constantMult(a, n){
for(var i = 0; i < a.length; i++){
a[i] *= n;
}
}
// creates an unscaled issoceles triangle centered at the origin
// returns a list of 3 lists, each containing the coordinates of a vertex, the first being the tip
// ie. [ [x1,y1], [x2,y2], [x3,y3] ]
// heading is a vector describing the direction of the triangle in the form [x,y]
// heading does not need to be normalized
function drawTriangle(heading){
heading = normalize(heading);
var v1 = [1,0];
var v2 = [-1, .5];
var v3 = [-1,-.5];
var thetaX = Math.acos(heading[0]);
var thetaY = Math.asin(heading[1]);
var theta;
if(thetaX >= 0)
theta = (Math.PI / 2) - thetaY;
else
theta = (Math.PI / 2) - thetaX;
function rotate(v){
var xp = (v[0] * Math.cos(theta)) - (v[1] * Math.sin(theta));
var yp = (v[1] * Math.cos(theta)) + (v[0] * Math.sin(theta));
return [xp, yp];
}
v1 = rotate(v1);
v2 = rotate(v2);
v3 = rotate(v3);
return [v1,v2,v3];
}
setup();
draw();
Related
I am trying to achieve effect as shown in the picture below:
Im using p5.js library but im not a graphics programmer and thats why its very difficult to achieve this particular graphical effect. I am sharing my code with you and also I followed this tutorial.
Index.html
<html>
<head>
<script language="javascript" type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/p5.min.js"></script>
<script language="javascript" src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/addons/p5.dom.min.js"></script>
<script language="javascript" src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/addons/p5.sound.min.js"></script>
<script language="javascript" type="text/javascript" src="sketch.js"></script>
<script language="javascript" type="text/javascript" src="particle.js"></script>
</head>
<body>
</body>
</html>
particle.js
function Particle() {
this.pos = createVector(random(width), random(height));
this.vel = createVector(0, 0);
this.acc = createVector(0, 0);
this.maxspeed = 4;
this.h = 0;
this.alphaPower = 20;
this.prevPos = this.pos.copy();
this.update = function() {
this.vel.add(this.acc);
this.vel.limit(this.maxspeed);
this.pos.add(this.vel);
this.acc.mult(0);
}
this.follow = function(vectors) {
var x = floor(this.pos.x / scl);
var y = floor(this.pos.y / scl);
var index = x + y * cols;
var force = vectors[index];
this.applyForce(force);
}
this.applyForce = function(force) {
this.acc.add(force);
}
this.showBlue = function() {
stroke(0, 76, 153, this.alphaPower);
strokeWeight(1);
line(this.pos.x, this.pos.y, this.prevPos.x, this.prevPos.y);
this.updatePrev();
}
this.showMaroon = function() {
stroke(165, 0, 68, this.alphaPower); // maroon
strokeWeight(1);
line(this.pos.x, this.pos.y, this.prevPos.x, this.prevPos.y);
this.updatePrev();
}
this.showYellow = function() {
stroke(237, 188, 0, this.alphaPower);
//stroke(1,2);
strokeWeight(1);
line(this.pos.x, this.pos.y, this.prevPos.x, this.prevPos.y);
this.updatePrev();
}
this.updatePrev = function() {
this.prevPos.x = this.pos.x;
this.prevPos.y = this.pos.y;
}
this.edges = function() {
if (this.pos.x > width) {
this.pos.x = 0;
this.updatePrev();
}
if (this.pos.x < 0) {
this.pos.x = width;
this.updatePrev();
}
if (this.pos.y > height) {
this.pos.y = 0;
this.updatePrev();
}
if (this.pos.y < 0) {
this.pos.y = height;
this.updatePrev();
}
}
}
sketch.js
var inc = 0.01;
var scl = 10;
var cols, rows;
var zoff = 0;
var fr;
var particles = [];
var particlesMaroon = [];
var particlesBlue = [];
var particlesYellow = [];
var flowfield;
var flowfieldMaroon;
var flowfieldBlue;
var flowfieldYellow;
var gamma_is_high = false;
var beta_is_high = false;
var alpha_is_high = false;
var maroon_data=1000;
var blue_data = 1000;
var yellow_data = 1000;
setInterval(function() {
ChangeLines();
}, 5000);
function dataRequest(){
socket.emit('datarequest', {data: "request"});
}
function ChangeLines(){
maroon_data = random(500, 2000);
blue_data = random(500, 2000);
yellow_data = random(500, 2000);
gamma_is_high = true;
alpha_is_high = true;
beta_is_high = true;
}
function setup() {
slider = createSlider(0.01, 0.1, 0.02,0);
slider.position(10, 10);
slider.style('width', '80px');
ChangeLines();
createCanvas(windowWidth-15, windowHeight-20);
cols = floor(width / scl);
rows = floor(height / scl);
fr = createP('');
flowfield = new Array(cols * rows);
flowfieldMaroon = new Array(cols * rows);
flowfieldBlue = new Array(cols * rows);
flowfieldYellow = new Array(cols * rows);
for (var i = 0; i < 1000; i++) {
particles[i] = new Particle();
particlesMaroon[i] = new Particle();
particlesBlue[i] = new Particle();
particlesYellow[i] = new Particle();
}
background(255);
}
function draw() {
let val = slider.value();
inc = val;
var yoff = 0;
for (var y = 0; y < rows; y++) {
var xoff = 0;
for (var x = 0; x < cols; x++) {
var index = x + y * cols;
var angle = noise(xoff, yoff, zoff) * TWO_PI;
var angleMaroon = noise(xoff, yoff, zoff) * TWO_PI;
var angleBlue = noise(xoff, yoff, zoff) * TWO_PI;
var angleYellow = noise(xoff, yoff, zoff) * TWO_PI;
var v = p5.Vector.fromAngle(angle);
var vm = p5.Vector.fromAngle(angleMaroon);
var vb = p5.Vector.fromAngle(angleBlue);
var vy = p5.Vector.fromAngle(angleYellow);
v.setMag(5);
vm.setMag(5);
vb.setMag(5);
vy.setMag(5);
flowfield[index] = v;
flowfieldMaroon[index] = vm;
flowfieldBlue[index] = vb;
flowfieldYellow[index] = vy;
xoff += inc;
}
yoff += inc;
}
zoff += 0.0003;
for (var i = 0; i < particles.length; i++) {
if(gamma_is_high==true){
particlesMaroon[i].follow(flowfieldMaroon);
particlesMaroon[i].update();
particlesMaroon[i].edges();
particlesMaroon[i].showMaroon();
}
if(beta_is_high){
particlesBlue[i].follow(flowfieldBlue);
particlesBlue[i].update();
particlesBlue[i].edges();
particlesBlue[i].showBlue();
}
if(alpha_is_high){
particlesYellow[i].follow(flowfieldYellow);
particlesYellow[i].update();
particlesYellow[i].edges();
particlesYellow[i].showYellow();
}
}
fr.html(floor(frameRate()));
}
The variables maroon_data, blue_dataand yellow_data are data coming from EEG device which will be calculated later but for now its hard coded values for prototype only. Also booleans gamma_is_high, beta_is_high and alpha_is_high are set to true for now. But with this much effort I only manage to achieve this as shown below:
And the actual output is like this:
Kindly help me get this actual output. Any help would be appreciated. Thanks.
Ive sorta done this before. I only had one array of particles and just changed their rgb values by a small random amount. I used an object to store the colour values.
function setup() {
//Do all the normal stuff
var c = {r: 100, g:100, b:100)
}
function draw() {
//All the other stuff
c.r += random(-3,3);
c.g += random(-3,3);
c.b += random(-3,3);
}
And then in the particle:
show() {
fill(c.r,c.g,c.b, whateverAlphaYouWant);
//Do all the rest
}
You can always tweak the values to get whatever colour you want.
I was able to visualize the aforementioned functions successfully, then I tried to use Object Oriented Programming and compress my code into one function, it seems to not give any result, it doesn't show any errors but in same time, it doesn't display anything except the background when I run it, I am using the p5js library, How can I fix this issue?
I just started working with JS a few months ago, sorry for my ignorance
Here is my code:
var step = 1;
var scl = 1;
//amplitude for each visualization
var sa, ca, ta;
var ssld, csld, tsld;
//to hold x-values and y-values of the three functions
var sx = [], sy = [], cx = [], cy = [], tx = [], ty = [];
function setup() {
angleMode(DEGREES);
createCanvas(640, 480);
background(55);
ssld = createSlider(0, 150, 75);
ssld.position(10, 10);
csld = createSlider(0, 150, 75);
csld.position(10, 35);
tsld = createSlider(0, 150, 75);
tsld.position(10, 60);
var s_ = generateValues("sin");
var c_ = generateValues("cos");
var t_ = generateValues("tan");
sx = s_[0]
sy = s_[1]
cx = c_[0]
cy = c_[1]
tx = t_[0]
ty = t_[1]
}
function draw() {
var sa = ssld.value();
var ca = csld.value();
var ta = tsld.value();
strokeWeight(scl);
stroke(255, 0, 0);
renderWave(sx, sy);
stroke(0, 255, 0);
renderWave(cx, cy);
stroke(0, 255, 255);
renderWave(tx, ty);
}
//given the wave type, it returns a two-dimensional array containing the x-values, and y-values
function generateValues(wave_type) {
var xvalues = [];
var yvalues = [];
for (var i = 0; i < width; i += step) {
append(xvalues, i)
}
if (wave_type === "sin") {
for (var i = 0; i < xvalues.length; i++) {
var y = sin(xvalues[i]);
append(yvalues, y * sa);
}
return [xvalues, yvalues];
} else if (wave_type === "cos") {
for (var i = 0; i < xvalues.length; i++) {
var y = cos(xvalues[i]);
append(yvalues, y * ca);
}
return [xvalues, yvalues];
} else if (wave_type === "tan") {
for (var i = 0; i < xvalues.length; i++) {
var y = tan(xvalues[i]);
append(yvalues, y * ta);
}
return [xvalues, yvalues];
}
}
function renderWave (array_x, array_y) {
for (var i = 0; i < width; i++) {
point(array_x[i], array_y[i] + (height / 2));
}
}
You don't have initial values for sa, ca and ta. So when you call generateValues, those are all undefined, and your y-values are all NaN. Here I've assigned values to them in the setup function, before the call to generateValues. I also removed the var keyword from the assignments in draw(), because you want to use/affect the global variables not create new local variables.
Your sliders don't work - this is because you only use the sa, ca, ta values in generateValues, which you only call on setup, not each time it redraws. You'll need to re-think that part.
var step = 1;
var scl = 1;
//amplitude for each visualization
var sa, ca, ta;
var ssld, csld, tsld;
//to hold x-values and y-values of the three functions
var sx = [], sy = [], cx = [], cy = [], tx = [], ty = [];
function setup() {
angleMode(DEGREES);
createCanvas(640, 480);
background(55);
ssld = createSlider(0, 150, 75);
ssld.position(10, 10);
sa = 10;
csld = createSlider(0, 150, 75);
csld.position(10, 35);
ca = 10;
tsld = createSlider(0, 150, 75);
tsld.position(10, 60);
ta = 10;
var s_ = generateValues("sin");
var c_ = generateValues("cos");
var t_ = generateValues("tan");
sx = s_[0]
sy = s_[1]
cx = c_[0]
cy = c_[1]
tx = t_[0]
ty = t_[1]
}
function draw() {
sa = ssld.value();
ca = csld.value();
ta = tsld.value();
strokeWeight(scl);
stroke(255, 0, 0);
renderWave(sx, sy);
stroke(0, 255, 0);
renderWave(cx, cy);
stroke(0, 255, 255);
renderWave(tx, ty);
}
//given the wave type, it returns a two-dimensional array containing the x-values, and y-values
function generateValues(wave_type) {
var xvalues = [];
var yvalues = [];
for (var i = 0; i < width; i += step) {
append(xvalues, i)
}
if (wave_type === "sin") {
for (var i = 0; i < xvalues.length; i++) {
var y = sin(xvalues[i]);
append(yvalues, y * sa);
}
return [xvalues, yvalues];
} else if (wave_type === "cos") {
for (var i = 0; i < xvalues.length; i++) {
var y = cos(xvalues[i]);
append(yvalues, y * ca);
}
return [xvalues, yvalues];
} else if (wave_type === "tan") {
for (var i = 0; i < xvalues.length; i++) {
var y = tan(xvalues[i]);
append(yvalues, y * ta);
}
return [xvalues, yvalues];
}
}
function renderWave (array_x, array_y) {
for (var i = 0; i < width; i++) {
point(array_x[i], array_y[i] + (height / 2));
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.11/p5.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.11/addons/p5.dom.min.js"></script>
I am developing a animation in javascript where a car moves towards a person and picks but currently instead of a path I am just driving diagonally to the person with below code.
Car.prototype.main = function() {
var angle = angleBetweenTwoPoints(this.target.position, this.position);
var cos = Math.cos(degreeToRadian(angle)) * -1;
var sin = Math.sin(degreeToRadian(angle));
var _this = _super.call(this) || this;
this.angle = angle;
this.position.x += cos * this.speed;
this.position.y -= sin * this.speed;
if (distance(this.position, this.target.position) < 10 && this.image == GameImage.getImage("hero") ) {
this.target.position.x = Math.random() * mainCanvas.width;
this.target.position.y = Math.random() * mainCanvas.height;
this.hitCount++;
console.log(hitCount);
ctx.fillText("points : " + hitCount, 32, 32);
this.changeImage = true;
_this.speed = 3;
this.changeImageTime = Date.now() + 600; //0.5 sec from now.
this.image = (this.image == GameImage.getImage("hero"))? GameImage.getImage("hero_other") : GameImage.getImage("hero");
}
if(this.changeImage){
if(Date.now() > this.changeImageTime){
this.changeImage = false;
_this.speed = 9;
this.image = (this.image == GameImage.getImage("hero_other"))? GameImage.getImage("hero") : GameImage.getImage("hero_other");
}
}
};
return Car;
}(Actor));
But instaed of this I want to follow a path.I also created some grids when u click the image it logs the console which grid it is.But I am unable move the car in a path.For complete understanding the animation is in
animation.
Any help is appreciated
Waypoints as a queue.
For waypoints path following you use a type of array called a queue. As the name suggests the queue holds items that need to be used, specifically they need to be used in the order in which they arrive. The first object on the queue is the first object out (unless you push in line)
In javascript a queue is easy to implement using an array.
const path = {
points : [],
currentPos : null,
dist : 0,
totalDistMoved : 0,
atEnd : false,
addPoint(x,y) {
if(this.currentPos === null){
this.currentPos = { x :0,y : 0};
this.dist = 0;
this.totalDistMoved = 0;
}
this.points.push({x,y}) ;
},
moveAlong(dist){
if(dist > 0){
if(this.points.length > 1){
var x = this.points[1].x - this.points[0].x;
var y = this.points[1].y - this.points[0].y;
var len = Math.sqrt(x*x+y*y) ;
if(len - this.dist < dist){
this.points.shift();
dist -= (len - this.dist);
this.totalDistMoved += (len - this.dist);
this.dist = 0;
this.moveAlong(dist);
return;
}
const frac = this.dist + dist / len;
this.currentPos.x = this.points[0].x + x * frac;
this.currentPos.y = this.points[0].y + y * frac;
this.dist += dist;
this.totalDistMoved += dist;
}else{
this.currentPos.x = this.points[0].x;
this.currentPos.y = this.points[0].y;
this.dist = 0;
this.atEnd = true;
}
}
}
}
To use
Add some way points.
path.addPoint(1,1);
path.addPoint(100,20);
path.addPoint(110,120);
path.addPoint(210,120);
path.addPoint(250,420);
Then for each step of the animations get a distance along
path.moveAlong(10); // move ten pixels
and use the current position
ctx.drawImage(car,path.currentPos.x,path.currentPos.y);
You know you have reached the end of the path when.
if(path.atEnd) {
// you have arrived
}
And at any time you know how far you have moved with
path.totalDistMoved
This is meant for animations that only play forward. It will ignore negative distances as way points are dumped when you have passed them
You will need to make some modifications if you wish to reuse the path object, or if the waypoints are being added as you go
A simple example.
Thing moves along at constant speed. Click on page to add more waypoints.
const ctx = canvas.getContext("2d");
requestAnimationFrame(mainLoop);
function mainLoop(time){
gTime = !gTime ? time : gTime;
fTime = time - gTime;
gTime = time;
if(canvas.width !== innerWidth || canvas.height !== innerHeight){
canvas.width = innerWidth;
canvas.height = innerHeight;
}else{
ctx.setTransform(1,0,0,1,0,0);
ctx.clearRect(0,0,canvas.width,canvas.height);
}
if(mouse.button){
if(!point){
point = {x:0,y:0};
path.addPoint(point);
}
point.x = mouse.x;
point.y = mouse.y;
}else{
if(point){ point = null }
}
ctx.beginPath();
var i = 0;
while(i < path.points.length){ ctx.lineTo(path.points[i].x,path.points[i++].y)}
ctx.strokeStyle = "blue";
ctx.lineWidth = 2;
ctx.stroke();
var i = 0;
while(i < path.points.length){ ctx.strokeRect(path.points[i].x-4,path.points[i++].y-4,8,8)}
path.moveAlong(4 * fTime / 100);
var x = path.currentPos.x - thingPos.x;
var y = path.currentPos.y - thingPos.y;
thingPos.x = path.currentPos.x;
thingPos.y = path.currentPos.y;
drawThing(thingPos.x,thingPos.y,Math.atan2(y,x));
requestAnimationFrame(mainLoop);
}
var point;
const thingPos = {x:0,y:0};
const path = {
points : [],
currentPos : null,
distAlong : 0,
totalDistMoved : 0,
atEnd : false,
addPoint(x,y) {
if(y === undefined){
this.points.push(x); // add point as object
return;
}
if(this.currentPos === null){
this.currentPos = { x :0,y : 0};
this.distAlong = 0;
this.totalDistMoved = 0;
}
this.points.push({x,y}) ;
},
moveAlong(dist){
if(dist > 0){
if(this.points.length > 1){
var x = this.points[1].x - this.points[0].x;
var y = this.points[1].y - this.points[0].y;
var len = Math.sqrt(x*x+y*y) ;
if(len - this.distAlong < dist){
this.points.shift();
dist -= (len - this.distAlong);
this.totalDistMoved += (len - this.distAlong);
this.distAlong = 0;
this.moveAlong(dist);
return;
}
const frac = (this.distAlong + dist) / len;
this.currentPos.x = this.points[0].x + x * frac;
this.currentPos.y = this.points[0].y + y * frac;
this.distAlong += dist;
this.totalDistMoved += dist;
}else{
this.currentPos.x = this.points[0].x;
this.currentPos.y = this.points[0].y;
this.distAlong = 0;
this.atEnd = true;
}
}
}
}
path.addPoint(20,20);
path.addPoint(120,20);
path.addPoint(220,120);
path.addPoint(320,120);
path.addPoint(420,20);
function mouseEvents(e) {
const m = mouse;
m.x = e.pageX;
m.y = e.pageY;
m.button = e.type === "mousemove" ? m.button : e.type === "mousedown";
}
function drawThing(x,y,dir) {
ctx.setTransform(1,0,0,1,x,y);
ctx.rotate(dir);
ctx.fillStyle = "red";
ctx.strokeStyle = "black";
ctx.lineWidth = 2;
ctx.beginPath();
var i = 0;
while(i < thing.length){ ctx.lineTo(thing[i++],thing[i++]) };
ctx.closePath();
ctx.fill();
ctx.stroke();
}
const thing = [-20,-10,20,-10,22,-7,22,7,20,10,-20,10];
var gTime; // global and frame time
var fTime;
const mouse = { x:0,y:0,button:false};
["mousemove","mousedown","mouseup"].forEach(t=>document.addEventListener(t,mouseEvents));
canvas {
position: absolute;
top : 0px;
left : 0px;
}
<canvas id="canvas"></canvas>
click drag to add waypoints.
I'm currently working on a particle system where the particles move around and create pictures with some seconds in between (almost like a slide). I know where to put the color code to change the color on the particles forming the pictures bur for some reason it doesn't work. I therefore suspect that the problem is somewhere else in the script but the question is where...
You can see the code below (tried to make a codepen but it didn't work):
var dispersed = false;
var firstDone = false;
var secondDone = false;
var thirdDone = false;
var fRgba = []; // first img rgba data
var sRgba = []; // second img rgba data
var tRgba = []; // third img rgba data
var WIDTH = window.innerWidth,
HEIGHT = window.innerHeight;
var VIEW_ANGLE = 45,
ASPECT = WIDTH / HEIGHT,
NEAR = 0.01,
FAR = 10000;
var $container = $("#container");
var renderer = new THREE.WebGLRenderer();
var camera = new THREE.PerspectiveCamera(
VIEW_ANGLE,
ASPECT,
NEAR,
FAR);
var scene = new THREE.Scene();
scene.add(camera);
camera.position.z = 900;
renderer.setSize(WIDTH, HEIGHT);
$container.append(renderer.domElement);
var particleCount = 5200,
particles = new THREE.Geometry();
var pMaterial = new THREE.PointsMaterial({
size: 6,
map: createCircleTexture('#CACACA', 256),
transparent: true,
depthWrite: false
});
function createCircleTexture(color, size) {
var matCanvas = document.createElement('canvas');
matCanvas.width = matCanvas.height = size;
var matContext = matCanvas.getContext('2d');
var texture = new THREE.Texture(matCanvas);
var center = size / 2;
matContext.beginPath();
matContext.arc(center, center, size/2, 0, 2 * Math.PI, false);
matContext.closePath();
matContext.fillStyle = color;
matContext.fill();
texture.needsUpdate = true;
return texture;
}
for (var i = 0; i < particleCount; i++) {
var x = Math.random() * 1600 - 800;
var y = getRandomInt(600, 1500)
var z = Math.random() * 30 - 15;
var particle = new THREE.Vector3(x, y, z);
particle.updated = 0;
particles.vertices.push(particle);
};
var particleSystem = new THREE.Points(particles, pMaterial);
particleSystem.sortParticles = true;
scene.add(particleSystem);
function drawImage(imageObj, array) {
var canvas = $("#canvas")[0];
var context = canvas.getContext("2d");
var imageX = 0;
var imageY = 0;
var imageWidth = imageObj.width;
var imageHeight = imageObj.height;
context.drawImage(imageObj, imageX, imageY);
var imageData = context.getImageData(imageX, imageY, imageWidth,
imageHeight);
var data = imageData.data;
for(var y = 0; y < imageHeight; y+= 4) {
for(var x = 0; x < imageWidth; x+= 4) {
var red = data[((imageWidth * y) + x) * 4];
var green = data[((imageWidth * y) + x) * 4 + 1];
var blue = data[((imageWidth * y) + x) * 4 + 2];
var alpha = data[((imageWidth * y) + x) * 4 + 3];
if (red < 100) {
var pX = (x % 500) - 249;
var pY = 249 - y;
array.push([pX, pY, red, green, blue, alpha]);
}
}
}
};
var addDestination = function(particle, x, y, z) {
var dest = new THREE.Vector3(x, y, z);
particle.destination = dest;
};
var addVelocity = function(particle) {
var xDiff = (particle.destination.x - particle.x) / 180;
var yDiff = (particle.destination.y - particle.y) / 180;
var zDiff = (particle.destination.z - particle.z) / 180;
var vel = new THREE.Vector3(xDiff, yDiff, zDiff);
particle.velocity = vel;
};
var move = function(particle) {
particle.x += particle.velocity.x;
particle.y += particle.velocity.y;
particle.z += particle.velocity.z;
particle.updated += 1;
};
var slowDown = function(particle) {
particle.velocity.x -= (particle.velocity.x / 300)
particle.velocity.y -= (particle.velocity.y / 300)
particle.velocity.z -= (particle.velocity.z / 160)
};
var resetProperties = function() {
var pCount = particleCount;
while (pCount--) {
var particle = particles.vertices[pCount];
particle.destination = null
particle.updated = 0;
};
};
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
};
var distributedZ = function(level) {
var z;
if (level === 1) {
z = getRandomInt(50, 100);
} else if (level === 2) {
z = getRandomInt(350, 400);
} else {
z = getRandomInt(650, 700);
}
return z;
};
function shuffle(array) {
var currentIndex = array.length, temporaryValue, randomIndex;
while (0 !== currentIndex) {
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
temporaryValue = array[currentIndex];
array[currentIndex] = array[randomIndex];
array[randomIndex] = temporaryValue;
}
return array;
};
var disperse = function() {
pCount = particleCount;
for (var i = 0; i < pCount; i++) {
var particle = particles.vertices[i];
if (typeof(particle.destination) === "undefined") {
var nums = [-1, 1];
var x = particle.x + nums[Math.round(Math.random())];
var y = particle.y - 1000;
var z = Math.random() * 30 - 15;
addDestination(particle, x, y, z);
particle.velocity = new THREE.Vector3(x - particle.x, -3, z -
particle.z);
}
if (particle.updated <= 300) {
move(particle);
} else {
particles.vertices = shuffle(particles.vertices);
resetProperties();
dispersed = true;
return;
}
}
}
var morphImageParticles = function(imageParticles, rgba) {
for (var i = 0; i < imageParticles.length; i++) {
var particle = imageParticles[i]
if (particle.destination === null) {
var pixelData = rgba[i];
var x = pixelData[0];
var y = pixelData[1];
var z = Math.random() * 15 - 7;
addDestination(particle, x, y, z);
addVelocity(particle);
}
if (particle.updated <= 180) {
move(particle);
}
}
};
var morphOuterParticles = function(outerParticles, ord) {
for (var i = 0; i < outerParticles.length; i++) {
var nums = [-1, 1];
var particle = outerParticles[i];
if (particle.destination === null) {
var x = Math.random() * 1000 - 500;
var y = Math.random() * 1000 - 500;
var z;
if (i <= Math.round(outerParticles.length * 0.6)) {
z = distributedZ(1)
} else if (i > Math.round(outerParticles.length * 0.6) && i <
Math.round(outerParticles.length * 0.9)) {
z = distributedZ(2)
} else {
z = distributedZ(3);
}
addDestination(particle, x, y, z);
addVelocity(particle);
}
if (particle.updated <= 600) {
move(particle);
slowDown(particle);
} else {
particles.vertices = shuffle(particles.vertices);
resetProperties();
if (ord === 1) {
firstDone = true;
} else if (ord === 2) {
secondDone = true;
} else {
thirdDone = true;
}
return;
}
}
};
var makeImg = function(rgba, ord) {
var pCount = particleCount;
var imagePs = particles.vertices.slice(0, rgba.length);
var outerPs = particles.vertices.slice(rgba.length, pCount);
morphImageParticles(imagePs, rgba);
morphOuterParticles(outerPs, ord);
};
var update = function() {
if (thirdDone) {
} else if (secondDone) {
makeImg(tRgba, 3);
} else if (firstDone) {
makeImg(sRgba, 2);
} else if (dispersed) {
makeImg(fRgba, 1);
} else {
disperse();
}
particleSystem.geometry.verticesNeedUpdate = true;
renderer.render(scene, camera);
requestAnimationFrame(update);
TWEEN.update();
};
var rotXScale = d3.scale.linear().domain([0, window.innerHeight]).range([15,
-15]);
var rotYScale = d3.scale.linear().domain([0, window.innerWidth]).range([25,
-25]);
d3.select("body").on("mousemove", function() {
var scaledX = rotXScale(d3.mouse(this)[1]) * Math.PI / 180;
var scaledY = rotYScale(d3.mouse(this)[0]) * Math.PI / 180;
var tween = new TWEEN.Tween(particleSystem.rotation).to({ x: scaledX, y:
scaledY, z: 0 });
tween.easing( TWEEN.Easing.Quartic.Out);
tween.start();
transparency: true
});
var img1 = new Image();
var img2 = new Image();
var img3 = new Image();
img1.onload = function() {
drawImage(this, fRgba);
img2.onload = function() {
drawImage(this, sRgba);
img3.onload = function() {
drawImage(this, tRgba);
}
img3.src = "images/p1.png";
}
img2.src = "images/p2.png";
update();
}
img1.src = "images/p3.png";
update();
I thought I only need to add the code below, for example ['0xffffff'], that's how it should work at least but it didn't. Therefore I guess the problem is somewhere else in the script.
var fRgba = []; // first img rgba data
var sRgba = []; // second img rgba data
var tRgba = []; // third img rgba data
I'm making a simple game (whack a mole), the game works like this:
Every time you press the start button, it will place 10 divs into the DOM.
The divs will be placed randomly into the DOM.
My problem is that they overlap each other and sometimes they're place outside of their container.
I'd like to know how can i place them randomly inside the container without overlapping each other, i prefer not to use a grid to place them, i want them to be randomly distributed across the container.
here's the main function:
function randomPos(size){
var result = new Array();
var height = (document.getElementById('field').clientHeight);
var width = document.getElementById('field').clientWidth;
for (var i = 0; i < size; i++) {
var obj = {};
var posY = Math.floor(Math.random() * height);
var posX = Math.floor(Math.random() * width);
if (result.length == 0){
obj.x = posX;
obj.y = posY;
result.push(obj);
}
else{
var flag = true;
for (var j = 0; j < i && flag; j++){
if (result[j].y == posY && result[j].x == posX){
flag = false;
}
}
if(flag){
obj.x = posX;
obj.y = posY ;
result.push(obj);
}
else{
i--;
}
}
}
return result;
}
here's a jsfiddle
Here's the function that I modified -
function randomPos(size){
var result = new Array();
var height = (document.getElementById('field').clientHeight);
var width = document.getElementById('field').clientWidth;
var generatePos = function(){
// generates the random x and y position, taking into account the size of the object
var posY = Math.floor(Math.random() * (height - 140) + 40);
var posX = Math.floor(Math.random() * (width - 100));
return {x: posX, y: posY}
}
var checkOverlap = function(x, y){
var no_overlap = true
// loops through existing objects and makes sure the newly generated one doesn't overlap
for (var j = 0; j < result.length; j++){
var yDiff = Math.abs(result[j].y - y)
var xDiff = Math.abs(result[j].x - x)
if (yDiff < 100 && xDiff < 100){
no_overlap = false;
}
}
return no_overlap
}
for (var i = 0; i < size; i++) {
var obj = {};
var pos = generatePos()
if (result.length == 0){
obj.x = pos.x;
obj.y = pos.y;
result.push(obj);
}
else{
var no_overlap = checkOverlap(pos.x, pos.y)
if(no_overlap){
obj.x = pos.x;
obj.y = pos.y ;
result.push(obj);
}
else{
i--;
}
}
}
return result;
}
https://jsfiddle.net/s5cv2n8y/6/