The Fault in my Stars (or drawing on top of looping background)

Hello!

I’m fairly new to p5.js and object-oriented programming (or programming in general), though I have been playing around in processing for a while. However, I have run into a problem with my code:

What I’m trying to do:
I’m trying to draw a starry sky, where by clicking on the stars with the mouse, connections appear that create constellations.

here is my code:

var randoms = [];
var stars = [];
var connections = [];
var star;

function setup() {
  createCanvas(windowWidth, windowHeight);
  background(0);
  for (var i = 0; i < 200; i++) {
    randoms[i] = random(windowWidth);
  }
}

function windowResized() {
  resizeCanvas(windowWidth, windowHeight);
}

function draw() {
  //  background(0);
  for (var i = 0; i < 100; i++) {
    stars[i] = new Star(randoms[i], randoms[i + 1]);
  }
  for (var k = 0; k < stars.length; k++) {
    stars[k].show();
    stars[k].shine();
  }
  noFill();
  strokeWeight(1);
}

function mouseReleased() {
  for (var i = 0; i < stars.length; i++) {
    stars[i].starClick(mouseX, mouseY);
    stars[i].connect();
  }
}

class Star {
  constructor(x, y) {
    this.xpos = x;
    this.ypos = y;
    this.diameter = 2;
    this.clicked = false;
  }
  show() {
    if (this.clicked == true) {
      fill(255);
    } else {
      noFill();
    }
    ellipse(this.xpos, this.ypos, this.diameter, this.diameter);

  }
  shine() {
    stroke(255);
    strokeWeight(map(dist(mouseX, mouseY, this.xpos, this.ypos), 0, sqrt(sq(width) + sq(height)), 5, 0));
  }
  starClick(nx, ny) {
    if (dist(nx, ny, this.xpos, this.ypos) < this.diameter + 5) {
      this.clicked = !this.clicked;
      connections.push(this.xpos, this.ypos);
    }
  }

  connect() {
    if (connections.length >= 4) {
      stroke(255);
      strokeWeight(1);
      beginShape();
      vertex(connections[0], connections[1]);
      vertex(connections[2], connections [3]);
        endShape();
      connections.splice(0, 2);

    }
  }

}

What doesn’t work:

  1. The lines appear when I only draw the background in setup() (as you can see, I commented it out in draw()), but in order for shine() to work, I need to loop the background - but that of course makes the lines disappear, because I draw over them.
  2. I can’t end the shape to start a new constellation.

What do I need?

  1. A way to activate the lines by clicking on them, but then looping them in draw permanently, so they don’t disappear.
  2. A way to end a shape when I’ve re-clicked the first initialized point and store that shape so I can do stuff with it (e.g. give it a fill) while also being able to start a new shape.

I know that this is a lot, I’m just wondering if anyone out there could point me in the right direction or tell me if I’m going about this all wrong, because I really want to figure this one out. Thank you in advance :slight_smile:

2 Likes

Cool project! Here’s one approach to drawing multiple constellations that makes connections a 2D array containing the coordinates set by starClick().

let randoms = [];
let stars = [];
let connections = [
  []
];
let star;
let numStars = 100;
let cn = 0; // constellation number

function setup() {
  createCanvas(windowWidth, windowHeight);
  background(0);
  for (let i = 0; i < 2 * numStars; i += 1) {
    randoms[i] = random(windowWidth);
  }

  for (let i = 0; i < numStars; i += 1) {
    stars[i] = new Star(randoms[i], randoms[i + 1]);
  }
}

function windowResized() {
  resizeCanvas(windowWidth, windowHeight);
}

function draw() {
  background(0);
  for (let k = 0; k < stars.length; k += 1) {
    stars[k].show();
    stars[k].shine();
  }

  connectStars();
}

function mouseReleased() {
  for (let i = 0; i < stars.length; i += 1) {
    stars[i].starClick(mouseX, mouseY);
  }
}

class Star {
  constructor(x, y) {
    this.xpos = x;
    this.ypos = y;
    this.diameter = 2;
    this.clicked = false;
  }

  show() {
    if (this.clicked) {
      fill(255);
    } else {
      noFill();
    }
    ellipse(this.xpos, this.ypos, this.diameter, this.diameter);
  }

  shine() {
    stroke(255);
    strokeWeight(map(dist(mouseX, mouseY, this.xpos, this.ypos), 0, sqrt(sq(width) + sq(height)), 0, 5));
  }

  starClick(nx, ny) {
    if (dist(nx, ny, this.xpos, this.ypos) < this.diameter + 5) {
      if (connections[cn].length >= 4 && this.xpos === connections[cn][0] && this.ypos === connections[cn][1]) {
        connections.push([]);
        cn += 1;
      } else {
        this.clicked = !this.clicked;
        connections[cn].push(this.xpos, this.ypos);
      }
    }
  }
}

function connectStars() {
  noFill();
  stroke(255);
  strokeWeight(1);
  for (let i = 0; i < connections.length; i += 1) {
    if (connections[i].length >= 4) {
      beginShape();
      for (let j = 0; j < connections[i].length; j += 2) {
        vertex(connections[i][j], connections[i][j + 1]);
      }

      endShape();
    }
  }
}
2 Likes

Thank you so much, this is exactly what I was looking for! :slight_smile: Thanks for taking the time to look at my project!