Translate processing to p5.js

Viewed 67

Could someone explain to me why this translation doesn't work? Since I'm super new to both processing and p5.js, I keep getting error messages...

This is the processing code that I'd like to change.

Particle[] particles;
float alpha;

void setup() {
  size(900, 500);
  background(0);
  noStroke();
  setParticles();
}

void draw() {
  frameRate(30);
  alpha = map(height, 0, width, 5, 35);
  fill(4, 255);
  rect(0, 0, width, height);
  background(0);

  loadPixels();
  for (Particle p : particles) {
    p.move();
  }
  updatePixels();
}

void setParticles() {
  particles = new Particle[10000]; 
  for (int i = 0; i < 10000; i++) { 
    float x = random(width);
    float y = random(height);
    float adj = map(y, 0, height, 255, 0);
    int c = color(60, adj, 255);
    particles[i]= new Particle(x, y, c);
  }
}

void mousePressed() {
  setParticles();
}

class Particle {
  float posX, posY, incr, theta;
  color  c;

  Particle(float xIn, float yIn, color cIn) {
    posX = xIn;
    posY = yIn;
    c = cIn;
  }

  public void move() {
    update();
    wrap();
    display();
  }

  void update() {
    incr +=  .008;
    theta = noise(posX * .006, posY * .008, incr) * TWO_PI;
    posX += 2 * tan(theta);
    posY += 2 * sin(theta);
  }

  void display() {
    if (posX > 0 && posX < width && posY > 0  && posY < height) {
      pixels[(int)posX + (int)posY * width] =  c;
    }
  }

  void wrap() {
    if (posX < 0) posX = width;
    if (posX > width ) posX =  0;
    if (posY < 0 ) posY = height;
    if (posY > height) posY =  0;
  }
}

And this is the p5.js translation which doesn't work.

var particles;
let particle  = [];
const num = 100;

function setup() {
    createCanvas(900, 500);
    background(0);
    noStroke();
    setParticles();
}

function draw() {
    frameRate(30);
    let alpha = map(height, 0, width, 5, 35);
    fill(0, alpha);
    rect(0, 0, width, height);
    loadPixels();
    for (var i = 0; i < num; i++) { 
    particles[i].update();
    particles[i].display();
    particles[i].wrap();
    }
    updatePixels();
}

function setParticles() {
    particles = new Array(10000);
    for (var i = 0; i < 10000; i++) {
        var x = random(width);
        var y = random(height);
        var adj = map(y, 0, height, 255, 0);
        let c = color(60, adj, 255);
        particles[i] = new Particle(x, y, c);
    }
}

function mousePressed() {
    setParticles();
}

function Particle (xln, yln, cln) {
    this.posX = xln;
    this.posY = yln;
    this.c = cln;

this.update = function() {
    this.incr += .008;
    this.theta = noise(this.posX * .006, this.posY * .008, this.incr) * TWO_PI;
    this.posX += 2 * tan(this.theta);
    this.posY += 2 * sin(this.theta);
}

this.display = function() {
    if (this.posX > 0 && this.posX < width && this.posY > 0 && this.posY < height) {
        pixels[int(this.posX) + int(this.posY) * width] = c;
    }
}

this.wrap = function() {
    if (this.posX < 0)
        this.posX = width;
    if (this.posX > width)
        this.posX = 0;
    if (this.posY < 0)
        this.posY = height;
    if (this.posY > height)
        this.posY = 0;
}
}

I'll be a great help if anyone with experience could help me!

1 Answers

Cool project! You're very close there were just a few things that needed tweaking.

If you plonk a console.log(this.posX) in the display() function you'll see that it's NaN, if you trace your steps you'll notice that it's caused by:

this.theta = noise(this.posX * 0.006, this.posY * 0.008, this.incr) * TWO_PI;
this.posX += 2 * sin(this.theta);

The problem here being that this.incr wasn't defined, so adding this.incr = 0 to the constructor fixes that.

The following line in the display function is missing a this. for c:

pixels[int(this.posX) + int(this.posY) * width] = c; // should be this.c

You're also not looping through all of the particles, which may be a concious decision but it looks pretty awesome when you do:

  for (var i = 0; i < particles.length; i++) {
    particles[i].update();
    particles[i].display();
    particles[i].wrap();
  }

When dealing with pixels you have to consider that there are 4 elements in the pixels array which represent the R, G, B, A values in order of each pixel. So to get the index of a given X and Y:

  let index =  (int(this.posX) + int(this.posY) * width) * 4;

And lastly, you'll probably need to set pixelDensity(1) so that it covers the whole screen, more information can be found in the p5.js docs.

I've used es6 classes rather than functions, but the premise is the same:

var particles = [];
let particle = [];
const num = 100;

function setup() {
  createCanvas(900, 400);
  pixelDensity(1);
  background(0);
  noStroke();
  setParticles();
}

function draw() {
  frameRate(30);
  let alpha = map(height, 0, width, 5, 35);
  fill(0, alpha);
  rect(0, 0, width, height);
  loadPixels();
  for (var i = 0; i < particles.length; i++) {
    particles[i].update();
    particles[i].display();
    particles[i].wrap();
  }
  updatePixels();
}

function setParticles() {
  particles = new Array(10000);
  for (var i = 0; i < 10000; i++) {
    var x = random(width);
    var y = random(height);
    var adj = map(y, 0, height, 255, 0);
    let c = color(60, adj, 255);
    particles[i] = new Particle(x, y, c);
  }
}

function mousePressed() {
  setParticles();
}

class Particle {
  constructor(xln, yln, cln) {
    this.posX = xln;
    this.posY = yln;
    this.c = cln;
    this.incr = 0;
  }

  update() {
    this.incr += 0.008;
    this.theta = noise(this.posX * 0.006, this.posY * 0.008, this.incr) * TWO_PI;
    this.posX += 2 * tan(this.theta);
    this.posY += 2 * sin(this.theta);
  }

  display() {
    if (
      this.posX > 0 &&
      this.posX < width &&
      this.posY > 0 &&
      this.posY < height
    ) {
      let index =  (int(this.posX) + int(this.posY) * width) * 4;
      pixels[index] = this.c; 
      pixels[index+1] = this.c; 
      pixels[index+2] = this.c; 
      pixels[index+3] = this.c; 
    }
  }

  wrap() {
    if (this.posX < 0) this.posX = width;
    if (this.posX > width) this.posX = 0;
    if (this.posY < 0) this.posY = height;
    if (this.posY > height) this.posY = 0;
  }
}
html, body {
  margin: 0;
  padding: 0;
}
canvas {
  display: block;
}
<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/addons/p5.sound.min.js"></script>
    <link rel="stylesheet" type="text/css" href="style.css">
    <meta charset="utf-8" />

  </head>
  <body>
    <main>
    </main>
    <script src="sketch.js"></script>
  </body>
</html>

And here's a link to the p5.js editor sketch.

Related