P5js instance mode - how to manage functions?

I am using instance mode for a p5js project and I am trying to figure out the best way to keep my functions organised.

Here is how I had my code organised originally:

var rotateSketch = function(p){
    p.setup = function() {
      p.rotateCanvas = p.createCanvas(800, 600);
      p.rotateCanvas.parent('toyContainer');
      // other set up bits
    };

    p.draw = function(){
      // loads of stuff here,
      // calling functions etc 
    };

    // loads of functions defined here, namespaced using p. 
    // e.g ...

    p.sendMyPoints = function() {
      // Stuff happens here   
    }

    // Also classes defined here 

}

var ps = new p5(rotateSketch);

My program has a lot going on and the definition of rotateSketch grew to over 500 lines and is a nightmare to scroll through. I would like to move the functions and classes I am defining after setup and draw to separate js files to keep them organised.

I am able to do this, I have created separate files and I have tried defining functions there like so

function drawSomeStuffExample(){
  ps.fill(100,100,100); 
  ps.rect(50,50,100,100);
  // ... etc
}

This does work and I’m able to call these functions from within p.setup and p.draw, just using drawSomeStuffExample(); and it is working BUT I just feel like I’m doing it a bit wrong.

Shouldn’t my function drawSomeStuffExample sit within rotateSketch? Is there a way to do that other than having a huge long definition for rotateSketch all in one file? Or does it just not matter that drawSomeStuffExample (and all my other functions) are no longer namespaced to rotateSketch?

Thank you for any insight!

No. Not necessary

It doesn’t matter

Did you try the processing IDE also? It might be easier with big projects. Has also p5.js mode afaik

  • Easy, free download

  • multiple tabs

Chrisir

B/c sendMyPoints() isn’t a p5 callback, like setup() or draw(), you don’t need to attach it to the p5 parameter p.

You can simply define it as an ordinary function: function sendMyPoints() {

That’s very doable & highly recommended!

But if those code happen to access p5 members (such as background(), ellipse(), width, etc.) they’re gonna need to request a p5 argument from its caller.

Let’s say your drawSomeStuffExample() is defined outside your rotateSketch() callback.

Then you’re gonna need to add some p5 parameter to it:

function drawSomeStuffExample(p = p5.instance) {
  p.fill(100).square(50, 50, 100);
}

Then inside your p.draw() callback you can invoke function drawSomeStuffExample() like this:

  p.draw = function () {
    // stuff

    drawSomeStuffExample(p);

    // more stuff
  }

If you don’t pass any parameter to drawSomeStuffExample() it’s gonna assume you’re in global mode and gonna use the default value p5.instance.

You can also take a look at my online sketch “Bouncing Colorful Balls” below:

In its file “ball.js” the class Ball’s constructor() requests a p5 instance:

class Ball {
  constructor(p = p5.instance) {
    this.p = p;
    this.pos = p.createVector();
    this.vel = p.createVector();
    this.reset();
  }

And inside its file “instance.js” a couple of Ball objects are instantiated like this:

for (let i = 0; i < NUM; balls[i++] = new Ball(p));

Obviously the passed argument p is an instance of class p5 of our sketch “instance.js”:

new p5(p => {
  const NUM = 15, balls = Array(NUM).fill();
  let bg;

  p.setup = () => {

Notice on the file “global.js” we don’t need to pass anything to class Ball’s constructor():

  for (let i = 0; i < NUM; balls[i++] = new Ball);

That’s b/c its constructor() defaults to p5.instance value for its parameter p when it’s undefined.

Alternatively we can pass this when on global mode:

  for (let i = 0; i < NUM; balls[i++] = new Ball(this));
2 Likes

I just want to say thank you to @GoToLoop. This is a super helpful and concise example for implementing code separate in instance mode!!

1 Like