how do I create a trailing pattern in processing? - processing

I'm trying to create a program, wherein the ellipses revolve around the center screen and add a trailing pattern to it. I'm using ArrayList in processing to store the old vector then draw it, but it's not rendering. Or am I doing things wrong? The part where I wrote it is on the bottom part, thank you.
Particle[] part = new Particle[10];
int len = 10;
void setup(){
size(1000,1000,P2D);
//fullScreen();
for(int i = 0; i < len; i++){
part[i] = new Particle();
}
}
void draw(){
background(255);
for(int i = 0; i < len; i++){
part[i].show();
part[i].update();
part[i].trail();
}
}
class Particle{
float r,angle,d;
PVector pos = new PVector();
ArrayList<PVector> history = new ArrayList<PVector>();
Particle(){
angle = random(20,360);
r = random(20,300);
pos.x = width/2 + cos(angle) * r;
pos.y = height/2 + sin(angle) * r;
}
void show(){
stroke(0,0,255);
ellipse(pos.x,pos.y,5,5);
//line(x,y,width/2,height/2);
}
void update(){
pos.x = width/2 + cos(angle) * r;
pos.y = height/2 + sin(angle) * r;
angle += random(0.001,0.01);
}
void trail(){
history.add(pos);
if(history.size() > 50){
history.remove(0);
}
for(int i = 0; i < history.size(); i++){
PVector prev = history.get(i);
ellipse(prev.x,prev.y,5,5);
}
}
}

When you do
history.add(pos);
then you do not create a new PVector object. You just add a reference to the attribute pos to the array list history. When pos is changed, then still all elements of history refer to pos. There exist just one PVecor object for each Particle.
Create a copy of pos when you add it to history, to solve the issue:
history.add(pos.copy());

Related

How to change the position of each PVector objects in an ArrayList that is made by an ArrayList?

