I want to achieve a slow fade in size on every collapse into itself. In other words, when the circle is at its biggest, the ellipses will be at the largest in size and conversely the opposite for the retraction. So far I am trying to achieve this affect by remapping the cSize from the distance of the center point, but somewhere along the way something is going wrong. At the moment I am getting a slow transition from small to large in ellipse size, but the inner ellipses are noticeably larger. I want an equal distribution of size amongst all ellipses in relation to center point distance.
I've simplified the code down to 4 ellipses rather than an array of rows of ellipses in order to hopefully simplify this example. This is done in the for (int x = -50; x <= 50; x+=100).
I've seen one or two examples that slightly does what I want, but is more or less static. This example is kind of similar because the ellipse size gets smaller or larger in relation to the mouse position
Distance2D
Here is an additional diagram of the grid of ellipses I am trying to create, In addition, I am trying to scale that "square grid" of ellipses by a center point.
Multiple ellipses + Scale by center
Any pointers?
float cSize;
float shrinkOrGrow;
void setup() {
size(640, 640);
noStroke();
smooth();
fill(255);
}
void draw() {
background(#202020);
translate(width/2, height/2);
if (cSize > 10) {
shrinkOrGrow = 0;
} else if (cSize < 1 ) {
shrinkOrGrow = 1;
}
if (shrinkOrGrow == 1) {
cSize += .1;
} else if (shrinkOrGrow == 0) {
cSize -= .1;
}
for (int x = -50; x <= 50; x+=100) {
for (int y = -50; y <= 50; y+=100) {
float d = dist(x, y, 0, 0);
float fromCenter = map(cSize, 0, d, 1, 10);
pushMatrix();
translate(x, y);
rotate(radians(d + frameCount));
ellipse(x, y, fromCenter, fromCenter);
popMatrix();
}
}
}
The values you're passing into the map() function don't make a lot of sense to me:
float fromCenter = map(cSize, 0, d, 1, 100);
The cSize variable bounces from 1 to 10 independent of anything else. The d variable is the distance of each ellipse to the center of the circle, but that's going to be static for each one since you're using the rotate() function to "move" the circle, which never actually moves. That's based only on the frameCount variable, which you never use to calculate the size of your ellipses.
In other words, the position of the ellipses and their size are completely unrelated in your code.
You need to refactor your code so that the size is based on the distance. I see two main options for doing this:
Option 1: Right now you're moving the circles on screen using the translate() and rotate() functions. You could think of this as the camera moving, not the ellipses moving. So if you want to base the size of the ellipse on its distance from some point, you have to get the distance of the transformed point, not the original point.
Luckily, Processing gives you the screenX() and screenY() functions for figuring out where a point will be after you transform it.
Here's an example of how you might use it:
for (int x = -50; x <= 50; x+=100) {
for (int y = -50; y <= 50; y+=100) {
pushMatrix();
//transform the point
//in other words, move the camera
translate(x, y);
rotate(radians(frameCount));
//get the position of the transformed point on the screen
float screenX = screenX(x, y);
float screenY = screenY(x, y);
//get the distance of that position from the center
float distanceFromCenter = dist(screenX, screenY, width/2, height/2);
//use that distance to create a diameter
float diameter = 141 - distanceFromCenter;
//draw the ellipse using that diameter
ellipse(x, y, diameter, diameter);
popMatrix();
}
}
Option 2: Stop using translate() and rotate(), and use the positions of the ellipses directly.
You might create a class that encapsulates everything you need to move and draw an ellipse. Then just create instances of that class and iterate over them. You'd need some basic trig to figure out the positions, but you could then use them directly.
Here's a little example of doing it that way:
ArrayList<RotatingEllipse> ellipses = new ArrayList<RotatingEllipse>();
void setup() {
size(500, 500);
ellipses.add(new RotatingEllipse(width*.25, height*.25));
ellipses.add(new RotatingEllipse(width*.75, height*.25));
ellipses.add(new RotatingEllipse(width*.75, height*.75));
ellipses.add(new RotatingEllipse(width*.25, height*.75));
}
void draw() {
background(0);
for (RotatingEllipse e : ellipses) {
e.stepAndDraw();
}
}
void mouseClicked() {
ellipses.add(new RotatingEllipse(mouseX, mouseY));
}
void mouseDragged() {
ellipses.add(new RotatingEllipse(mouseX, mouseY));
}
class RotatingEllipse {
float rotateAroundX;
float rotateAroundY;
float distanceFromRotatingPoint;
float angle;
public RotatingEllipse(float startX, float startY) {
rotateAroundX = (width/2 + startX)/2;
rotateAroundY = (height/2 + startY)/2;
distanceFromRotatingPoint = dist(startX, startY, rotateAroundX, rotateAroundY);
angle = atan2(startY-height/2, startX-width/2);
}
public void stepAndDraw() {
angle += PI/64;
float x = rotateAroundX + cos(angle)*distanceFromRotatingPoint;
float y = rotateAroundY + sin(angle)*distanceFromRotatingPoint;
float distance = dist(x, y, width/2, height/2);
float diameter = 50*(500-distance)/500;
ellipse(x, y, diameter, diameter);
}
}
Try clicking or dragging in this example. User interaction makes more sense to me using this approach, but which option you choose really depends on what fits inside your head the best.
Related
This is a school project so i cannot use a lot of functions like translate or rotate. I have to use basic trigonometry to do this. So I have made a square and I need it to move in a circular motion 360 degrees with one of it's point constant and not moving.
float rotX,rotY;
size(500,500);
fill(#B71143);
int rectX=width/4;
int rectY=height/10;
int rectSize=30;
angle=angle+0.1;
//rotX=rectX*cos(angle)-rectY*sin(angle);
//rotY=rectX*cos(angle)+rectY*sin(angle);
square(rotX,rotY,rectSize);
You are so close, at least in terms of the trigonometry part.
In terms of Processing you're only missing setup() and draw() which will draw a single frame (once you uncomment the assignments of rotX, rotY and initialise angle to 0)
Here's your code with above notes applied:
float rotX, rotY;
float angle = 0;
void setup() {
size(500, 500);
fill(#B71143);
}
void draw() {
int rectX=width/4;
int rectY=height/10;
int rectSize=30;
angle=angle+0.1;
rotX = rectX*cos(angle)-rectY*sin(angle);
rotY = rectX*cos(angle)+rectY*sin(angle);
square(rotX, rotY, rectSize);
}
Additionally, if you want to draw from the centre, you can add half the width/height to the square coordinates before rendering (equivalent to translating to centre), and if you want to draw a circle instead of an oval, use the same size for the two radii (named rectX, rectY):
float rotX, rotY;
float angle = 0;
void setup() {
size(500, 500);
fill(#B71143);
rectMode(CENTER);
}
void draw() {
int rectX=width/4;
int rectY=height/4;
int rectSize=30;
angle=angle+0.1;
rotX = rectX*cos(angle)-rectY*sin(angle);
rotY = rectX*cos(angle)+rectY*sin(angle);
// offset to center
rotX += width / 2;
rotY += height / 2;
square(rotX, rotY, rectSize);
}
Personally I'd simplify the code a bit (though your assignment requirements might differ based on your curriculum).
// initialise angle value
float angle = 0;
void setup() {
size(500, 500);
fill(#B71143);
}
void draw() {
// circular motion radius
int radius = width / 4;
// define square size
int rectSize=30;
// increment the angle (rotating around center)
angle=angle+0.1;
// convert polar (angle, radius) to cartesian(x,y) coords
float x = cos(angle) * radius;
float y = sin(angle) * radius;
// offset to center
x += width / 2;
y += height / 2;
// render the square at the rotated position
square(x, y, rectSize);
}
(In case you're after another polar to cartesian coordinates conversion formula explanation you can check out my older answer here which includes an interactive demo)
//declaringglobalvaribales
float dia1=50;
//diameteroftheface
float x=400;
float y=400;
float speedX=4;
float speedY=0;
//setup
void setup() {
size(810, 810);
} //draw
void draw() {
background(225);
fill(225, 0, 0);
stroke(0);
ellipse(x, y, dia1, dia1);
fill(0, 225, 0);
//a nose
triangle(x, y, x+10, y+10, x-10, y+10);
//movingtheballXway
x=x+speedX;
//movingtheballYway
y=y+speedY;
//if it hits the left or right corners it will turn around
if (x>width-dia1/2 || x<2+dia1/2) {
speedX=speedX*-1;
}
// it its hits the top or bottom it will turn around
if (y>height-dia1/2 || y<2+dia1/2) {
speedY=speedY*-1;
}
// this code to move it according to the keys W S D A
void keyPressed() {
if (keyCode=='W') {
speedX=0;
speedY=-4;
}
if (keyCode=='S') {
speedX=0;
speedY=4;
}
if (keyCode=='A') {
speedX=-4;
speedY=0;
}
if (keyCode=='D') {
speedX=4;
speedY=0;
}
}
I made this ball with a nose, which moves around the screen with the keys W S D A. If it hits the edges it will bounce back.
I'm trying to change the direction the ball is facing to make it face the same way as it's moving. I wanted to use rotate for this, but once I use rotate it throws all the coordinates off. Rotating it back doesn't help either.
I have commented out the stuff I have tried to do. For example, I tried to translate it to 250,250 and then rotate it afterwards, but then the X and Y coordinates are switched. Also, the ball won't go all the way to the corners and it moves out (since it's translated down).
What kind of rotation/translation logic do I need to change?
It is likely that using the rotate function on your triangle is wreaking havoc as you are performing the rotate on several variables in your draw loop because you're not telling processing exactly which object you want to transform. One way to do this is to look up the pushMatrix and popMatrix functions (google "processing pushMatrix" to see helpful info for how to use the type and associated functions). It would be cumbersome to implement this into your code as the triangle is created in your draw loop every frame. An easy way to make transformations to a specific shape you have (in your instance, a triangle) is to store it as a PShape and then make transformations as you need to. Since PShape's can easily be transformed using PShape functions you don't need to worry about your transformations effecting other variables (so no need to use push/popmatrix. Here is a commented version of your code that implements your Triangle as a PShape.
//declaringglobalvaribales
float dia1=50;
//diameteroftheface
float x=400;
float y=400;
float speedX=4;
float speedY=0;
//Initialize PShape which we can later store a triangle in
PShape tri;
void setup() {
size(810, 810);
//Initialize triangle - this triangle faces right
tri = createShape(TRIANGLE, 0, 10, 0, -10, 10, 0);
}
void draw() {
background(225);
fill(225, 0, 0);
stroke(0);
ellipse(x, y, dia1, dia1);
fill(0, 225, 0);
//Draw the stored PShape at x and y coordinate
shape(tri,x,y);
//movingtheballXway
x=x+speedX;
//movingtheballYway
y=y+speedY;
//if it hits the left or right corners it will turn around
if (x>width-dia1/2 || x<2+dia1/2) {
speedX=speedX*-1;
//Flip PShape rotation
tri.rotate(PI);
} // it its hits the top or bottom it will turn around
if (y>height-dia1/2 || y<2+dia1/2) {
speedY=speedY*-1;
//Flip PShape rotation
tri.rotate(PI);
}
}
// this code to move it according to the keys W S D A
void keyPressed() {
if (keyCode=='W') {
speedX=0;
speedY=-4;
//reset triangle orientation (transformation matrix) to original then rotate to face UP
tri.resetMatrix();
tri.rotate(-PI/2);
}
if (keyCode=='S') {
//reset triangle orientation (transformation matrix) to original then rotate to face DOWN
speedX=0;
speedY=4;
tri.resetMatrix();
tri.rotate(PI/2);
}
if (keyCode=='A') {
//reset triangle orientation (transformation matrix) to original then rotate to face LEFT
tri.resetMatrix();
tri.rotate(PI);
speedX=-4;
speedY=0;
}
if (keyCode=='D') {
//reset triangle orientation (transformation matrix) to original - it is already pointing right
tri.resetMatrix();
speedX=4;
speedY=0;
}
}
I suspect your next step, or a more efficient way to write this piece of code might be to begin to implement PVectors (google processing PVectors to see helpful info for how to use the type and associated functions) for position and direction of your 'ball'. Here is some commented code that begins to show you how you might implement this in your current code. Although there are many improvements that can be made on this. For more information on how vectors work in processing follow this tutorial - http://natureofcode.com/book/chapter-1-vectors/
//declaringglobalvaribales
//diameteroftheface
float dia1=50;
//initialize position PVector and tell it where you want it to be - in this case 400,400
PVector position = new PVector(400, 400);
//how many steps you want your position to move per frame
float speed=4;
//initialize direction vector as 0,0 - the ellipse will not move until you give it a
//direction as it is initialized with no direction
PVector direction = new PVector(0, 0);
void setup() {
size(810, 810);
}
void draw() {
background(225);
fill(225, 0, 0);
stroke(0);
//draw ellipse at your position PVector using the PVectors x and y values
ellipse(position.x, position.y, dia1, dia1);
fill(0, 225, 0);
//drawing a line to indicate what direction the ellipse is heading in using the position coordinates and the position plus direction
line(position.x, position.y, position.x+direction.x*4, position.y+direction.y*4);
// add the direction to the position to make it move
position =position.add(direction);
//if the position PVector is close to sketch edges invert its direction by multiplying direction PVector by -1
if (position.x>width-dia1/2 || position.x<2+dia1/2) {
direction.mult(-1);
}
if (position.y>height-dia1/2 || position.y<2+dia1/2) {
direction.mult(-1);
}
}
// this code to move it according to the keys W S D A
void keyPressed() {
//set the direction coordinates based on keypresses
//also multiply the direction by speed variable so it moves at a speed set at top of script
if (keyCode=='W') {
direction.y = -1*speed;
direction.x = 0;
}
if (keyCode=='S') {
direction.y = 1*speed;
direction.x = 0;
}
if (keyCode=='A') {
direction.x = -1*speed;
direction.y = 0;
}
if (keyCode=='D') {
direction.x = 1*speed;
direction.y = 0;
}
}
If you have a center point, an angle you want to face, and a distance from that center, you can use cos() and sin() to calculate the end point. Here's a simple example:
float angle = 0;
float distance = 25;
void draw(){
angle += .01;
float startX = width/2;
float startY = height/2;
float endX = startX + cos(angle)*distance;
float endY = startY + sin(angle)*distance;
background(255);
line(startX, startY, endX, endY);
}
In the future, please try to narrow your question down to an MCVE like this before posting.
I am new to Processing.js and need a little bit support with this issue. I have made a HTML-Canvas animation where I have lines with a curtain like behavior which can be seen here:
Click
this is made with a canvas plugin called Paper.js
I now want to get similar effect on processing but don't really know how to figure it out. My attempt was:
float x;
float y;
void setup() {
size(1024, 768);
strokeWeight(2);
background(0, 0, 0);
}
void mouseMoved() {
x = mouseX;
y = mouseY;
}
void draw() {
background(0);
line(50, 50, x += x - x/5, y += y - y/5);
stroke(255, 255, 255);
line(50, 700, x += x - x/15, y += y - y/15);
stroke(255, 255, 255);
line(75, 50, x += x - x/25, y += y - y/25);
stroke(255, 255, 255);
line(75, 700, x += x - x/35, y += y - y/35);
// and so on, would create it within a loop
}
So what I am trying to do is basically get the same effect which I have done in HTML and adapt it in Processing.js.
Thanks in advance.
I'd strongly recommend ignoring the paper.js and reimplementing this properly. We're seeing a sequence of lines that connect to a historical line of coordinates, based on mouse position, so let's just implement that:
class Point {
float x, y;
Point(float _x, float _y) { x=_x; y=_y; }}
// our list of historical points
ArrayList<Point> points;
// the horizontal spacing of our lines has fixed interval
float interval;
// how many lines do we want to draw?
int steps = 50;
void setup() {
size(500, 500);
// initialise the "history" as just the midpoint
points = new ArrayList<Point>();
for (int i=0; i<steps; i++) {
points.add(new Point(width/2, height/2));
}
// compute the horizontal interval, because it's
// width-dependent. Never hard code dependent values.
interval = width/(float)steps;
// the lower we set this, the slower it animates.
frameRate(60);
}
void draw() {
// white background, black lines
background(255);
stroke(0);
// for each historic point, draw two
// lines. One from height 0 to the point,
// another from height [max] to the point.
Point p;
for (int i=0; i<steps; i++) {
p = points.get(i);
line(interval/2 + i*interval, 0, p.x, p.y);
line(interval/2 + i*interval, height, p.x, p.y);
}
// when we move the mouse, that counts as a new historic point
points.remove(0);
points.add(new Point(mouseX, mouseY));
}
Sketch running in the browser: http://jsfiddle.net/M2LRy/1/
(You could speed this up by using a round-robin array instead of an ArrayList, but ArrayLists are pretty convenient here)
The code below draws a spiral using objects from a string array. Everything is fine, except that I would like the text objects to be drawn at a roughly 45 degree angle at each instance (based on the current x, y coordinates in the code below) rather than being drawn horizontally (when the text is horizontally drawn, it naturally overlaps with other text at concentrated points along the top & bottom of the curve). I researched some methods, but I'm still very new to all of this, and potential solutions have all evaded me.
String example = "";
String[] wordSet = split(example, " ");
float x, y;
float angle = 0;
float radiusSpiralLine = 10;
size (800, 800);
translate(width/2, height/2);
background(#ffffff);
smooth();
fill(0);
for (int i = 0; i < wordSet.length; i++) {
angle += .05;
radiusSpiralLine += .5;
x = cos(angle) * radiusSpiralLine;
y = sin(angle) * radiusSpiralLine;
textSize(9);
text(wordSet[i], x, y);
}
Here is tutorial to very similar problem. In basic you need to store projection matrix by pushMatrix() then translate and rotate according to position of letter on curve and then restore matrix by popMatrix(). I don't know how exactly do you want to rotate you text but just fold round your text() function like this maybe it will help you:
pushMatrix();
translate(x, y);
rotate(angle);
text(wordSet[i], 0, 0);
popMatrix();
First, you should start getting in the habit of wrapping code in the setup() and draw() functions. Since you're drawing a static image you don't need the draw() function, but I think it's good practice to have those two.
Now, what you are doing now is simply translating the words by a very small amount. Do the math:
x = cos(angle) * radiusSpiralLine; //cos(.05)*.5 = .499
y = sin(angle) * radiusSpiralLine; //sin(.05)*.5 = .024
That means they move less than a pixel, and they're not rotating at all.
What you need is your good ol' friend, the rotate() function.
Let's re-write code:
String example = "These are a bunch of words going around!";
String[] wordSet = split(example, " ");
float x, y;
float angle = 0;
void setup() {
size (800, 800);
background(#ffffff);
smooth();
fill(0);
pushMatrix();
translate(width/2, height/2); //Translate when you need to translate, not before
for (int i = 0; i < wordSet.length; i++) {
angle = PI/5; //Our good friends, radians
textSize(20); //What is this, text for ants? Change to 20
rotate(angle);
text(wordSet[i], 20, 0);
}
popMatrix();
}
void draw() {
}
First notice, the setup() and draw(). I like them there. It looks nicer, I think.
A couple of important things to note.
The effects of rotate() and translate() are on the canvas are cumulative.
We could have had the same effect in different ways:
for (int i = 0; i < wordSet.length; i++) {
angle = PI/5;
textSize(20);
rotate(angle); //always rotating by PI/5 ON TOP of previous rotation
text(wordSet[i], 20, 0);
}
//Everything from now on will still be rotated, we don't want that!
Slightly better, but not there yet:
for (int i = 0; i < wordSet.length; i++) {
angle += PI/5; //constantly increasing the angle
textSize(20);
pushMatrix(); //push a new canvas on top of everything
rotate(angle); //rotate by angle (which increases every loop)
text(wordSet[i], 20, 0);
popMatrix(); //pop the rotated canvas out, go back to original canvas
} //Things won't be rotated, but they'll still be translated, since translate() is outside of pushMatrix and popMatrix
Hope this helps.
I wrote a program in Procesisng that renders opaque cubes with random colour and rotation on top of each other, but I'm looking to individually continuously spin each cube while the program is running. Here's my code at the moment,
int boxval = 1;
void setup(){
size (640, 320, P3D);
frameRate(60);
}
void draw(){
for (int i = 0; i < boxval; i++){
translate(random(0,640), random(0,320), 0);
rotateY(random(0,360));
rotateX(random(0,360));
rotateZ(random(0,360));
fill(random(0,255),random(0,255),random(0,255),50);
noStroke();
box(64,64,64);
}
}
Here's a screenshot if it helps at all,
This is a great time to use Object Oriented Programming! If I understand the question correctly, you would like each cube to rotate independently of the other cubes. Let's make a Cube class. Think of each cube as an object that we will handle individually.
class Cube {
float x, y, z; // position of the cube
float size; // size of cube
color c; // color of cube
float xAngle, yAngle, zAngle; // current rotation amount of cube's x, y, z axes
float xSpeed, ySpeed, zSpeed; // how quickly the cube is rotated in the x, y, z axes
// Cube constructor - create the cube and all of its parameters
Cube(float x_, float y_, float z_, float size_, color c_, float xSpeed_, float ySpeed_, float zSpeed_) {
x = x_;
y = y_;
z = z_;
size = size_;
c = c_;
xSpeed = xSpeed_;
ySpeed = ySpeed_;
zSpeed = zSpeed_;
xAngle = yAngle = zAngle = 0; // starting position
}
// update the cube
// all we're doing is rotating each axis
void update() {
xAngle += xSpeed;
yAngle += ySpeed;
zAngle += zSpeed;
}
// draw the cube to the screen
void display() {
pushMatrix(); // need this
translate(x, y, z); // position on screen
rotateX(xAngle); // rotation amounts
rotateY(yAngle);
rotateZ(zAngle);
fill(c);
noStroke();
box(size);
popMatrix(); // and this
// push and pop matrix allows for individual cube rotation
// otherwise you would rotate the whole draw window, which isn't what you're looking for
}
}
If you would like each cube to change color and position on screen but still rotate independently, the display() function could be something like this instead:
void display() {
pushMatrix();
translate(random(0, width), random(0, height), random(-100, 100)); // random position on screen
rotateX(xAngle);
rotateY(yAngle);
rotateZ(zAngle);
fill(random(255), random(255), random(255), 50); // random color
noStroke();
box(size);
popMatrix();
}
Understanding rotation and translation of elements in Processing is really key. I highly recommend this tutorial from the Processing website if you have not read it. I incorporated some concepts into the Cube class.
Since you would like to have more than one Cube drawn on the screen, let's make an array of Cubes. I chose 25 as an arbitrary number.
Cube[] cube = new Cube[25];
Now in setup(), we'll need to actually create each Cube and give it certain parameters, like position on screen, color, etc. Here is how that is accomplished.
for (int i = 0; i < cube.length; i++) {
cube[i] = new Cube(random(0, width), random(0, height), 0, // x, y, z position
random(30, 80), color(random(255), random(255), random(255), 50), // size, color
random(0.001, 0.020), random(0.001, 0.020), random(0.001, 0.020)); // xSpeed, ySpeed, zSpeed
}
Now we just need to draw the Cubes to the screen and update the rotation of each one, which simply happens in the draw() loop.
for (int i = 0; i < cube.length; i++) {
cube[i].update();
cube[i].display()
}
Here is whole program. It's important to call background() each time through the draw() loop so the display window will be cleared each frame. Comment it out to see what will happen, but I noticed that was not in the code snippet you provided above. I guess it can be an effect though!
Cube[] cube = new Cube[25];
void setup() {
size(640, 320, P3D);
smooth();
frameRate(60);
for (int i = 0; i < cube.length; i++) {
cube[i] = new Cube(random(0, width), random(0, height), 0,
random(30, 80), color(random(255), random(255), random(255), 50),
random(0.001, 0.020), random(0.001, 0.020), random(0.001, 0.020));
}
}
void draw() {
camera();
lights();
background(50);
for (int i = 0; i < cube.length; i++) {
cube[i].update();
cube[i].display();
}
}
I'm not sure what your programming background is, but getting a hang of Object Oriented Programming is really helpful in Processing (and other OOP languages), so I'd recommend this OOP tutorial from the Processing website if you need a crash course. My programming life changed when OOP finally made sense.