How to make a shape move while keeping a shape static without re-rendering the static shape? - processing

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);
}

Related

How can add interaction and animation to shapes drawn in Processing?

I'm trying to code a canvas full of shapes(houses) and animate them in processing.
Here's an example of shape:
void house(int x, int y) {
pushMatrix();
translate(x, y);
fill(0, 200, 0);
triangle(15, 0, 0, 15, 30, 15);
rect(0, 15, 30, 30);
rect(12, 30, 10, 15);
popMatrix();
}
By animation I mean moving them in random directions.
I would also like to add basic interaction: when hovering over a house it's colour would change.
At the moment I've managed to render a canvas full of houses:
void setup() {
size(500, 500);
background(#74F5E9);
for (int i = 30; i < 500; i = i + 100) {
for (int j = 30; j < 500; j = j + 100) {
house(i, j);
}
}
}
void house(int x, int y) {
pushMatrix();
translate(x, y);
fill(0, 200, 0);
triangle(15, 0, 0, 15, 30, 15);
rect(0, 15, 30, 30);
rect(12, 30, 10, 15);
popMatrix();
}
Without seeing source code: your attempted sketch it's very hard to tell.
They can be animated in many ways and it's unclear what you mean. For example, is that the position/rotation/scale of each square, is it the corners/vertices of each square, both ?
You might have a clear idea in your mind, but the current form of the question is ambiguous. We also don't know you're comfort level with various notions such as classes/objects/PVector/PShape/etc. If you were to 'story board' this animation what would it look like ? Breaking the problem down and explaining it in a way that anyone can understand might actually help you figure out a solution on your own as well.
Processing has plenty of examples. Here are a few I find relevant based on what my understanding is of your problem.
You can have a look at the Objects and Create Shapes examples:
File > Examples > Basics > Objects > Objects: Demonstrates grouping drawing/animation (easing, damping). You can tweak this example draw a single square and once you're happy with the look/motion you can animate multiple using an array or ArrayList
File > Examples > Topics > Create Shapes > PolygonPShapeOOP3: Great example using PShape to animate objects.
File > Examples > Topics > Create Shapes > WigglePShape: This example demonstrates how to access and modify the vertices of a PShape
For reference I'm simply copy/pasting the examples mentioned above here as well:
Objects
/**
* Objects
* by hbarragan.
*
* Move the cursor across the image to change the speed and positions
* of the geometry. The class MRect defines a group of lines.
*/
MRect r1, r2, r3, r4;
void setup()
{
size(640, 360);
fill(255, 204);
noStroke();
r1 = new MRect(1, 134.0, 0.532, 0.1*height, 10.0, 60.0);
r2 = new MRect(2, 44.0, 0.166, 0.3*height, 5.0, 50.0);
r3 = new MRect(2, 58.0, 0.332, 0.4*height, 10.0, 35.0);
r4 = new MRect(1, 120.0, 0.0498, 0.9*height, 15.0, 60.0);
}
void draw()
{
background(0);
r1.display();
r2.display();
r3.display();
r4.display();
r1.move(mouseX-(width/2), mouseY+(height*0.1), 30);
r2.move((mouseX+(width*0.05))%width, mouseY+(height*0.025), 20);
r3.move(mouseX/4, mouseY-(height*0.025), 40);
r4.move(mouseX-(width/2), (height-mouseY), 50);
}
class MRect
{
int w; // single bar width
float xpos; // rect xposition
float h; // rect height
float ypos ; // rect yposition
float d; // single bar distance
float t; // number of bars
MRect(int iw, float ixp, float ih, float iyp, float id, float it) {
w = iw;
xpos = ixp;
h = ih;
ypos = iyp;
d = id;
t = it;
}
void move (float posX, float posY, float damping) {
float dif = ypos - posY;
if (abs(dif) > 1) {
ypos -= dif/damping;
}
dif = xpos - posX;
if (abs(dif) > 1) {
xpos -= dif/damping;
}
}
void display() {
for (int i=0; i<t; i++) {
rect(xpos+(i*(d+w)), ypos, w, height*h);
}
}
}
PolygonPShapeOOP3:
/**
* PolygonPShapeOOP.
*
* Wrapping a PShape inside a custom class
* and demonstrating how we can have a multiple objects each
* using the same PShape.
*/
// A list of objects
ArrayList<Polygon> polygons;
// Three possible shapes
PShape[] shapes = new PShape[3];
void setup() {
size(640, 360, P2D);
shapes[0] = createShape(ELLIPSE,0,0,100,100);
shapes[0].setFill(color(255, 127));
shapes[0].setStroke(false);
shapes[1] = createShape(RECT,0,0,100,100);
shapes[1].setFill(color(255, 127));
shapes[1].setStroke(false);
shapes[2] = createShape();
shapes[2].beginShape();
shapes[2].fill(0, 127);
shapes[2].noStroke();
shapes[2].vertex(0, -50);
shapes[2].vertex(14, -20);
shapes[2].vertex(47, -15);
shapes[2].vertex(23, 7);
shapes[2].vertex(29, 40);
shapes[2].vertex(0, 25);
shapes[2].vertex(-29, 40);
shapes[2].vertex(-23, 7);
shapes[2].vertex(-47, -15);
shapes[2].vertex(-14, -20);
shapes[2].endShape(CLOSE);
// Make an ArrayList
polygons = new ArrayList<Polygon>();
for (int i = 0; i < 25; i++) {
int selection = int(random(shapes.length)); // Pick a random index
Polygon p = new Polygon(shapes[selection]); // Use corresponding PShape to create Polygon
polygons.add(p);
}
}
void draw() {
background(102);
// Display and move them all
for (Polygon poly : polygons) {
poly.display();
poly.move();
}
}
// A class to describe a Polygon (with a PShape)
class Polygon {
// The PShape object
PShape s;
// The location where we will draw the shape
float x, y;
// Variable for simple motion
float speed;
Polygon(PShape s_) {
x = random(width);
y = random(-500, -100);
s = s_;
speed = random(2, 6);
}
// Simple motion
void move() {
y+=speed;
if (y > height+100) {
y = -100;
}
}
// Draw the object
void display() {
pushMatrix();
translate(x, y);
shape(s);
popMatrix();
}
}
WigglePShape:
/**
* WigglePShape.
*
* How to move the individual vertices of a PShape
*/
// A "Wiggler" object
Wiggler w;
void setup() {
size(640, 360, P2D);
w = new Wiggler();
}
void draw() {
background(255);
w.display();
w.wiggle();
}
// An object that wraps the PShape
class Wiggler {
// The PShape to be "wiggled"
PShape s;
// Its location
float x, y;
// For 2D Perlin noise
float yoff = 0;
// We are using an ArrayList to keep a duplicate copy
// of vertices original locations.
ArrayList<PVector> original;
Wiggler() {
x = width/2;
y = height/2;
// The "original" locations of the vertices make up a circle
original = new ArrayList<PVector>();
for (float a = 0; a < radians(370); a += 0.2) {
PVector v = PVector.fromAngle(a);
v.mult(100);
original.add(new PVector());
original.add(v);
}
// Now make the PShape with those vertices
s = createShape();
s.beginShape(TRIANGLE_STRIP);
s.fill(80, 139, 255);
s.noStroke();
for (PVector v : original) {
s.vertex(v.x, v.y);
}
s.endShape(CLOSE);
}
void wiggle() {
float xoff = 0;
// Apply an offset to each vertex
for (int i = 1; i < s.getVertexCount(); i++) {
// Calculate a new vertex location based on noise around "original" location
PVector pos = original.get(i);
float a = TWO_PI*noise(xoff,yoff);
PVector r = PVector.fromAngle(a);
r.mult(4);
r.add(pos);
// Set the location of each vertex to the new one
s.setVertex(i, r.x, r.y);
// increment perlin noise x value
xoff+= 0.5;
}
// Increment perlin noise y value
yoff += 0.02;
}
void display() {
pushMatrix();
translate(x, y);
shape(s);
popMatrix();
}
}
Update
Based on your comments here's an version of your sketch modified so the color of the hovered house changes:
// store house bounding box dimensions for mouse hover check
int houseWidth = 30;
// 30 px rect height + 15 px triangle height
int houseHeight = 45;
void setup() {
size(500, 500);
}
void draw(){
background(#74F5E9);
for (int i = 30; i < 500; i = i + 100) {
for (int j = 30; j < 500; j = j + 100) {
// check if the cursor is (roughly) over a house
// and render with a different color
if(overHouse(i, j)){
house(i, j, color(0, 0, 200));
}else{
house(i, j, color(0, 200, 0));
}
}
}
}
void house(int x, int y, color fillColor) {
pushMatrix();
translate(x, y);
fill(fillColor);
triangle(15, 0, 0, 15, 30, 15);
rect(0, 15, 30, 30);
rect(12, 30, 10, 15);
popMatrix();
}
// from Processing RollOver example
// https://processing.org/examples/rollover.html
boolean overRect(int x, int y, int width, int height) {
if (mouseX >= x && mouseX <= x+width &&
mouseY >= y && mouseY <= y+height) {
return true;
} else {
return false;
}
}
// check if the mouse is within the bounding box of a house
boolean overHouse(int x, int y){
// offset half the house width since the pivot is at the tip of the house
// the horizontal center
return overRect(x - (houseWidth / 2), y, houseWidth, houseHeight);
}
The code is commented, but here are the main takeaways:
the house() function has been changed so you can specify a color
the overRect() function has been copied from the Rollover example
the overHouse() function uses overRect(), but adds a horizontal offset to take into account the house is drawn from the middle top point (the house tip is the shape's pivot point)
Regarding animation, Processing has tons of examples:
https://processing.org/examples/sinewave.html
https://processing.org/examples/additivewave.html
https://processing.org/examples/noise1d.html
https://processing.org/examples/noisewave.html
https://processing.org/examples/arrayobjects.html
and well as the Motion / Simulate / Vectors sections:
Let's start take sine motion as an example.
The sin() function takes an angle (in radians by default) and returns a value between -1.0 and 1.0
Since you're already calculating positions for each house within a 2D grid, you can offset each position using sin() to animate it. The nice thing about it is cyclical: no matter what angle you provide you always get values between -1.0 and 1.0. This would save you the trouble of needing to store the current x, y positions of each house in arrays so you can increment them in a different directions.
Here's a modified version of the above sketch that uses sin() to animate:
// store house bounding box dimensions for mouse hover check
int houseWidth = 30;
// 30 px rect height + 15 px triangle height
int houseHeight = 45;
void setup() {
size(500, 500);
}
void draw(){
background(#74F5E9);
for (int i = 30; i < 500; i = i + 100) {
for (int j = 30; j < 500; j = j + 100) {
// how fast should each module move around a circle (angle increment)
// try changing i with j, adding i + j or trying other mathematical expressions
// also try changing 0.05 to other values
float phase = (i + frameCount) * 0.05;
// try changing amplitude to other values
float amplitude = 30.0;
// map the sin() result from it's range to a pixel range (-30px to 30px for example)
float xOffset = map(sin(phase), -1.0, 1.0, -amplitude, amplitude);
// offset each original grid horizontal position (i) by the mapped sin() result
float x = i + xOffset;
// check if the cursor is (roughly) over a house
// and render with a different color
if(overHouse(i, j)){
house(x, j, color(0, 0, 200));
}else{
house(x, j, color(0, 200, 0));
}
}
}
}
void house(float x, float y, color fillColor) {
pushMatrix();
translate(x, y);
fill(fillColor);
triangle(15, 0, 0, 15, 30, 15);
rect(0, 15, 30, 30);
rect(12, 30, 10, 15);
popMatrix();
}
// from Processing RollOver example
// https://processing.org/examples/rollover.html
boolean overRect(int x, int y, int width, int height) {
if (mouseX >= x && mouseX <= x+width &&
mouseY >= y && mouseY <= y+height) {
return true;
} else {
return false;
}
}
// check if the mouse is within the bounding box of a house
boolean overHouse(int x, int y){
// offset half the house width since the pivot is at the tip of the house
// the horizontal center
return overRect(x - (houseWidth / 2), y, houseWidth, houseHeight);
}
Read through the comments and try to tweak the code to get a better understanding of how it works and have fun coming up with different animations.
The main changes are:
modifying the house() function to use float x,y positions (instead of int): this is to avoid converting float to int when using sin(), map() and get smoother motions (instead of motion that "snaps" to whole pixels)
Mapped sine to positions which can be used to animate
Wrapping the 3 instructions that calculate the x offset into a reusable function would allow you do further experiment. What if you used a similar technique the y position of each house ? What about both x and y ?
Go through the code step by step. Try to understand it, change it, break it, fix it and make new sketches reusing code.

object releases another smaller object?

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;
}

How to generate random position object

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 :)

How to remove previous shape after draw() in Processing

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.

Processing: Move centerpoint of a random Starfield to the center

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.

Resources