I am currently working on an ArrayList of an ArrayList that I want the outer ArrayList to have different locations.
So I tried to use thetranslate(); to distinguish the position of the outer ArrayList but it doesn't work. On screen it is still showing all the ArrayList at one place.
I have also tried to multiply the points location with point(v3.x * gap, v3.y * gap, v3.z * gap); but it doesn't work neither.
Does anyone knows is ther a way on how can I alter the location of outer ArrayList?
Here are the codes I am working on:
//import
import peasy.*;
//import variables
PeasyCam acam;
//position variable for pointSphere
float x;
float y;
float z;
float gap = 500;
//arraylist of arraylist
ArrayList<ArrayList <PVector>> sphereList = new ArrayList<ArrayList<PVector>>();
//empty arraylist
ArrayList<PVector> sphere1 = new ArrayList<PVector>();
void setup() {
size(1920, 1080, P3D);
//camera setting
acam = new PeasyCam(this, 500, 500, 500, 2000);
acam.rotateX(0);
acam.rotateY(0);
acam.rotateZ(0);
pointSphere(270, 27, 27);
}
void draw() {
background(0);
for (int i = 0; i < sphere1.size(); i++) {
PVector v1;
v1 = sphere1.get(i);
stroke(255);
strokeWeight(random(2, 10));
point(v1.x, v1.y, v1.z);
for (int j = 0; j < sphereList.size(); j++) {
PVector v3;
v3=sphereList.get(i).get(j);
pushMatrix();
gap = gap + 500;
translate(1000 + gap, 1000 + gap, 1000 + gap);
point(v3.x, v3.y, v3.z);
popMatrix();
}
}
}
void pointSphere (float r, float uAmount, float wAmount) {
for (float u= 0; u < 180; u += 180/uAmount) {
for (float w = 0; w < 360; w += 360/wAmount) {
//define PVector
PVector vS1 = new PVector(r*sin(radians(u))*cos(radians(w)), r*sin(radians(u))*sin(radians(w)), r*cos(radians(u)));
//storing the location of Pvector into sphere1
sphere1.add(vS1);
sphereList.add(sphere1);
}
}
}
You have most of the "ingredients" in place (sphere points, a scene to render into, translate to offset each sphere, etc.), however there are two sections that are confusing:
1.ArrayList<ArrayList <PVector>> sphereList = new ArrayList<ArrayList<PVector>>(); this would store a list of lists of points. Do you need to render multiple spheres each with a different set of points (e.g. different float r, float uAmount, float wAmount values ?) If so, this makes sense. However if you simply want to render the same sphere in different locations, you can get away with 1 list of points (i.e. just sphere1) and render it in multiple locations.
The nested for loops in draw(): the first loop accesses and draws the sphere points. The second loop iterates for every sphere point (which is a lot). This second loop would iterate through each point and translate.
If simply rendering the same sphere 3 times in 3 locations, you can translate the group of points (i.e. before the for loop rendering each point).
Here's one way of writing it:
I recommend tweaking the pointSphere() points function so it returns the points (instead of using the hardcoded list to add points to). The advantage is you can calculate sphere points with various settings that can be stored into independent lists of points (as opposed to the single hardcoded list). (Additionally, you could easily reuse this function in other sketches as it requires copything the function indepdent of the hardcoded list of points)
e.g.
ArrayList<PVector> pointSpherePoints(float r, float uAmount, float wAmount) {
ArrayList<PVector> points = new ArrayList<PVector>();
for (float u= 0; u < 180; u += 180/uAmount) {
for (float w = 0; w < 360; w += 360/wAmount) {
//define PVector
PVector vS1 = new PVector(r*sin(radians(u))*cos(radians(w)), r*sin(radians(u))*sin(radians(w)), r*cos(radians(u)));
//storing the location of Pvector
points.add(vS1);
}
}
return points;
}
you can write a function that renders a list of points which can be reused.
void drawSpherePoints(ArrayList<PVector> points){
for (int i = 0 ; i < points.size(); i++) {
PVector v = points.get(i);
stroke(255);
strokeWeight(random(2, 10));
point(v.x, v.y, v.z);
}
}
Putting the two together makes it simple to render the sphere in different places:
//import
import peasy.*;
//import variables
PeasyCam acam;
ArrayList<PVector> sphere1 = pointSpherePoints(270, 27, 27);
void setup() {
size(1920, 1080, P3D);
//camera setting
acam = new PeasyCam(this, 500, 500, 500, 2000);
acam.rotateX(0);
acam.rotateY(0);
acam.rotateZ(0);
}
void draw() {
background(0);
translate(width * 0.5, height * 0.5);
float gap = -1000;
for(int i = 0 ; i < 3; i++){
gap = gap + 500;
translate(1000 + gap, 1000 + gap, 1000 + gap);
drawSpherePoints(sphere1);
}
}
void drawSpherePoints(ArrayList<PVector> points){
for (int i = 0 ; i < points.size(); i++) {
PVector v = points.get(i);
stroke(255);
strokeWeight(random(2, 10));
point(v.x, v.y, v.z);
}
}
ArrayList<PVector> pointSpherePoints(float r, float uAmount, float wAmount) {
ArrayList<PVector> points = new ArrayList<PVector>();
for (float u= 0; u < 180; u += 180/uAmount) {
for (float w = 0; w < 360; w += 360/wAmount) {
//define PVector
PVector vS1 = new PVector(r*sin(radians(u))*cos(radians(w)), r*sin(radians(u))*sin(radians(w)), r*cos(radians(u)));
//storing the location of Pvector
points.add(vS1);
}
}
return points;
}
The encapsulation makes it easier to draw spheres with independent parameters (radius, detail level):
//import
import peasy.*;
//import variables
PeasyCam acam;
int numSpheres = 3;
ArrayList<ArrayList<PVector>> spheres = new ArrayList<ArrayList<PVector>>();
void setup() {
size(1920, 1080, P3D);
//camera setting
acam = new PeasyCam(this, 500, 500, 500, 2000);
for(int i = 0 ; i < numSpheres ; i++){
int detailLevel = i + 1;
spheres.add(pointSpherePoints(30 * (detailLevel * 2), 9 * detailLevel, 9 * detailLevel));
}
}
void draw() {
background(0);
translate(width * 0.5, height * 0.5);
for(int i = 0 ; i < numSpheres ; i++){
ArrayList<PVector> sphere = spheres.get(i);
translate(100 * i, 0, 0);
drawSpherePoints(sphere);
}
}
void drawSpherePoints(ArrayList<PVector> points){
for (int i = 0 ; i < points.size(); i++) {
PVector v = points.get(i);
stroke(255);
strokeWeight(random(2, 10));
point(v.x, v.y, v.z);
}
}
ArrayList<PVector> pointSpherePoints(float r, float uAmount, float wAmount) {
ArrayList<PVector> points = new ArrayList<PVector>();
for (float u= 0; u < 180; u += 180/uAmount) {
for (float w = 0; w < 360; w += 360/wAmount) {
//define PVector
PVector vS1 = new PVector(r*sin(radians(u))*cos(radians(w)), r*sin(radians(u))*sin(radians(w)), r*cos(radians(u)));
//storing the location of Pvector
points.add(vS1);
}
}
return points;
}
or even a sphere of spheres:
//import
import peasy.*;
//import variables
PeasyCam acam;
ArrayList<PVector> sphere1 = pointSpherePoints(270, 27, 27);
void setup() {
size(1920, 1080, P3D);
//camera setting
acam = new PeasyCam(this, 500, 500, 500, 2000);
}
void draw() {
background(0);
translate(width * 0.5, height * 0.5);
for(int i = 0 ; i < sphere1.size(); i += 10){
// scale vector point
PVector v = PVector.mult(sphere1.get(i), 10);
pushMatrix();
translate(v.x, v.y, v.z);
drawSpherePoints(sphere1);
popMatrix();
}
}
void drawSpherePoints(ArrayList<PVector> points){
for (int i = 0 ; i < points.size(); i++) {
PVector v = points.get(i);
stroke(255);
strokeWeight(random(2, 10));
point(v.x, v.y, v.z);
}
}
ArrayList<PVector> pointSpherePoints(float r, float uAmount, float wAmount) {
ArrayList<PVector> points = new ArrayList<PVector>();
for (float u= 0; u < 180; u += 180/uAmount) {
for (float w = 0; w < 360; w += 360/wAmount) {
//define PVector
PVector vS1 = new PVector(r*sin(radians(u))*cos(radians(w)), r*sin(radians(u))*sin(radians(w)), r*cos(radians(u)));
//storing the location of Pvector
points.add(vS1);
}
}
return points;
}

