mo.h
mo.h

Reputation: 15

How to make the size of ellipse to get smaller and bigger in processing automatically

I am creating something using classes in order to get used to them and I am trying to get the size of the ellipse I have drawn to get smaller and larger on its own so that it makes it look more interactive however I don't know what code to implement.

I have shown the code I am using below;

void setup()
{
  size(640, 480);
}

void draw()
{  
  background(255); 

  for (int i = height-50; i > 0; i-= 20)
  {
    fill(random(255), random(255), random(255));
    ellipse(width/2, height/2, i, i);
  }
}

Upvotes: 0

Views: 9176

Answers (2)

George Profenza
George Profenza

Reputation: 51837

Just to add to Kevin's great answer, here are couple of variations on the same idea (keeping track if the size is increasing or not).

The first approach involves using using a growth speed variable that simply flips sign when a limit is reached. If the size is too small (lower limit) or too big (upper limit), flipping the sign ( multiplying the growth speed by -1 ) will change growing to shrinking and vice-versa:

//current size - continuously updated
float size = 10;
//minimum size
float minSize = 10;
//maximum size
float maxSize = 240;
//change speed for size (how much will the size increase/decrease each frame)
float sizeSpeed = 1.5;

void setup()
{
  size(640, 480);
}

void draw()
{  
  //if the size is either too small, or too big, flip the size speed sign (if it was positive (growing) - make it negative (shrink) - and vice versa)
  if(size < minSize || size > maxSize) {
    sizeSpeed *= -1;
  }
  //increment the size with the size speed (be it positive or negative)
  size += sizeSpeed;

  background(255); 
  fill(random(255), random(255), random(255));
  ellipse(width/2, height/2, size,size);

}

Note that the motion is fairly linear. Since you want to grow and shrink a circle over time, you could get a smoother animation using the sin() function. It takes an angle as an argument and based on the angle value it returns a value between -1.0 and 1.0. You can use the map() function to remap this range to the desired ellipse size:

//current size - continuously updated
float size = 10;
//minimum size
float minSize = 10;
//maximum size
float maxSize = 240;
//change speed for size (how much will the size increase/decrease each frame)
float sizeSpeed = 0.025;

void setup()
{
  size(640, 480);
}

void draw()
{  
  size = map(sin(frameCount * sizeSpeed),-1.0,1.0,minSize,maxSize);

  background(255); 
  fill(random(255), random(255), random(255));
  ellipse(width/2, height/2, size,size);

}

Update In terms of classes, you can start encapsulating the variables used for drawing the ellipse into a class. The syntax isn't that complex:

  1. Use the class keyword, then the name of the class (Uppercase by convention) and add the class members within {} - the classes scope
  2. Create an instance of the class using the new keyword and use . notation to access the instance members

Here's a really basic example using the above:

Ellipse e = new Ellipse();

void setup()
{
  size(640, 480);
}

void draw()
{  
  e.size = map(sin(frameCount * e.sizeSpeed),-1.0,1.0,e.minSize,e.maxSize);

  background(255); 
  fill(random(255), random(255), random(255));
  ellipse(width/2, height/2, e.size,e.size);

}

class Ellipse{
  //current size - continuously updated
  float size = 10;
  //minimum size
  float minSize = 10;
  //maximum size
  float maxSize = 240;
  //change speed for size (how much will the size increase/decrease each frame)
  float sizeSpeed = 0.025;

}

That's a nice and easy start, but the drawing part isn't encapsulated. The same way you declare and use variables in a class, you can declare and use functions. Here's a basic example of simply moving the ellipse drawing functionality into a function:

Ellipse e = new Ellipse();

void setup()
{
  size(640, 480);
}

void draw()
{  

  background(255); 
  e.render();

}

class Ellipse{
  //current size - continuously updated
  float size = 10;
  //minimum size
  float minSize = 10;
  //maximum size
  float maxSize = 240;
  //change speed for size (how much will the size increase/decrease each frame)
  float sizeSpeed = 0.025;

  void render(){
    size = map(sin(frameCount * sizeSpeed),-1.0,1.0,minSize,maxSize);
    fill(random(255), random(255), random(255));
    ellipse(width/2, height/2, size,size);
  }
}

As you notice, it now takes 2 lines to initialize and render an ellipse from the main sketch. There are still things that can be improved. If a second ellipse is created, the x and y is the same so they'd obscure each other. Adding x,y properties to the class will mean each instance will have independent coordinates. On a similar note, frameCount is global, which means, each ellipse uses the same angle/size. We can make that independent too.

Ellipse e1 = new Ellipse(320,240);
Ellipse e2 = new Ellipse(20,20);

void setup()
{
  size(640, 480);
}

void draw()
{  

  background(255);
  e1.render(); 
  e2.render();

}

