I cant figure this out. I have a sketch with little rotating rectangles on it. They rotate on every draw(). However the previous rectangle remains visible. I tried moving background() around but it either gets rid of all the rectangles apart from one or it doesn't clear the screen. I would like to be able to clear all the rectangles after each draw.
Here is the code:
//Create array of objects
ArrayList<Circle> circles = new ArrayList<Circle>();
ArrayList<Connector> centrePoint = new ArrayList<Connector>();
void setup(){
size(800, 800);
frameRate(1);
rectMode(CENTER);
background(204);
for(int i = 1; i < 50; i++){
float r = random(100,height-100);
float s = random(100,width-100);
float t = 20;
float u = 20;
println("Print ellipse r and s " + r,s);
circles.add(new Circle(r,s,t,u,color(14,255,255),random(360),random(5),random(10)));
}
//Draw out all the circles from the array
for(Circle circle : circles){
circle.draw();
float connectStartX = circle.x1;
float connectStartY = circle.y1;
println("PrintconnectStartX and Y " + connectStartX,connectStartY);
for(Circle circleEnd : circles){
float connectEndX = (circleEnd.x1);
float connectEndY = (circleEnd.y1);
centrePoint.add(new Connector(connectStartX,connectStartY,connectEndX,connectEndY));
}
}
//For each ellipse, add the centre point of the ellipse to array
for(Connector connectUp : centrePoint){
println(connectUp.connectStartX ,connectUp.connectStartY ,connectUp.connectEndX ,connectUp.connectEndY);
stroke(100, 0, 0);
if (dist(connectUp.connectStartX ,connectUp.connectStartY ,connectUp.connectEndX ,connectUp.connectEndY) < 75){
connectUp.draw(connectUp.connectStartX ,connectUp.connectStartY ,connectUp.connectEndX ,connectUp.connectEndY);
}
}
//For the line weight it should equal the fat of the node it has come from ie
//for each circle, for each connectUp if the x==connectStartX and y==connectStartY then make the line strokeWeight==fat
for(Circle circle : circles){
for(Connector connectUp : centrePoint){
if (connectUp.connectStartX == circle.x1 & connectUp.connectStartY == circle.y1 & (dist(connectUp.connectStartX ,connectUp.connectStartY ,connectUp.connectEndX ,connectUp.connectEndY) < 75)){
print(" true "+ circle.fat);
float authority = circle.fat;
strokeWeight(authority*1.5);
connectUp.draw(connectUp.connectStartX ,connectUp.connectStartY ,connectUp.connectEndX ,connectUp.connectEndY);
}
}
}
}
void update(){
}
void draw() {
for(Circle circle : circles){
circle.rot =+0.02;
circle.draw();
circle.rot = random(-6,6);
}
}
//Need to connect each ellipse to all the other ellipses
class Connector {
public float connectStartX;
public float connectStartY;
public float connectEndX;
public float connectEndY;
public color cB;
public float thickness;
public Connector(float connectStartX, float connectStartY, float connectEndX, float connectEndY){
this.connectStartX = connectStartX;
this.connectStartY = connectStartY;
this.connectEndX = connectEndX;
this.connectEndY = connectEndY;
//this.cB = tempcB;
//this.thickness = thickness;
}
void draw(float connectStartX, float connectStartY, float connectEndX, float connectEndY){
line(connectStartX, connectStartY, connectEndX, connectEndY);
// float fat = random(255);
//fill(fat);
stroke(100, 0, 0);
}
}
class Circle{
public float x1;
public float y1;
public float x2;
public float y2;
public color cB;
public float rot;
public float fat = random(5);
public float fert = 0.1;
public Circle(float x1, float y1, float x2, float y2, color tempcB, float rot, float fat, float fert){
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.cB = tempcB;
//Tilt - I think this is done in radians
this.rot = rot;
//Authority -this is the fill
this.fat = fat;
//Fertility- this is a multiplier for the tilt
this.fert = fert;
}
void draw(){
pushMatrix();
translate(x1, y1);
fert = random(0.5);
rot = random(-6,6);
rotate(rot*fert);
translate(-x1, -y1);
//float fat = random(255);
fill(fat);
rect(x1, y1, 24, 36);
popMatrix();
}
}
You've got a few things going on in your code that I've seen in your previous posts. The way you're doing your drawing doesn't make a ton of sense, and I'll explain why.
Here's what most Processing sketches do:
Use the setup() function to setup any data structures you'll use in your program. Don't do any drawing from the setup() function.
Call background() every frame to clear out old frames.
Draw everything you want to be drawn in the frame in the draw() function.
Modify the data structures to change what you're drawing on the screen.
Your code is a bit too long for an MCVE, so here's a little example that handles the drawing in a more standard way:
ArrayList<PVector> circles = new ArrayList<PVector>();
void setup() {
size(500, 500);
ellipseMode(RADIUS);
//setup your data structures here
circles.add(new PVector(250, 250));
//don't do any drawing yet
}
void mousePressed() {
//modify the data structure whenever you want to change what's on the screen
circles.add(new PVector(mouseX, mouseY));
}
void keyPressed() {
//modify the data structure whenever you want to change what's on the screen
if (!circles.isEmpty()) {
circles.remove(0);
}
}
void draw() {
//call background every frame to clear out old frames
background(0);
//draw everything
for (PVector p : circles) {
ellipse(p.x, p.y, 20, 20);
}
}
Notice how this is different from what you're doing. Here's what you do:
You use the setup() function to setup your data structures, but then you draw the background and some of the objects to the screen.
You then don't call background() from draw(), so you're always stuck with whatever has already been drawn.
You then only draw a subset of what you want on the screen, so you can't redraw your whole scene.
You have to modify your code to no longer draw anything from setup(), to call the background() function every frame, and to draw everything you want on the screen every frame.
What you are doing is printing every single circle or line...ect. You need to have a timer that removes them every so often. If you do it too fast you get a strobe like look. So have a timer that removes the first rect from the array list every so often.
Related
Can anyone help me?
So, I'm supposed to have a ball that is moving horizontally, such that every time I press the mouse, a ball would get shoot vertically, then slows down due to friction. The vertical ball would stay in the old position but the player would reset.
How do I go about doing that without using classes?
Here my code so far:
boolean circleupdatetostop = true;
float x = 100;
float yshot = 880;
float speedshot = random(4,10);
float speedx = 6;
void setup() {
size(1280,960);
}
void draw() {
background(255);
stroke(0);
fill(0);
circle(x,880,80);
if (x > width || x < 0 ) {
speedx = speedx * -1;
}
if (circleupdatetostop) {
x = x + speedx;
}
if (circleupdatetostop == false) {
float locationx = x;
stroke(0);
fill(255,0,255);
circle(locationx,yshot,30);
yshot = yshot - speedshot;
}
}
void mousePressed () {
circleupdatetostop = !circleupdatetostop;
}
I'm not entirely sure if this is what you meant, but you could achieve shooting multiple balls by using ArrayList as well as processing's PVector to better handle the x and y coordinate pairs. If you wanted to look at classes, see this post.
import java.util.*;
// Whether the ball is moving or not
boolean circleupdatetostop = true;
// Information about the main_ball
PVector position = new PVector(100, 880);
PVector speed = new PVector(6, 0);
float diameter = 80;
// Information about the sot balls
ArrayList<PVector> balls_loc = new ArrayList<PVector>();
ArrayList<PVector> balls_speed = new ArrayList<PVector>();
float diameter_shot = 30;
float friction = 0.994;
void setup() {
size(1280, 960);
}
void draw() {
background(255);
stroke(0);
fill(0);
circle(position.x, position.y, diameter);
// Remember to consider the radius of the ball when bouncing off the edges
if (position.x + diameter/2 > width || position.x - diameter/2 < 0 ) {
speed.mult(-1);
}
if (circleupdatetostop) {
position.add(speed);
}
// Cycle through the list updating their speed and draw each ball
for (int i = 0; i<balls_loc.size(); i++) {
balls_speed.get(i).mult(friction+random(-0.05, 0.05));
balls_loc.get(i).add(balls_speed.get(i));
stroke(0);
fill(255, 0, 255);
circle(balls_loc.get(i).x, balls_loc.get(i).y, diameter_shot);
}
}
void mousePressed(){
// Add a new ball to be drawn
if(circleupdatetostop){
balls_loc.add(new PVector(position.x, position.y));
balls_speed.add(new PVector(0, random(-4, -10)));
}
circleupdatetostop = !circleupdatetostop;
}
I'm trying to generate 15 circles on a 1500 - 1000 space, every cirlce with a diferent position. I know how to generate 1 random circle but that's all. How should I do it?
It sounds like you're looking for a for loop:
for(int i = 0; i < 15; i++){
// draw a random circle here
}
Shameless self-promotion: here is a tutorial on for loops in Processing.
Basically, you need to create a Circle class and ArrayList which contains all your circles.
Then using a for you add in that list 15 circles passing to constructor random coordinates and a fixed width and height you decide.
class Circle {
float x, y, size;
public Circle(float x, float y, float size) {
this.x = x;
this.y = y;
this.size = size;
}
public void update() {
ellipse(x, y, size, size);
}
}
Declare globally your ArrayList. Now, in setup() you instantiate your ArrayList and populate it with randomly generated coordinates
ArrayList<Circle> circlesList; // This needs to be declared globally
float circleSize = 64; // Circles size in pixels
void setup() {
size(1500, 1000);
circlesList = new ArrayList<Circle>();
// Populating the ArrayList with circles
for (int i = 0; i < 15; i++) {
float randomx = random(0, 1500); // Random generated X
float randomy = random(0, 1000); // Random generated Y
Circle newCircle = new Circle(randomx, randomy, circleSize);
circlesList.add(newCircle);
}
}
Now in draw() function, using a foreach loop, you'll draw every single circle inside that ArrayList
void draw() {
background(255); // Background color
fill(255, 0, 0); // Circle fill color
for (Circle c : circlesList) {
c.update();
}
}
Please note that this way your circles may overlap or be a little bit outside of the screen. Ask anything if the code is unclear, don't just copy-paste it.
Hope this helped :)
In Processing, I'm trying to animate a spinning polygon. In the background, I have a series of 50 triangles that act as a gradient. These are both created in my draw function. How do I ensure that the polygon keeps spinning, but the triangles stay in the background without having to keep re-rendering the 50 triangles? Perhaps there's a cleaner way to create this triangular gradient?
int n = 9;
float ceiling = 350;
float floor = 250;
float diff = (ceiling - floor)/2;
float per = 0;
float dir = -1;
float rate = 0.01;
void setup() {
size(800, 800);
background(125,25,25);
frameRate(30);
}
void draw() {
background(125,25,25);
// Creates the triangles in background
for (float k=0; k<50; k++) {
strokeWeight(1);
stroke(#5E4622);
fill(47,74,57,100*(k/50));
triangle(100,height,width-100,height,width/2,height*k/50);
}
stroke(0);
// Creates spinning nonagons
pushMatrix();
translate(width/2, height/2);
rotate(2*PI*(dir*per));
stroke(#F4EA4A);
strokeWeight(6);
noFill();
polygon(0,0,floor+(diff*sin(2*PI*per))+10,n);
stroke(0);
strokeWeight(3);
float[] vertices = polygon(0, 0, floor+(diff*sin(2*PI*per)), n);
connect(vertices);
per += rate;
popMatrix();
}
// Takes a center (x,y) and draws an n-gon of radius r around it
// Returns an array of floats representing the points of the polygon
// Like: {x1,y1,x2,y2,...,xn,yn}
float[] polygon(float x, float y, float r, int n) {
float angle = 2*PI/n;
float[] vertices = new float[2*n];
beginShape();
for (int i=0; i<n; i++) {
float vX = r*cos(i*angle) + x;
float vY = r*sin(i*angle) + y;
vertex(vX, vY);
vertices[2*i] = vX;
vertices[2*i+1] = vY;
}
endShape(CLOSE);
return vertices;
}
// Takes in an array of vertices of a polygon and connects them together.
// Ignores neighboring vertices when considering which vertices to connect
// to a vertex.
void connect(float[] vertices) {
int n = vertices.length / 2;
for (int i=0; i<n; i++) {
float x = vertices[2*i];
float y = vertices[2*i+1];
for (int j=0; j<n; j++) {
if (j!=i || j!=(i-1)%n || j!=(i+1)%n) {
float endX = vertices[2*j];
float endY = vertices[2*j+1];
line(x, y, endX, endY);
}
}
}
}
This code creates what I want, but it runs pretty choppily due to having to re-render the triangles
How do I ensure that the polygon keeps spinning, but the triangles stay in the background without having to keep re-rendering the 50 triangles?
Render the static background to a PGraphics at initialization, in the setup function:
PGraphics pg;
void setup() {
size(800, 800);
// Creates the triangles in background
pg = createGraphics(800, 800);
pg.beginDraw();
pg.background(125,25,25);
for (float k=0; k<50; k++) {
pg.strokeWeight(1);
pg.stroke(#5E4622);
pg.fill(47,74,57,100*(k/50));
pg.triangle(100,height,width-100,height,width/2,height*k/50);
}
pg.endDraw();
frameRate(30);
}
Draw the background image to the scene by image(), in every frame, instead of filling the background by background():
void draw() {
// background image to screen
image(pg, 0, 0);
stroke(0);
// Creates spinning nonagons
// ...
}
Perhaps there's a cleaner way to create this triangular gradient?
If you want to get a smooth gradient background and get rid of the lines, then use pg.noStroke() rather than of pg.stroke(#5E4622);.
Additionally vary the size of the triangle on ist base, too:
for (float k=0; k<50; k++) {
pg.noStroke();
pg.fill(47,74,57,100*(k/50));
pg.triangle(k/50*width/2,height,width-k/50*width/2,height,width/2,height*k/50);
}
I am trying to create a sketch which consists of randomly placed lines with random angulations and strokeWeight. The idea is that at each frame the lines change their tilt slightly according to a preset rule which in turn depends on the strokeWeight and other parameters. To do this I think I need to record the co-ordinates of each line at setup and then transform them and then record them again. If that makes sense.
Basically the question boils down to how can I record the co-ordinates of all the lines on a canvas?
Here is what I have written so far but how do I store the shape co-ordinates:
//Sets up the random lines on the canvas
//Sets up the authorities (line widths)
//Sets up the connections between lines
void setup() {
background(204);
size(800, 800);
for (int x=1;x <1000;x +=1){
fill(75, 70, 80);
//For the x y cords
float r = random(800);
float s = random(800);
//for the strokeWeight
float fat = random(5);
//for the stroke colour which varies with stroke weight
float col = random(350);
float red = random(350);
float g = random(350);
float b = random(350);
//for the initial tilt
float rot = random(360);
//stroke(242, 204, 47, 255);
strokeWeight(fat);
//stroke (red,green,blue,opacity)
stroke(fat*100, 180, 180);
//stroke(242, 204, 47, 255);
line(r,s,r+10,s+10);
rotate(radians(rot));
}
}
//This part is the diffusion animation
void draw() {
}
You might want to create a Line class that holds the information necessary to draw a line. Something like this:
class Line{
float x1, y1, x2, y2;
public Line(float x1, float y1, float x2, float y2){
this.x1 = x1;
this.y1 = y1
this.x2 = x2;
this.y2 = y2;
}
public void draw(){
line(x1, y1, x2, y2);
}
public boolean intersects(Line other){
//left as exercise for reader
}
}
Then you can randomly generate lines:
ArrayList<Line> lines = new ArrayList<Line>();
void setup(){
for(int i = 0; i < 10; i++){
lines.add(new Line(random(width), random(height), random(width), random(height));
}
}
void draw(){
background(0);
for(Line line : lines){
line.draw();
}
}
This is what I was getting at when I told you in your other question that you need to create a data structure and store your line coordinates. From here you can write logic that moves your lines around, or detects intersections, etc.
I'm working on a little space simulation with processing. In the game you can zoom in & out of the solar system. To gove that a neat paralax effect, I want to zoom into the randomly renerated starsky in the background. So far I have everything working, but the starsky is zooming into the top left corner. I know I have to translate the origin point of the stars to (width/2,height/2), but I can't figure out how I do that.
Here is the code:
int starCount = 1200;
float[] xStar = new float[starCount];
float[] yStar = new float[starCount];
float starSpread;
float zoom;
void setup() {
size(1600, 900);
frameRate(30);
calcStars();
zoom = 1;
}
void draw() {
background(#000000);
for(int i=0;i<starCount;i++){
fill(#fff7e6);
noStroke();
ellipse(xStar[i]*starSpread,yStar[i]*starSpread,1,1);
}
starSpread = 1+zoom*0.001;
}
void calcStars(){
for(int i=0;i<starCount;i++){
xStar[i] = -random(0-width);
}
for(int i=0;i<starCount;i++){
yStar[i] = -random(0-height);
}
}
void mousePressed(){
zoom = zoom - 1;
}
(Click mouse to "zoom" out! <- I want the stars to move to the middle not to the upper left corner)
So, I have 2 arrays giving me 1200 random coordinates in the window. "zoom" is a simple float that's controllable with a slider. This variable controlls the spread of all the content. It's mutiplied by 0.001 to make the effect on my stars just slightly.
Now can somebody help me making the zoom happen as I intend it to?
Thanks in advance!
There are a bunch of ways to do this, but the basic approach is this:
Step 1: Calculate how far apart from the center of the screen each star is.
Step 2: Scale that distance.
Step 3: Draw each star that scaled distance away from the center point.
int starCount = 1200;
float[] xStar = new float[starCount];
float[] yStar = new float[starCount];
float zoom = 1;
void setup() {
size(1600, 900);
frameRate(30);
calcStars();
}
void draw() {
background(#000000);
for (int i=0; i<starCount; i++) {
fill(#fff7e6);
noStroke();
float centerX = width/2.0;
float centerY = height/2.0;
float xDistFromCenterX = centerX - xStar[i];
float yDistFromCenterY = centerY - yStar[i];
float scaledXDistFromCenterX = zoom * xDistFromCenterX;
float scaledYDistFromCenterY = zoom * yDistFromCenterY;
ellipse(centerX + scaledXDistFromCenterX, centerY + scaledYDistFromCenterY , 1, 1);
}
}
void calcStars() {
for (int i=0; i<starCount; i++) {
xStar[i] = -random(0-width);
}
for (int i=0; i<starCount; i++) {
yStar[i] = -random(0-height);
}
}
void mousePressed() {
zoom = zoom + .1;
}
This works, and I think it's pretty close to what you were going for, but you might also consider refactoring your code to use a Star object that keeps track of its own position. Whenever you want to zoom, just tell each Star object to move. You could also draw your starts to an image ahead of time, and then just scale that image. Like I said, there are a bunch of ways to do this.