Trying to make a ball bounce on the screen in processing using classes

I am working on making a single ball bounce all over the screen but I have an issue with making the ball bounce the bounce() function is responsible for making the ball bounce but I run into an array out of bounds exception despite only going through 1 element in the array. I have provided the code below. This code utilizes 2 classes (Ball_Usage and Ball).
Ball_Usage code:
Ball ball1;
void setup(){
size(500,500);
ball1 = new Ball();
}
void draw(){
background(255);
ball1.bounce();
}
Ball:
class Ball{
float [] xPos = {};
float [] yPos = {};
float [] dia = {};
float [] xSpeed = {};
float [] ySpeed = {};
Ball(){
}
Ball(float x, float y, float argDia){
xPos = append(xPos, x);
yPos = append(yPos, y);
dia = append(dia, argDia);
}
void bounce(){
for(int i=0; i<1; i++){
ellipse(xPos[i], yPos[i], 50, 50);
xPos[i] += xSpeed[i];
yPos[i] += ySpeed[i];
if(xPos[i]<0 || xPos[i]>=width){
xSpeed[i] = -xSpeed[i];
}
if(yPos[i]<0 || yPos[i]>=height){
ySpeed[i] = -ySpeed[i];
}
}
}
}
I believe the confusion comes from the fact that your class has two constructors:
an empty constructor (that takes no arguments): Ball()
a constructor with position and argDia (guessing diameter ?) arguments: Ball(float x, float y, float argDia)
In setup() you call the empty constructor:
ball1 = new Ball();
This means the five float arrays still have a length of 0, hence the out of bounds exception.
Even if you call the position + diameter version of the constructor, the xSpeed, ySpeed arrays will still have length 0.
You could fix this by initialising the two two arrays as well as using this version of the constructor:
Ball ball1;
void setup() {
size(500, 500);
//ball1 = new Ball();
ball1 = new Ball(250, 250, 50);
}
void draw() {
background(255);
ball1.bounce();
}
class Ball {
float [] xPos = {};
float [] yPos = {};
float [] dia = {};
float [] xSpeed = {};
float [] ySpeed = {};
Ball() {
}
Ball(float x, float y, float argDia) {
xPos = append(xPos, x);
yPos = append(yPos, y);
dia = append(dia, argDia);
xSpeed = append(xSpeed, random(-1, 1));
ySpeed = append(ySpeed, random(-1, 1));
}
void bounce() {
for (int i=0; i<1; i++) {
ellipse(xPos[i], yPos[i], 50, 50);
xPos[i] += xSpeed[i];
yPos[i] += ySpeed[i];
if (xPos[i]<0 || xPos[i]>=width) {
xSpeed[i] = -xSpeed[i];
}
if (yPos[i]<0 || yPos[i]>=height) {
ySpeed[i] = -ySpeed[i];
}
}
}
}
This will work, however there is still a bit of confusion: why use the arrays at all if you're only looping once for the first element ? It makes the arrays and for loop mostly redundant.
You might choose to keep if you plan to change the diameter over time (which in your code is hardcoded to 50), maybe positions and velocities and render a changing history of a ball.
If you don't, you could simply use float properties instead of arrays:
Ball ball1;
void setup() {
size(500, 500);
ball1 = new Ball();
}
void draw() {
background(255);
ball1.bounce();
}
class Ball {
float xPos;
float yPos;
float diameter = 50;
float xSpeed;
float ySpeed;
Ball() {
xPos = width / 2;
yPos = height / 2;
xSpeed = random(-1, 1);
ySpeed = random(-1, 1);
}
void bounce() {
ellipse(xPos, yPos, diameter, diameter);
xPos += xSpeed;
yPos += ySpeed;
if (xPos < 0 || xPos >= width) {
xSpeed = -xSpeed;
}
if (yPos < 0 || yPos >= height) {
ySpeed = -ySpeed;
}
}
}
This looks more similar to the Bounce Processing Example.
You can at a later stage make an array of Ball objects.
Additionally it's worth formatting code as it saves you time reading/scrolling through it and visually it's easier to scan the structure of the program (how each part fits in) and therefore makes it easier to debug/run mentally. It takes no effort as you can simply press Ctrl+T on Windows/Linux or CMD+T on OSX. On the long run this will pay off, especially as programs get longer and more complex as you spend more time reading code than writing code. It's a good habit to pickup early while learning to code. Have fun!

