Using colors with variables

Hello. My problem is that when you press tab (to make the ellipse color be random) it works fine. But, when you change the size of the ellipse (with keys 1-3) the ellipse color isn’t random anymore, but on the last random color it was on. What I want, is that when you change the size of the ellipse, it keeps changing to random colors instead of freezing to one.

PGraphics circles;
//Variables for the size and color of the ball and the text
float right = 50;
float left = 50;
float bin = 0;
float ban = 0;
float bam = 0;
float lop = 110;


void setup() 
{
  //Setup the window
  size(1280, 730);
  background(255);
  fill(0);

  circles = createGraphics(1280, 730); 
}

void draw() 
{
  //Setup
  background(255);
  noStroke();
  noCursor();
  //When different keys are pressed they change the color of the ellipse
  if (key == TAB)
  {
    bin = random(255);
    ban = random(255);
    bam = random(255);
  }
  //Press keys 0-9 to change size of the ellipse
  if (key == '1')
  {
    right=10;
    left=10;
    lop=90;
  }
  if (key == '2')
  {
    right=20;
    left=20;
    lop=95;
  }
  if (key == '3')
  {
    right=30;
    left=30;
    lop=100;
  }
  if (key == ' ')
  {
    background(255);
    circles.beginDraw();
    circles.background(255);
    circles.endDraw();
  }
  //If mouse is pressed, then draw 
  if (mousePressed)
  {
    circles.beginDraw();
    circles.noStroke();
    circles.fill(bin, ban, bam);
    circles.ellipse(mouseX, mouseY, right, left);
    circles.endDraw();
  }
  //Print the second plane
  image(circles, 0, 0);
  //If mouse isn't pressed, show the ellipse but dont draw it
  fill(bin, ban, bam);
  ellipse(mouseX, mouseY, right, left);
}

Hi again :slight_smile:

Instead of checking the last key that was pressed with you if statements: if (key == xxx) you should try using the keyPressed() function.

You get inside everytime the user press a key and this is where you can put all of your code. You just need to switch some variables to remember the mode you are using - random or fixed color.

Check this example:

PGraphics circles;
//Variables for the size and color of the ball and the text
boolean randomCol;
int size;


void setup() 
{
  //Setup the window
  size(1280, 730);
  background(255);
  fill(0);

  circles = createGraphics(1280, 730); 

  randomCol = false;
  size = 10;
}

void draw() 
{
  //Setup
  background(255);
  noStroke();
  noCursor();
  //When different keys are pressed they change the color of the ellipse
  color col;
  if (randomCol) {
    col = color(random(255), random(255), random(255));
  } else {
    col = color(0);
  }


  //If mouse is pressed, then draw 
  if (mousePressed)
  {
    circles.beginDraw();
    circles.noStroke();
    circles.fill(col);
    circles.ellipse(mouseX, mouseY, size, size);
    circles.endDraw();
  }
  //Print the second plane
  image(circles, 0, 0);
  //If mouse isn't pressed, show the ellipse but dont draw it
  fill(col);
  ellipse(mouseX, mouseY, size, size);
}


void keyPressed() {
  if (key == TAB)
  {
    randomCol = !randomCol;
  }
  //Press keys 0-9 to change size of the ellipse
  if (key == '1')
  {
    size = 10;
  }
  if (key == '2')
  {
    size = 20;
  }
  if (key == '3')
  {
    size = 30;
  }
}

@jb4x Thanks for your code. It works, but now I am confused when I want to implement multiple colors so when you press different keys, it changes to other colors.

The spirit is the same.

First create a global color variable:

color circleColor;

void setup() {
  ...
}

Then, let’s you want a red color when pressing the ‘r’ key. You would write something like this:

