p5.js: How to build a starfield

In this article, I will show how to build a starfield in p5.js. The starfield is presented as if you are flying through a field of stars, where the closer stars are bigger and there is an appearance of light streaking as your speed increases. This sketch is interactive in that moving the mouse to the right makes the stars fly faster, and moving the mouse to the left makes them appear to fly slower.

Here is what the final result looks like:

This p5.js code features use of a class called Star that has a constructor and two other functions called update() and show(). For example:

class Star {
    constructor() {
    	this.x = random(-width, width);
        this.y = random(-height, height);
        this.z = random(width);      
        this.pz = this.z;
    }
    update() {
        this.z = this.z - speed;
        if (this.z < 1) {
      	    this.z = width;
            this.x = random(-width, width);
            this.y = random(-height, height);
            this.pz = this.z;
        }
    }
    show() {
        fill(255);
        noStroke();
      
        var sx = map(this.x/this.z, 0, 1, 0, width);
        var sy = map(this.y/this.z, 0, 1, 0, height);
        var r = map(this.z, 0, width, 12, 0);
        ellipse(sx, sy, r, r);    
      
        var px = map(this.x/this.pz, 0, 1, 0, width);
        var py = map(this.y/this.pz, 0, 1, 0, height);
        this.pz = this.z;
      
        stroke(255);
        line(px, py, sx, sy);
    }
}

It also uses an array called stars where 1600 stars of random x, y, and z postions are created.

var stars = [];

Values for the array are generated like so (inside the setup() function):

// Create an array of 1600 star objects
for (var i = 0; i < 1600; i++) {
    stars[i] = new Star();

    // This also works to populate the array
    // star = new Star();
    // append(stars, star);
}

Stars are drawn on the screen inside the draw() function by iterating over the stars array:

for (var i = 0; i < stars.length; i++) {
    stars[i].update();
    stars[i].show();
}

Another interesting feature of this code is use of the p5.js map() method, which remaps a number from one range to another. This is useful for mapping a range of numbers to the boundaries of a screen for example.

For more information about the map() method, see:
https://p5js.org/reference/#/p5/map

Here is the complete p5.js code:

var stars = [];
var speed;

class Star {
    constructor() {
    	this.x = random(-width, width);
        this.y = random(-height, height);
        this.z = random(width);      
        this.pz = this.z;

    }
    update() {
      this.z = this.z - speed;
      if (this.z < 1) {
      	this.z = width;
        this.x = random(-width, width);
        this.y = random(-height, height);
        this.pz = this.z;
      }
    }
  
    show() {
      fill(255);
      noStroke();
      
      var sx = map(this.x/this.z, 0, 1, 0, width);
      var sy = map(this.y/this.z, 0, 1, 0, height);
      var r = map(this.z, 0, width, 12, 0);
      ellipse(sx, sy, r, r);    
      
      var px = map(this.x/this.pz, 0, 1, 0, width);
      var py = map(this.y/this.pz, 0, 1, 0, height);
      this.pz = this.z;
      
      stroke(255);
      line(px, py, sx, sy);
    }
}

function setup() {
    createCanvas(600, 600);
    star = new Star();
  
    // Create an array of 1600 star objects
    for (var i = 0; i < 1600; i++) {
      	stars[i] = new Star();
      
        // This also works to populate the array
      	// star = new Star();
  	// append(stars, star);
    }
}

function draw() {
    speed = map(mouseX, 0, width, 5, 30);
    background(0);
    translate(width/2, height/2);
  
    for (var i = 0; i < stars.length; i++) {
    	stars[i].update();
      	stars[i].show();
    }
}

The code in this article is based on The Coding Train – “Coding Challenge #1: Starfield in Processing“.  In this video, the sketch was coded by Daniel Shiffman in Processing. As I followed along, I translated it into p5.js. Then I double checked my code against the p5.js code that was posted on github. My code does have some small differences.