Processing: How can I make multiple elements in a for() loop move to one location then return?

I have a grid of ellipses generated by two for() loops. What I'd like to do is have all of these ellipses ease into mouseX and mouseY when mousePressed == true, otherwise return to their position in the grid. How can I go about this? I've started with this template, which doesn't work as I can't figure out how affect the position of the ellipses, but the easing is set up.
float x;
float y;
float easeIn = 0.01;
float easeOut = 0.08;
float targetX;
float targetY;
void setup() {
size(700, 700);
pixelDensity(2);
background(255);
noStroke();
}
void draw() {
fill(255, 255, 255, 80);
rect(0, 0, width, height);
for (int i = 50; i < width-50; i += 30) {
for (int j = 50; j < height-50; j += 30) {
fill(0, 0, 0);
ellipse(i, j, 5, 5);
if (mousePressed == true) {
// go to mouseX
targetX = mouseX;
// ease in
float dx = targetX - x;
if (abs(dx) > 1) {
x += dx * easeIn;
}
//go to mouseY
targetY = mouseY;
// ease in
float dy = targetY - y;
if (abs(dy) > 1) {
y += dy * easeIn;
}
} else {
// return to grid
targetX = i;
// ease out
float dx = targetX - x;
if (abs(dx) > 1) {
x += dx * easeOut;
}
// return to grid
targetY = j;
// ease out
float dy = targetY - y;
if (abs(dy) > 1) {
y += dy * easeOut;
}
}
}
}
}
Any help would be greatly appreciated. I'm not sure in which order to do things/which elements should be contained in the loop.
Thanks!
You're going to have to keep track of a few things for each dot: its "home" position, its current position,its speed, etc.
The easiest way to do this would be to create a class that encapsulates all of that information for a single dot. Then you'd just need an ArrayList of instances of the class, and iterate over them to update or draw them.
Here's an example:
ArrayList<Dot> dots = new ArrayList<Dot>();
void setup() {
size(700, 700);
background(255);
noStroke();
//create your Dots
for (int i = 50; i < width-50; i += 30) {
for (int j = 50; j < height-50; j += 30) {
dots.add(new Dot(i, j));
}
}
}
void draw() {
background(255);
//iterate over your Dots and move and draw each
for (Dot dot : dots) {
dot.stepAndRender();
}
}
class Dot {
//the point to return to when the mouse is not pressed
float homeX;
float homeY;
//current position
float currentX;
float currentY;
public Dot(float homeX, float homeY) {
this.homeX = homeX;
this.homeY = homeY;
currentX = homeX;
currentY = homeY;
}
void stepAndRender() {
if (mousePressed) {
//use a weighted average to chase the mouse
//you could use whatever logic you want here
currentX = (mouseX+currentX*99)/100;
currentY = (mouseY+currentY*99)/100;
} else {
//use a weighted average to return home
//you could use whatever logic you want here
currentX = (homeX+currentX*99)/100;
currentY = (homeY+currentY*99)/100;
}
//draw the ellipse
fill(0, 0, 0);
ellipse(currentX, currentY, 5, 5);
}
}
Note that I'm just using a weighted average to determine the position of each ellipse, but you could change that to whatever you want. You could give each ellipse a different speed, or use your easing logic, whatever. But the idea is the same: encapsulate everything you need into a class, and then put the logic for one dot into that class.
I'd recommend getting this working for a single dot first, and then moving up to getting it working with multiple dots. Then if you have another question you can post the code for just a single dot instead of a bunch. Good luck.