class Ellipse{
  //current size - continuously updated
  float size = 10;
  //minimum size
  float minSize = 10;
  //maximum size
  float maxSize = 240;
  //change speed for size (how much will the size increase/decrease each frame)
  float sizeSpeed = 0.025;

  //position
  float x,y;

  //internal frameCount replacement
  int tick;

  //constructor
  Ellipse(float x,float y){
    this.x = x;//copy x argument value to the instance (this) x property 
    this.y = y;//copy x argument value to the instance (this) x property
  }

  void render(){
    tick++;
    size = map(sin(tick * sizeSpeed),-1.0,1.0,minSize,maxSize);
    fill(random(255), random(255), random(255));
    ellipse(x,y, size,size);
  }
}

Notice we also added a constructor. A constructor is a very special: it's like an entry point to a new instance. Whenever you create a new instance of a class, the constructor is called, which usually initialises data. The previous example didn't explicitly define a constructor, but Processing provides one with no arguments by default. To take the above concepts a step further, we create a constructor with x,y coordinates:

Ellipse e1 = new Ellipse(320,240);
Ellipse e2 = new Ellipse(20,20);

void setup()
{
  size(640, 480);
}

void draw()
{  

  background(255);
  e1.render(); 
  e2.render();

}

class Ellipse{
  //current size - continuously updated
  float size = 10;
  //minimum size
  float minSize = 10;
  //maximum size
  float maxSize = 240;
  //change speed for size (how much will the size increase/decrease each frame)
  float sizeSpeed = 0.025;

  //position
  float x,y;

  //internal frameCount replacement
  int tick;

  //constructor
  Ellipse(float x,float y){
    this.x = x;//copy x argument value to the instance (this) x property 
    this.y = y;//copy x argument value to the instance (this) x property
  }

  void render(){
    tick++;
    size = map(sin(tick * sizeSpeed),-1.0,1.0,minSize,maxSize);
    fill(random(255), random(255), random(255));
    ellipse(x,y, size,size);
  }
}

This is a very quick overview. For more details, be sure to check out Daniel Shiffman's Objects tutorial.

With that in mind, you can use an ArrayList to create new ellipses at runtime and have some fun randomising ellipse parameters:

ArrayList<Ellipse> ellipses = new ArrayList<Ellipse>();

void setup()
{
  size(640, 480);
  ellipses.add(new Ellipse(width / 2, height / 2));
}

void draw()
{  

  background(255);
  for(Ellipse e : ellipses){
    e.render();
  }
}
//add an ellipse every 5th frame if mouse is dragged
void mouseDragged(){
  if(frameCount % 5 == 0) ellipses.add(new Ellipse(mouseX,mouseY));
}
//remove all ellipses if SPACE is pressed
void keyPressed(){
  if(key == ' ') ellipses.clear();
}

//ellipse class
class Ellipse{
  //current size - continuously updated
  float size = 10;
  //minimum size
  float minSize = 10;
  //maximum size
  float maxSize = 240;
  //change speed for size (how much will the size increase/decrease each frame)
  float sizeSpeed = 0.025;

  //position
  float x,y;

  //internal frameCount replacement
  int tick;

  int fill;


  //constructor
  Ellipse(float x,float y){
    this.x = x;//copy x argument value to the instance (this) x property 
    this.y = y;//copy x argument value to the instance (this) x property
    fill = color(random(32,192));
    sizeSpeed = random(0.025,0.01);
    maxSize = random(120,240);
  }

  void render(){
    tick++;
    size = map(sin(tick * sizeSpeed),-1.0,1.0,minSize,maxSize);
    fill(fill);
    ellipse(x,y, size,size);
  }
}

Upvotes: 1

Kevin Workman
Kevin Workman

Reputation: 42176

You just need to store the width and height of your circle in a variable, use that variable in the draw() function, and then change it whenever you want to change the circle size.

Here is an example program that changes the circle size when you click the mouse:

float radius = 50;

void setup(){
  size(500, 500);
  ellipseMode(RADIUS);
}

void mouseClicked(){
  radius = 250.0*mouseX/width;
}

void draw(){
  background(0);
  ellipse(width/2, height/2, radius, radius);
}

Here is an example program that grows and shrinks the circle automatically:

float radius = 0;
boolean grow = true;

void setup() {
  size(500, 500);
  ellipseMode(RADIUS);
}

void draw() {

  if (grow) {
    radius++;
    if (radius == 250) {
      grow = false;
    }
  } else {
    radius--;
    if (radius == 0) {
      grow = true;
    }
  }

  background(0);
  ellipse(width/2, height/2, radius, radius);
}

But the idea is the same in both examples: just store your circle radius in a variable, change that variable to change the size, and use that variable to draw your circle.

Upvotes: 1

Related Questions