if (key == 'r') {
  randomCol = false; //We don't want random colors anymore
  circleColor = color(255, 0, 0);

And of course in draw() you need to change to filling color to match that color variable :slight_smile:

@jb4x Sorry but I am a bit confused in what you are saying. So do I replace randomcol with circleColor?

What I think @jb4x means is that you won’t replace randomCol with circleColor, instead what you’re basically checking, is first, if randomCol is true or not. If it is true, then when you start drawing, it will start drawing at the random color. If you press a key, for example “r”, then you will start drawing red, for example.

Here:

  color col;
  if (randomCol) {
    col = color(random(255), random(255), random(255));
  } else {
    col = color(0);
  }

You are doing that check. If randomCol, do your random color, if not, that color will be black. And then here:

fill(col);
ellipse(mouseX, mouseY, size, size);

Is where you are drawing everything, pay most attention to the line with the fill. Then you have this:

if (key == 'r') {
  randomCol = false; //We don't want random colors anymore
  circleColor = color(255, 0, 0);

I don’t know specifically why we are setting a new color variable here, so forgive me if I’m wrong when I say that you could just do

col = color(255,0,0);

In there, instead of setting a new variable. Of course if you set a new variable you can just make the col variable equal to it somewhere later on in the code, so when you draw your ellipses it comes out as the color that you want it to be.

Hopefully that clarified things a bit?

EnhancedLoop7

1 Like

@EnhancedLoop7 @jb4x thank you I have solved the problem

@EnhancedLoop7 @jb4x Is there a way that when you put an ellipse command (in void draw) that when it moves around really fast, instead of leaving a trace of circles, to have all of the circles connected so it covers all of it up.

Hi Lore,

Everything’s possible :slight_smile:

In photoshop, what you are referring to is called the step of a brush. Basically that’s a value that control the spacing between two strokes of a brush.

If you are going too fast so it leaves space in between each strokes, you just need to assume the brush went straight between those two positions and add some “fake” strokes every step value. If step value is small enough, it should solve your issue.

@jb4x
Thanks for the reply :grin:

how do I increase or decrease the step value?

That is yours to code, there is no built-in functions for that.

Here is an example. It allows just two mouse click: the first one sets the starting point and the second one the end point. You can play with the step value to see how it affects the result:

int step;
int nbOfStrokes;
int prevY, prevX;

void setup() {
  size(800, 600);
  step = 1;
  nbOfStrokes = 0;
  background(20);
  fill(255, 25, 25);
  noStroke();
}

void draw() {
  
}

void mousePressed() {
  if (nbOfStrokes == 0) {
    prevY = mouseY;
    prevX = mouseX;
    ellipse(mouseX, mouseY, 20, 20);
  } else if (nbOfStrokes == 1) {
    interpolateStrokes(prevX, prevY, mouseX, mouseY);
  }
  
  nbOfStrokes++;
}

void interpolateStrokes(int prevX, int prevY, int newX, int newY) {
  PVector dir = new PVector(newX - prevX, newY - prevY);
  int maxLength = (int)pow(dir.mag(), 2);
  
  dir.normalize();
  dir.mult(step);
  
  PVector pos = new PVector(prevX, prevY);
  pos.add(dir);
  
  while ((pos.x - prevX) * (pos.x - prevX) + (pos.y - prevY) * (pos.y - prevY) < maxLength) {
    ellipse(pos.x, pos.y, 20, 20);
    pos.add(dir);
  }
}

@jb4x

Thank you for the answer, but it seems a little bit complicated for me as I don’t know how I would code it myself.

Take your time, try to understand the logic behind the code, code simple example to adapt the logic to your specific problem and then include it to your project.

Take it step by step and you will manage :slight_smile:

I’ll try to give you more details:

What really interests you is the interpolateStrokes() function.
It takes 4 arguments:

  • prevX: the X position of the last circle you draw
  • prevY : the Y position of the last circle you draw
  • newX: the X position of the new circle you want to draw
  • newY: the Y position of the new circle you want to draw
PVector dir = new PVector(newX - prevX, newY - prevY);

Here you create an arrow that starts in your previous circle and point to the new one you want to draw

int maxLength = (int)pow(dir.mag(), 2);

Here you just compute the distance between your 2 circles. The power of 2 is facultative: I’m using it to avoid to compute a square root in the if statement later on.

dir.normalize();

Here, I’m taking the previous big arrow and change its length to be one (but keeping the direction so it starts at the previous circle and still point in the direction of the new one but without being able to reach it).

dir.mult(step);

Now you multiply it by the step size so its length will be the step size. It will now point right were you should draw the next cricle

PVector pos = new PVector(prevX, prevY);

This vector will keep track of where you should draw your circles. You set it first to be where the previous circle is.

pos.add(dir);

Now you can add the previous vector to get the position of the next circle you want to draw.

while ((pos.x - prevX) * (pos.x - prevX) + (pos.y - prevY) * (pos.y - prevY) < maxLength) {
  ellipse(pos.x, pos.y, 20, 20);
  pos.add(dir);
}

Finally you draw the ellipse at the new position and find the next position by adding the previous vector.
You do it until the distance between the previous circle and the one you want to draw becomes higher than the distance between the previous circle and where you wanted your last circle to be.

Hope it clears out some stuff

@jb4x

So by replacing the x and y that will draw a line connecting the previous circle with the next circle placed?