How to change speed of ellipses in processing

I am trying to create an array of circles which all move at different speeds and have different colours using classes which i have done however about 5 seconds into running it for some reason the ellipses all go to the edges of the window and the code doesn't work properly. Below I have provided my code including the class and setup:
circle circles = new circle(1, 8);
void setup() {
size(800, 600);
}
void draw() {
background(255);
circles.display();
circles.bounce();
}
class circle {
int[] posX = new int [10];
int[] posY = new int [10];
float[] speedX = new float[10];
float[] speedY = new float[10];
int[] red = new int [10];
int[] green = new int [10];
int[] blue = new int [10];
circle(float start, float end) {
for (int i = 0; i < 10; i++) {
speedX[i] = random(start, end);
speedY[i] = random(start, end);
posX[i] = int(random(500, 800));
posY[i] = int(random(500, 600));
red[i] = int(random(0, 255));
green[i] = int(random(0, 255));
blue[i] = int(random(0, 255));
}
}
void display() {
for (int i = 0; i < 10; i++) {
fill(red[i], green[i], blue[i]);
ellipse(posX[i], posY[i], 50, 50);
}
}
void bounce() {
for (int i = 0; i < 10; i++) {
posX[i] += speedX[i];
posY[i] += speedY[i];
if (posX[i] - 50 < 0 || posX[i] + 50 > width) {
speedX[i] = -speedX[i];
}
if (posY[i] - 50 < 0 || posY[i] + 50 > height) {
speedY[i] = -speedY[i];
}
}
}
}
The main problem is that you were not setting the balls to be inside the screen again! This is a very common problem, and Dan Shiffman used it to show the new Processing 3 Debugger.
But since i've found many stuff about your code i will also comment other stuff that might help you with programming.
But first let me show you the working code:
int n_of_circles = 10;
Circle[] circles = new Circle[n_of_circles];
void setup() {
size(800, 600);
for (int i = 0; i < n_of_circles; i++) {
circles[i] = new Circle(1, 8);
}
}
void draw() {
background(255);
for (int i = 0; i < n_of_circles; i++) {
circles[i].display();
circles[i].move();
}
}
class Circle {
float posX = random(0, width); //no need to set these value in constructor
float posY = random(0, height); //we can set it here
float speedX = 666; //we will change these on constructor
float speedY = 666; //666 is just a personal convention that i use to indicate that :p
//Similarly, no need to set the color variable in the constructor
//also, lets use a color variable instead of 3 separate variables
color circ_color = color(
(int) random(0, 255),
(int) random(0, 255),
(int) random(0, 255)
);
//defining circle diameter instead of using a literal ("50", in our case)
int diameter = 50;
int radius = diameter/2;
Circle(float min_speed, float max_speed) {
// The purpose of "min_speed" and "max_speed" are clearer than "start" and "end"
speedX = random(min_speed, max_speed);
speedY = random(min_speed, max_speed);
}
void display() {
//this push an pop commands ensure that this fill command won't
//interfere with any other stuff, if you ever reuse this code
pushStyle();
fill( circ_color );
ellipse(posX, posY, diameter, diameter);
popStyle();
}
//notice how i separated the move declartions form the bounce. It's good programming practice
//to keep stuff simpler. Functions should always have one single responsibility.
//In this case it won't helpĀ“much, but we're yoru move function more complex, it would!
void move(){
posX += speedX;
posY += speedY;
bounce();
}
void bounce() {
//note that you were using the diameter, but you should really use the radius!
//if it's touching left or side edges
if (posX - radius < 0 || posX + radius > width) {
speedX *= -1; //inverts the sign
//Here's the actual missing bits!
if (posX - radius < 0 ){ posX = radius; }
if (posX + radius > width ){ posX = width-radius; }
}
//if it's touching top or bottom edges
if (posY - radius < 0 || posY + radius > height) {
speedY *= -1; //inverts the sign
//Here's the actual missing bits!
if (posY - radius < 0 ){ posY = radius; }
if (posY + radius > height ){ posY = height-radius; }
}
}
} //end of class Circle
Just i few suggestions:
The convention is that Class names are upper case. This you you have Circle circles = new Circle(1,5); This is clearer.
Avoid using literals! (writing hard-coded numbers) For example, you we're using "ellipse(posX[i], posY[i], 50, 50);". By using a variable for diameter your code becomes more modular. Should you change the circles diameter, you just alter one line of code!
Use arrays of objects instead of classes that contains other stuff. That's good programming practice as it makes your code easier to understand. Now if you need to group lots of circles you use an array, or you can create another class "Group_of_circles" for ex.
I know i've presented some new concepts/syntaxes and changed a lot to your code, but i tried to comment everything to make it clear and instructive
Since i've already changed much thing i didn't use any Vectors, but when dealing with positions , you really should use PVectors! This free book have a great chapter on them!
Try to find good tutorials about software development. They will teach about godo programming practices like keeping your code as modular as possible and etc. But don't worry, it will come to you natrually over time!
Try learncpp.com, tutorialss 1-10a and 1-4b. Those 2 are part of a c++ tutorial, but are a good starting point and refer to programming in general.

