Description
In this project, I referred to some works of Professor Aaron and added some ideas. The project is about various flowers of different colors made up by texts.
For the interaction part, if you press “W”, a new flower will be added at mouse coordinate, and if you press “S”, a random flower will be deleted. Pressing “R” will restart the program. There are two modes designed in the program. By default, when you put the cursor around the texts, they move away. Clicking the mouse will change the mode. In this mode, the texts will randomly move around.
Code
Mover is the foundation class of my program, which I referred to Professor Aaron’s text example and modified some parts. Every alphabet of a string is a Mover.The Mover class includes the physical attributes like speed, acceleration and gravity.
class Mover{ PVector velocity; PVector gravity; PVector position; PVector acceleration; PVector wind; float drag; float mass; float hDampening; PVector speed; Mover(PVector pos, float _mass, PVector _speed){ mass=_mass; position = pos; speed = _speed; velocity = new PVector(0,0); acceleration = new PVector(0,0); gravity = new PVector(0, 0.1*mass); drag = map(mass,15, 80, .999, .96); wind = new PVector(0,0); set_hDampening(); } void move() { position.add(speed); speed.x *= 0.98; speed.y *= 0.98; acc = new PVector(0, 0); bounds(); } void update(){ wind.x=globalWind1; wind.y=globalWind2; if (globalWind1==0) velocity.x*=hDampening; applyForce(wind); applyForce(gravity); velocity.add(acceleration); velocity.mult(drag); position.add(velocity); bounds(); acceleration.mult(0); } void display(){ ellipse(position.x,position.y,mass,mass); } void bounds(){ if (position.x>width - 30) position.x=width - 30; if (position.x<0) position.x=0; if (position.y>height) position.y=height; if (position.y<45) position.y=45; } void set_hDampening(){ hDampening=map(mass,0,100,.98,.96); } void applyForce(PVector force){ PVector f = PVector.div(force, mass); acceleration.add(f); } }
The Letter class prints out the Movers.
class Letter extends Mover{ char let; Letter(PVector pos, float _mass, char s, PVector _speed){ super(pos,_mass, _speed); let=s; drag = random(.98,.999); } void display(){ text(let,position.x,position.y); } }
The most significant part of my project is the Flower class, which transforms letters into flowers. It basically concatenates the letters to form a circle and adds animations to the letters. The run function is for shifting between the two modes, and the generate function is for changing colors.
class Flower { float x, y; String s; PVector speed = new PVector(0,0); ArrayList<Letter> letters = new ArrayList<Letter>(); Flower(String _s, float _x, float _y) { s = _s; x = _x; y = _y; } void show() { generate(); run(); } void mysetup() { for (int i=0; i<s.length(); i++) { char c = s.charAt(i); float radius = random(s.length()*15, s.length()*25); float angle = PI + i*TWO_PI/s.length(); float posx = cos(angle)*radius + x; float posy = sin(angle)*radius + y; PVector pos = new PVector(posx, posy); letters.add(new Letter(pos, random(0.1, 0.3), c, speed)); } } void mouse_pos(Mover object) { float x = object.position.x; float y = object.position.y; if (dist(mouseX, mouseY, x, y)<30) { acc = new PVector(cos(random(TWO_PI)), cos(random(TWO_PI))); speed.add(acc); } } void run() { if (bool) { for (int i=0; i<s.length(); i++) { mouse_pos(letters.get(i)); letters.get(i).move(); letters.get(i).display(); } } if (!bool) { for (int i=0; i<s.length(); i++) { globalWind1 = random(-0.3, 0.3); globalWind2 = random(-0.35, 0.3); letters.get(i).update(); letters.get(i).display(); } } } void generate() { switch (s) { case "Rose": fill(#D8163A); break; case "Dandelion": fill(255); break; case "Sunflower": fill(#EFF70A); break; case "Daisy": fill(#E3A3E2); break; case "Carnation": fill(#F083E5); break; case "Iris": fill(#B44EB4); break; } mysetup(); } }
Below is my main function where I put parameters into the flower class, and design the interactions.
PFont f; String s; String [] words = {"Rose", "Dandelion", "Sunflower", "Daisy", "Carnation", "Iris"}; Flower flower; ArrayList<Flower> flowers = new ArrayList<Flower>(); int count = 0; float globalWind1=0; float globalWind2=0; PVector acc = new PVector(0,0); boolean bool = true; void setup() { size(600, 600); f = createFont("Monaco", 60); textFont(f); s = words[0]; flower = new Flower(s, width/2-(textWidth(s)/2), height/2); flowers.add(flower); count += 1; } void draw() { background(#EDE5FF); for (int i = 0; i < flowers.size(); i++) { flower = flowers.get(i); flower.show(); } if (!keyPressed) globalWind1=0; globalWind2=0; } void keyPressed() { if (key == 'r' || key == 'R') { while (count > 0) { delete_flower(); } } //if (keyCode==LEFT) { // globalWind1=-0.3; //} //if (keyCode==RIGHT) { // globalWind1=0.3; //} //if (keyCode==UP) { // globalWind2=-0.5; //} //if (keyCode==DOWN) { // globalWind2=0.5; //} if (key == 'w' || key == 'W') { add_flower(); } if (key == 's' || key == 'S') { delete_flower(); } } void mouseClicked() { bool = !bool; } void add_flower() { s = words[count % 6]; flower = new Flower(s, mouseX, mouseY); flowers.add(flower); count += 1; } void delete_flower() { try { flowers.remove(int(random(0, 6))); count -= 1; } catch (Exception e) { } }
Challenges
This project is pretty challenging as I have three classes connected with each other. It’s hard to organize these classes. Adding new features and animations can be painful because I have to also modify the classes, and it requires a clear mind and efforts. You can easily get an error message for not sorting things out.
For example, when I was trying to make alphabets randomly move by adding a variable globalWind to the Mover class, I encountered a problem that every alphabet moves towards the exactly same directions. My final solution was to add a speed parameter to flower class.
There is still a problem I haven’t solved. When I was trying to change the font, the intervals between alphabets are not evenly distributed. So some alphabets appear too close, but some are far away from each other. I don’t understand why — I think it should be displayed normally because my code was to calculate textWidth before locating the positions.
Overall, I think making this project improves my understanding of classes, especially how the parameters can help. It also helps me get grasp of the physics in Processing.
Hope you enjoy 🙂