# Change shape when changing directions

I am working through “Coding Art” and there is an extra task I am not able to solve until now. I am really a beginner and this task seems quite hard without coding experience at all.

I have Particles moving in a circle and changing directions when their distance from center greater than 150:

``````//reserve memory for 4000 particles
Particle[] particles = new Particle [40];

void setup() {
size(600, 600);
smooth();
noStroke();

//loop through all 4000 particles an initialize
for (int i = 0; i < 40; i++) {
particles[i] = new Particle();
}
}

void draw() {
//dark background
background(35, 27, 105);

//always draw from center of canvas
translate(width/2, height/2);

//loop through all particles
for (Particle p : particles) {
//change position and draw particle
p.move();
p.show();
}
}

//create new class for our particle
class Particle {
float x, y, size, directionX, directionY, shape;

//initialize (called 'constructor')
public Particle() {
this.size = random(1, 17);
this.directionX = random(-1, 1);
this.directionY = random(-1, 1);
}

//function to move the particle position in direction
public void move() {
//calculate distance from center
if (dist(this.x, this.y, 0, 0) > 150) {
//create position and new random target position
PVector position = new PVector(this.x, this.y);
PVector target = new PVector(random(-250, 250), random(-250, 250));
//calculate direction vecotr betwenn current and target position
PVector direction = PVector.sub(target, position);
//divide direction by 300 to make the steps small
direction.div(300);
//set new direction for the particle
directionX = direction.x;
directionY = direction.y;
}
this.x += directionX;
this.y += directionY;
}

//draw the particle on the Processing canvas
public void show() {
//set individual particle color
fill(195, 215, 112);
//draw particle shape
ellipse(this.x, this.y, this.size, this.size);
//draw circle
noFill();
stroke(250);
ellipse(0, 0, 310, 310);
noStroke();
}
}
``````

And the task is to change the ellipses to a rectangle when they change directions. It’s mentioned that it must be done in the show() function. But I have no clue how to do it.

It’s clear to me that I have to do something like:

• if direction changes
• then change the shape to rectangle.

But how do I know, when direction has changed?

I think it must something be like

• store the direction information of each particle in an array
• when a direction changes, change the shape in the show function.

Is this path going in the right direction? Grateful for any suggestions how to solve this.

1 Like

store a boolean metCircle = false; in the class

When particle hits the circle set it to true individually

Evaluate the variable metCircle to decide if you draw a circle or a rectangle

It’s pretty easy actually

You’ve got this check inside method Particle::move():

So it’s inside that `if ()` block that you should make the decision to switch to either circle() or square().

As @Chrisir already advised, add an extra `boolean` field to your class Particle.

Inside your Particle::show() method invoke square() when that `boolean` is `true`, otherwise invoke circle().

Here’s a refactor I did to your code:

``````/**
* Circle/Square Within Big Circle (v1.0.1)
* by Marina_Kdot (2021-Dec-27)
* mod GoToLoop
*
* Discourse.Processing.org/t/change-shape-when-changing-directions/34315/3
*/

final Particle[] particles = new Particle[40];
final PApplet p = this;

void setup() {
size(600, 600);

rectMode(CENTER);
strokeWeight(1.5);

for (int i = 0; i < particles.length; particles[i++] = new Particle());
}

void draw() {
background(35, 27, 105);
translate(width >> 1, height >> 1);

noStroke();
fill(195, 215, 112);
for (final Particle p : particles)  p.move().show();

stroke(250);
noFill();
circle(0, 0, height >> 1);
}

class Particle {
final PVector pos, dir;
final int diam;
boolean isSquare;

Particle() {
diam = (int) random(4, 20);
pos = new PVector(diam, diam);
dir = PVector.random2D(p);
}

Particle move() {
final int h = height;

if (sq(pos.x) + sq(pos.y) > sq(h - diam*2 >> 2)) {
isSquare ^= true;
pos.add(PVector.random2D(dir, p).mult(h / 3).sub(pos).div(h >> 1));
}

return this;
}

Particle show() {
if (isSquare)  square(pos.x, pos.y, diam);
else           circle(pos.x, pos.y, diam);

return this;
}
}
``````
2 Likes

Thanks a lot for your fast help.

@Chrisir your input helped a lot and I added the boolean and checked it in the move().

``````public void move() {
//calculate distance from center
if (dist(this.x, this.y, 0, 0) >= 150) {
//check value of metCircle boolean and change it
if (metCircle == false) {
metCircle = true;
} else {
metCircle = false;
};
``````

In the show() I added this if statement

`````` //draw particle shape
if (metCircle == true) {
ellipse(this.x, this.y, this.size, this.size);
} else {
rect(this.x, this.y, this.size, this.size);
}
``````

For sure this is not the most beautiful code. But it works for the first time

@GoToLoop Your solution looks so clean and I like it a lot. But unfortunately I haven’t covered all the things you’re using in it right now. I see huge possibilities to grow

Thanks to both of you.

2 Likes

short form

`if( ! metCircle) {`

! means “not”

short form

` if (metCircle) {`

1 Like

Meanwhile I replaced the whole if statement where I checked metCircle with this expression:

``````metCircle = !metCircle;
``````

As I understand, whatever metCircle is, this expression will change it to the opposite. Makes it nice and short. But writing the if/else statement was very helpful to understand what’s happening.

2 Likes

it is not necessary to use “`this.`” in the class.

(this is only necessary when you pass a variable in the constructor which has the same name as the class’s variables (to distinguish them), but not in your code)

2 Likes

Hi everyone. I actually didn’t get the idea of metCircle, I’ve solved this just by adding conditional in the ‘show’ function:

public void show() {

[…]

``````if (dist(this.x, this.y, 0, 0) < 245) {
ellipse(this.x, this.y, this.size, this.size);

} else {
rect(this.x, this.y, this.size, this.size);
}
``````

it may be not the best solution, but it works