How can I use a FOR loop to create circles in a circle (in Processing)

I need to create a loop which will space circles equally around a circle in Processing.
I know I can somehow implement a FOR loop.
I need to be able to increase or decrease the number of circles around this circle (with button presses) but keep them equally spaced.
I know the formula's I need to include in the FOR loop to get the X and Y axis. The formulas:
being
X = R*cos(angle-90)+Y0
Y = R*sin(angle-90)+X0
I understand the three parameters of the FOR loop; when does it start, when does it finish, what changes when it runs.
What I can't see is how to implement the formulas into the FOR loop.
Many thanks
Here is the code I do have
void setup () {
size (600, 600);
background (255, 255, 255);
smooth ();
ellipse (width/2, height/2, 200, 200); // the guide circle. Not needed in final code.
}
void draw() {
for (int i = 0; i < 20; i ++) {
for (int j = 0; j < 20; j ++) {
ellipse (i *20, j * 20, 20, 20);
}
}
}
This code should do the trick:
float incrementalAngle = 0.0;
void setup(){
size(600, 600);
smooth();
background(0);
ellipse(width/2, height/2, 200, 200);
drawCircles(20, 200);
}
void draw(){
}
void drawCircles(int circlesNumber, int bigCircleNumber){
float angle = incrementalAngle;
for(int i = 0; i < circlesNumber; i++){
ellipse(bigCircleNumber * cos(incrementalAngle) + height/2,
bigCircleNumber * sin(incrementalAngle) + width/2,
circlesNumber, circlesNumber);
incrementalAngle += TWO_PI / circlesNumber;
}
}
So the second loop wasn't needed, and the formula you were trying to introduce would go in the X and Y position of your ellipse, there by playing whit the angle and the cos and sin you can get the result you were looking for.
What's left now is for you to get the number of circles you want by the clicking inside a mousePressed() method and drawing that amount.
Hope this comes useful and call me if you need more help
Regards
Jose.
Thank you to everyone who helped.
I managed to do it (slightly differently to you #Jose Gonzalez
int nbr_circles = 2;
void setup() {
size(600, 600);
smooth();
background(255);
}
void draw() {
background(255);
float cx = width/2.0;
float cy = height/2.0;
fill(0);
//float x, y; //
for (int i = 0; i < nbr_circles; i++)
{
float angle = i * TWO_PI / nbr_circles;
float x = cx + 110.0 * cos(angle);
float y = cy + 110.0 * sin(angle);
ellipse(x, y, 20, 20);
}
}
void mousePressed() {
if (mouseButton == LEFT) {
if (nbr_circles < 20)
nbr_circles = nbr_circles + 1;
} else if (mouseButton == RIGHT) {
if (nbr_circles > 2)
nbr_circles = nbr_circles - 1;
}
}

Resources