Processing: collisions with trails - processing

Dealing with collisions in Processing is straightforward. However, how do I identify collisions with trails?
Example: imagine the light cycles in Tron, if you wish, with the alteration that trails of derezzed light cycles do not disappear. In Tron, if a cycle intersects any point another cycle, itself included, has ever been, it 'dies'. How do I efficiently find this event in Processing?

One hacky workaround is to draw the line into a PImage and check if the colour at a location is the same as the background or not (e.g. a pre-existing line, hence a collision).
Here's a rough (and slightly inefficient (due to get()/set() calls) proof of concept:
PImage buffer;
//how mutch we scale down = how pixely this will look
int multiplier = 8;
//scaled down width/height
int w,h;
//cursor position
int px,py;
//cursor velocity;
int vx,vy;
void setup(){
size(400,400);
noSmooth();
w = width / multiplier;
h = height / multiplier;
buffer = createImage(w,h,RGB);
clear();
}
void clear(){
java.util.Arrays.fill(buffer.pixels,color(0));
buffer.updatePixels();
}
void draw(){
//update cursor
px += vx;
py += vy;
//check edges
if(px < 0){
px = w-1;
}
if(px > w){
px = 0;
}
if(py < 0){
py = h-1;
}
if(py > h){
py = 0;
}
//check collision
if(keyPressed){
if(keyCode == UP || keyCode == DOWN || keyCode == LEFT || keyCode == RIGHT){
checkSelfIntersection();
}
}
//paint cursor
buffer.set(px,py,color(0,192,0));
//render on screen
image(buffer,0,0,width,height);
}
void checkSelfIntersection(){
//if the pixel ahead is not the same colour as the background
if(buffer.get(px+vx,py+vy) > color(0)){
clear();
println("Cycle go BOOM!");
}
}
void keyPressed(){
if(keyCode == UP){
vy = -1;
}
if(keyCode == DOWN){
vy = +1;
}
if(keyCode == LEFT){
vx = -1;
}
if(keyCode == RIGHT){
vx = +1;
}
}
void keyReleased(){
vx = vy = 0;
}
A similar concept can be done be keeping track of points in a list and checking if a new point is already part of this list (collision) or not:
ArrayList<PVector> path = new ArrayList<PVector>();
//cursor position
int px,py;
//cursor velocity;
int vx,vy;
void setup(){
size(400,400);
noFill();
strokeWeight(10);
}
void draw(){
//update cursor
px += vx;
py += vy;
//check edges
if(px < 0){
px = 0;
}
if(px > width){
px = width;
}
if(py < 0){
py = 0;
}
if(py > height){
py = height;
}
//check collision
if(keyPressed){
if(keyCode == UP || keyCode == DOWN || keyCode == LEFT || keyCode == RIGHT){
checkSelfIntersection();
}
}
background(255);
beginShape();
for(int i = 0 ; i < path.size(); i++){
PVector p = path.get(i);
vertex(p.x,p.y);
}
endShape();
}
void checkSelfIntersection(){
PVector cursor = new PVector(px,py);
if(path.contains(cursor)){
path.clear();
println("Cycle go BOOM!");
}else{
path.add(cursor);
}
}
void keyPressed(){
if(keyCode == UP){
vy = -5;
}
if(keyCode == DOWN){
vy = +5;
}
if(keyCode == LEFT){
vx = -5;
}
if(keyCode == RIGHT){
vx = +5;
}
}
void keyReleased(){
vx = vy = 0;
}
The concept isn't that different from how games like Snake/Volfied/etc. check for self intersections.
Note I'm cheating a bit by updating a "cursor" on keys with a small velocity: this avoid gaps in the lines. If you try to replace with the mouse, you'll notice the collision check may fail if the mouse moves fast as it checks one point against a list of recorded points. An alternative might be to split the list of points into pairs of lines and check if the new point intersects any of them.
You might want to also check this similar question

Stack Overflow isn't really designed for general "how do I do this" type questions. It's for specific "I tried X, expected Y, but got Z instead" type questions. That being said, I'll try to help in a general sense.
You can probably just keep track of the lines formed by the cycles, in the form of an ArrayList of all of the points where a player turned. Then at each step, you can check whether the player is intersecting with any of those lines.
More specifically, you'd probably want to form another line between the previous player coordinate and the next player coordinate. Then check whether that line intersects with any of the other lines using formulas that I'm sure you can find through a google search or two.
You probably don't have to do anything smarter than that unless you're talking about very very large playing fields (as in, millions of lines). So it's a little early to ask about efficiency.
There are of course many other ways to approach the problem. You might also use a 2D array that keeps track of the trails, or you could use pixel-based collision, or probably any number of other solutions. The point is you need to try something and post a MCVE along with a specific question if you get stuck, and we'll go from there. Good luck.

Related

How to make this pattern to expand and shrink back

i have a task to make a pattern of circles and squares as described on photo, and i need to animate it so that all objects smoothly increase to four times the size and then shrink back to their original size and this is repeated. i tried but i cant understand problem
{
size(500,500);
background(#A5A3A3);
noFill();
rectMode(CENTER);
ellipseMode(CENTER);
}
void pattern(int a, int b)
{
boolean isShrinking = false;
for(int x = 0; x <= width; x += a){
for(int y = 0; y <= height; y += a){
stroke(#1B08FF);
ellipse(x,y,a,a);
stroke(#FF0000);
rect(x,y,a,a);
stroke(#0BFF00);
ellipse(x+25,y+25,a/2,a/2);
if (isShrinking){a -= b;}
else {a += b;}
if (a == 50 || a == 200){
isShrinking = !isShrinking ; }
}
}
}
void draw()
{
pattern(50,1);
}
this is what pattern need to look like
Great that you've posted your attempt.
From what you presented I can't understand the problem either. If this is an assignment, perhaps try to get more clarifications ?
If you comment you the isShrinking part of the code indeed you have an drawing similar to image you posted.
animate it so that all objects smoothly increase to four times the size and then shrink back to their original size and this is repeated
Does that simply mean scaling the whole pattern ?
If so, you can make use of the sine function (sin()) and the map() function to achieve that:
sin(), as the reference mentions, returns a value between -1 and 1 when you pass it an angle between 0 and 2 * PI (because in Processing trig. functions use radians not degrees for angles)
You can use frameCount divided by a fractional value to mimic an even increasing angle. (Even if you go around the circle multiple times (angle > 2 * PI), sin() will still return a value between -1 and 1)
map() takes a single value from one number range and maps it to another. (In your case from sin()'s result (-1,1) to the scale range (1,4)
Here's a tweaked version of your code with the above notes:
void setup()
{
size(500, 500, FX2D);
background(#A5A3A3);
noFill();
rectMode(CENTER);
ellipseMode(CENTER);
}
void pattern(int a)
{
for (int x = 0; x <= width; x += a) {
for (int y = 0; y <= height; y += a) {
stroke(#1B08FF);
ellipse(x, y, a, a);
stroke(#FF0000);
rect(x, y, a, a);
stroke(#0BFF00);
ellipse(x+25, y+25, a/2, a/2);
}
}
}
void draw()
{
// clear frame (previous drawings)
background(255);
// use the frame number as if it's an angle
float angleInRadians = frameCount * .01;
// map the sin of the frame based angle to the scale range
float sinAsScale = map(sin(angleInRadians), -1, 1, 1, 4);
// apply the scale
scale(sinAsScale);
// render the pattern (at current scale)
pattern(50);
}
(I've chosen the FX2D renderer because it's smoother in this case.
Additionally I advise in the future formatting the code. It makes it so much easier to read and it barely takes any effort (press Ctrl+T). On the long run you'll read code more than you'll write it, especially on large programs and heaving code that's easy to read will save you plenty of time and potentially headaches.)

How to make something "instantaneously" in Processing

So, i'm sorry if this is a weird or stupid question but I genuinely couldn't find an answer. So, the thing is I'm trying to do a visual representation of the multiplication tables, so i divide a circle in a certain number of "slices", for example I divide it in 10. Then I join each point with its product, for example for the 2 times table i make a line between 1 and 2, another one between 2 and 4, 3 and 6 and so on...
The thing is, if i surpass a certain amount of "slices" i can clearly see Processing drawing each one of the lines one by one. I wanted to progressively change the number of slices so you can see how does it evolve, but then the lines would just have to "appear" or change instantaneously since the "animation" makes no sense if you see it drawing every line. Is there a way I can improve the speed of the program, or just make it show all lines at once?
For reference, this is how i kinda want it to look like:
YouTube video
This is the code i'm using (with the ControlP5 library and soooo poorly optimized):
import controlP5.*;
ControlP5 cp5;
Knob myKnobA;
Knob myKnobB;
int ncosas = 30;
float sumangle = (2*PI)/ncosas;
float angle = HALF_PI + PI + sumangle;
int radius = 100;
int counter = 1;
int sumar = 15;
int tablade = 2;
int prueba = 30;
void setup(){
size(400,400);
background(255);
textAlign(CENTER,CENTER);
fill(0);
stroke(0);
textSize(8);
cp5 = new ControlP5(this);
myKnobA = cp5.addKnob("Servo")
.setRange(1,120)
.setValue(1)
.setPosition(20,20)
.setRadius(30)
.setDragDirection(Knob.HORIZONTAL)
.setCaptionLabel("N")
.setColorCaptionLabel(0)
;
myKnobB = cp5.addKnob("TablaD")
.setRange(1,50)
.setValue(1)
.setPosition(20,120)
.setRadius(30)
.setDragDirection(Knob.HORIZONTAL)
.setCaptionLabel("Tabla de")
.setColorCaptionLabel(0)
;
//translate(height/2,width/2);
//line(0,0,radius*sin(radians(prueba)),radius*cos(radians(prueba)));
}
void draw(){
if(counter <= ncosas){
dibujar();
}
}
void Servo(int theValue){
background(255);
counter = 1;
ncosas = theValue;
sumangle = (2*PI)/ncosas;
angle = HALF_PI + PI + sumangle;
}
void TablaD(int theValue){
background(255);
counter = 1;
tablade = theValue;
angle = HALF_PI + PI + sumangle;
}
void dibujar(){
pushMatrix();
translate(width*2.5/4,height/2);
circle(radius*sin(angle),radius*cos(angle),2);
//if(counter*tablade<=ncosas){
line(radius*sin(angle),radius*cos(angle),radius*sin((counter*tablade*sumangle)+(angle-counter*sumangle)),radius*cos((counter*tablade*sumangle)+(angle-counter*sumangle)));
//}
println(counter*tablade + " -> " + counter*tablade*degrees(sumangle));
text(counter,(radius+sumar)*sin(angle),(radius+sumar)*cos(angle));
angle += sumangle;
counter++;
popMatrix();
}
void keyPressed(){
if (key == 'D' || key == 'd'){
Servo(int(myKnobA.getValue())+1);
myKnobA.setValue(int(myKnobA.getValue())+1);
}
if (key == 'A' || key == 'a'){
Servo(int(myKnobA.getValue())-1);
myKnobA.setValue(int(myKnobA.getValue())-1);
}
if (key == 'W' || key == 'w'){
TablaD(int(myKnobB.getValue())+1);
myKnobB.setValue(int(myKnobB.getValue())+1);
}
if (key == 'S' || key == 's'){
TablaD(int(myKnobB.getValue())-1);
myKnobB.setValue(int(myKnobB.getValue())-1);
}
}
Thank you in advance
To expand on what John Coleman said, you need to execute the dibujar() command multiple times in draw(). In Processing, the canvas is rendered at the end of the draw() loop, so if you draw multiple lines in draw(), they will all appear at the same time.
This will involve some kind of loop. If you want to draw the entire multiplication circle at once, you could replace if with while in the draw() loop:
void draw(){
while (counter <= ncosas){
dibujar();
}
}
I believe this will draw the entire multiplication circle in a single frame. You can then adjust the knobs to change the parameters of the multiplication circle, and the multiplication circle will change as you adjust the knobs.

Constrain mouse daw to 45degrees Processing

How does one constrain interactively drawing a line to 45degrees?
Imagine there in an underlining grid that's at 45 degees which the mouse draw is magnetized too. Perhaps on mousedown decides which your starting position is and after that your Mouse.X and Mouse.Y position only update in 45 degrees from that starting click?
float dif = 10;
float easing = 0.05;
boolean current = false;
boolean started = false;
float rainbow, x, y;
float colbase;
PVector pos, prev_pos, update_pos;
float step = 25;
void setup(){
size(400, 400);
background(100);
colorMode(HSB);
}
void draw(){
if (rainbow >= 255) rainbow=0; else rainbow+=5;
if (frameCount % dif == 0) {
colbase = rainbow;
}
if(mousePressed){
update_pos();
if(current){
started = true;//start drawing
pos = update_pos;
}else{
prev_pos = update_pos;
}
current = !current;
}else{
update_pos();
started = false;
pos = update_pos;
prev_pos = update_pos;
}
if(started){
//style for lines
strokeWeight(step);
stroke(colbase,255,255);
noFill();
line(prev_pos.x, prev_pos.y, pos.x, pos.y);
}
}
PVector update_pos(){
x = lerp(x, mouseX, easing);
y = lerp(y, mouseY, easing);
update_pos = new PVector(x, y);
return update_pos;
}
I would like to say that I like this. Also, that this question was ultimately way harder to answer than I though it would be.
Here's the result:
First, I took the liberty to reorganize your example code. I don't know how experienced you are, and maybe some of the things I changed were on purpose, but it seemed to me that your example had a lot of weird code bits dangling. Here's the example code with my changes (check the next code block for the answer, this one is more like a code review to help you in general):
float dif = 10;
float easing = 0.05;
boolean current, started; // automatically initializing as false unless stated otherwise
float rainbow;
float colbase;
PVector pos, prev_pos;
float step = 25;
void setup() {
size(400, 400);
background(100);
colorMode(HSB); // clever!
pos = prev_pos = new PVector(); // instanciating some non-null PVectors
}
void draw() {
pos = prev_pos = update_pos(); // cascade attribution: it starts by the last one and goes back toward 'pos'
if (mousePressed) {
if (!started) {
// initializing variables needed for drawing
started = true;
pos = prev_pos = new PVector(mouseX, mouseY);
}
} else {
started = false;
}
if (started) {
updateColor();
strokeWeight(step);
stroke(colbase, 255, 255);
noFill();
line(prev_pos.x, prev_pos.y, pos.x, pos.y);
}
}
void updateColor() {
if (rainbow >= 255) {
rainbow=0;
} else {
rainbow+=5;
}
if (frameCount % dif == 0) {
colbase = rainbow;
}
}
PVector update_pos() {
float x = lerp(pos.x, mouseX, easing);
float y = lerp(pos.y, mouseY, easing);
return new PVector(x, y);
}
Notice how I changed a couple variables names. As a general rule, you should always name your variables as if the guy maintaining your code was an angry biker who knows where you live.
Now to solve your actual question:
boolean isDrawing;
float rainbow, colbase, dif, easing, step, centerZone;
PVector pos, prev_pos, origin, quadrant;
void setup() {
size(400, 400);
background(100);
colorMode(HSB); // clever!
centerZone = 5; // determine how close to the original click you must be to change quadrant
dif = 10;
easing = 0.05;
step = 25;
origin = pos = prev_pos = new PVector();
}
void draw() {
updatePosition();
if (mousePressed) {
if (!isDrawing) {
// setting variables needed for drawing
isDrawing = true;
origin = pos = prev_pos = new PVector(mouseX, mouseY); // drawing should always start where the mouse currently is
}
} else {
isDrawing = false;
}
if (isDrawing) {
updateColor();
strokeWeight(step);
stroke(colbase, 255, 255);
noFill();
line(prev_pos.x, prev_pos.y, pos.x, pos.y);
}
}
void updateColor() {
if (rainbow >= 255) {
rainbow=0;
} else {
rainbow+=5;
}
if (frameCount % dif == 0) {
colbase = rainbow;
}
}
void updatePosition() {
float relativeX = pos.x - origin.x;
float relativeY = pos.y - origin.y;
float diffX = mouseX - origin.x;
float diffY = mouseY - origin.y;
float distance = abs(diffX) > abs(diffY) ? abs(diffX) : abs(diffY); // this is just inline if, the syntax being " condition ? return if true : return if false; "
prev_pos = pos;
// validating if the mouse is in the same quadrant as the pencil
PVector mouseQuadrant = new PVector(diffX > 0 ? 1 : -1, diffY > 0 ? 1 : -1);
// we can only change quadrant when near the center
float distanceFromTheCenter = abs(relativeX) + abs(relativeY);
if (quadrant == null || distanceFromTheCenter < centerZone) {
quadrant = new PVector(diffX > 0 ? 1 : -1, diffY > 0 ? 1 : -1);
}
// if the mouse left it's quadrant, then draw toward the center until close enough to change direction
// ^ is the XOR operator, which returns true only when one of the sides is different than the other (one true, one false)
// if the quadrant info is positive and the diff coordinate is negative (or the other way around) we know the mouse has changed quadrant
if (distanceFromTheCenter > centerZone && (relativeX > 0 ^ mouseQuadrant.x > 0 || relativeY > 0 ^ mouseQuadrant.y > 0)) {
// going toward origin
pos = new PVector(lerp(prev_pos.x, origin.x, easing), lerp(prev_pos.y, origin.y, easing));
} else {
// drawing normally
pos = new PVector(lerp(prev_pos.x, origin.x + (distance * quadrant.x), easing), lerp(prev_pos.y, origin.y + (distance * quadrant.y), easing));
}
}
I'll answer your questions on this code if you have any. Have fun!
EDIT:
This part could use more explainations, so let's elaborate a little bit:
if (distanceFromTheCenter > centerZone && (relativeX > 0 ^ mouseQuadrant.x > 0 || relativeY > 0 ^ mouseQuadrant.y > 0)) {
// going toward origin
} else {
// drawing normally
}
The point of this check is to know if the mouse is still in the same quadrant than the "pencil", by which I mean the point where we're drawing.
But what are the "quadrants"? Remember, the user can only draw in 45 degrees lines. Theses lines are defines in relation to the point where the user clicked to draw, which I call "origin":
Which means that the screen is always divided into 4 different "quadrants". Why? Because there is 4 different directions where we can draw. But we don't want the user to have to stick to these exact pixels to be able to draw, do we? We could, but that's not how the algo is working: it poses a pencil on the page and then follows the mouse. So here if the mouse goes up-left from origin, the pencil will draw on the up-left branch of the 45 degrees X lines. Each of these imaginary lines has it's own "part of the screen" where they control where the pencil has the right to draw, which I call "quadrants":
Now with this algorithm we can force the pencil over the 45 degrees lines, but what happens if the mouse goes from one quadrant to another one? I figured out that the pencil should follow, but without breaking the "only drawing in 45 degrees lines" rule, so it has to go through the center before changing quadrant:
There is no big secret here. It's kind of easy to figure the business rules we want to apply:
While the mouse and the pencil are in the same quadrant, follow the mouse's position to draw (but only on the line).
If the mouse is in a different quadrant from the pencil, draw toward the center, then toward the mouse normally.
Which is exactly what we're doing here:
if (mouse and pencil are in different quadrants) {
// draw toward origin
} else {
// draw toward the mouse
}
Then... if it's so simple, why this convoluted code?
(distanceFromTheCenter > centerZone && (relativeX > 0 ^ mouseQuadrant.x > 0 || relativeY > 0 ^ mouseQuadrant.y > 0))
Well, really, it could be written in a waaay easier to read way, but it would be longer. Let's decompose it and see why it's written this way:
My operational logic here go as follow:
As you probably know, point (0,0) is on the upper-left side of the sketch. Most drawing in computer science calculate coordinates this way.
Quadrants exist in relation to the origin point (where the user clicked to start drawing).
Relative coordinates in each quadrant will be either positive or negative. X will be positive if they are to the right of origin. Y will be positive if they are lower in the screen than origin:
If you follow my logic, when relative coordinate of the mouse and pencil aren't both positive or both negative in the same way, it would mean that they are not located in the same quadrant.
So:
distanceFromTheCenter > centerZone => when we're close enough to the center, we can let the pencil switch direction. No need to calculate the rest if the pencil isn't near the center.
relativeX > 0 ^ mouseQuadrant.x > 0 => relativeX is really just pos.x - origin.x. It's where the pencil is in relation to origin. mouseQuadrant "knows" where the mouse is in relation to the origin (it's just diffX and diffY as interpreted for later use, in fact we totally could have used diffX and diffY instead as we just compare if they are positive or negative numbers)
Why the XOR operator if it's so simple? Because of this:
relativeX > 0 ^ mouseQuadrant.x > 0
// is the same thing than this pseudocode:
if (relativeX sign is different than mousequadrant.x's sign)
// and the same thing than this more elaborated code:
!(relativeX > 0 && mouseQuadrant.x > 0) || !(relativeX < 0 && mouseQuadrant.x < 0)
// or, in a better writing:
(relativeX > 0 && mouseQuadrant.x < 0) || (relativeX < 0 && mouseQuadrant.x > 0)
...which is also convoluted and also ugly. So, really, (relativeX > 0 ^ mouseQuadrant.x > 0 || relativeY > 0 ^ mouseQuadrant.y > 0) is just a short hand for:
(!(relativeX > 0 && mouseQuadrant.x > 0) || !(relativeX < 0 && mouseQuadrant.x < 0) || !(relativeY > 0 && mouseQuadrant.y > 0) || !(relativeY < 0 && mouseQuadrant.y < 0))
I hope this just made sense! Have fun!

How do I make text grow then shrink while still keeping the same midpoint?

I'm making a bit of a late father's day present. I need some sort of ____Mode(CENTER) for text. I am trying to make a piece of text expand, then shrink, then expand again, then shrink again, on a loop. However, what I attempt seems to grow and shrink sparatically, making the text move around, and not staying centered. Is there an easy way to do this with text?
Code:
String msg = "Happy Father's Day";
int ts = 50;
float textX = 165;
float textY = 312.5;
float tSize = 50;
boolean flip;
void setup() {
size(800, 600);
}
void draw() {
background(0);
fill(255);
textSize(tSize);
text(msg, textX, textY);
if (flip == false) {
tSize += 0.5;
textX -= 1;
textY -= 1;
} else if (flip == true) {
tSize -= 0.5;
textX += 1;
textY += 1;
}
if (tSize == 35) flip = false;
else if (tSize == 65) flip = true;
}
Rather than constantly modifying textX and textY, you can use textAlign if you want to keep the text centered. In this case, you can simply drop those 2 variables:
String msg = "Happy Father's Day";
int ts = 50;
float tSize = 50;
boolean flip;
void setup() {
size(800, 600);
textAlign(CENTER,CENTER);
}
void draw() {
background(0);
fill(255);
textSize(tSize);
text(msg, width/2, height/2);
if (!flip) {
tSize += 0.5;
} else {
tSize -= 0.5;
}
if (tSize == 35) flip = false;
if (tSize == 65) flip = true;
}
You can streamline your code by making flip a number which is always 1 or -1 rather than a Boolean. This reduces the amount of conditional logic required. Note also how the following code replaced the equality comparisons (==) with inequalities (<= and >=). Something like tSize == 65 does work with steps of size 0.5 (since 0.5 has a finite base-2 expansion) but if you changed 0.5 to e.g. 0.1 to try to make it slower, the value 65 would be skipped over entirely due to floating-point round-off error. Since tSize is declared to be a float, using == with it is asking for trouble.
String msg = "Happy Father's Day";
int ts = 50;
float tSize = 50;
float flip = -1;
void setup() {
size(800, 600);
textAlign(CENTER,CENTER);
}
void draw() {
background(0);
fill(255);
textSize(tSize);
text(msg, width/2, height/2);
tSize += flip * 0.5;
if (tSize <= 35 || tSize >= 65 ) flip *= -1;
}

Sierpinski carpet in processing

So I made the Sierpinski carpet fractal in processing using a Square data type which draw a square and has a function generate() that generates 9 equal squares out of itself and returns an ArrayList of (9-1)=8 squares removing the middle one (it is not added to the returned ArrayList) in order to generate the Sierpinski carpet.
Here is the class Square -
class Square {
PVector pos;
float r;
Square(float x, float y, float r) {
pos = new PVector(x, y);
this.r = r;
}
void display() {
noStroke();
fill(120,80,220);
rect(pos.x, pos.y, r, r);
}
ArrayList<Square> generate() {
ArrayList<Square> rects = new ArrayList<Square>();
float newR = r/3;
for (int i=0; i<3; i++) {
for (int j=0; j<3; j++) {
if (!(i==1 && j==1)) {
Square sq = new Square(pos.x+i*newR, pos.y+j*newR, newR);
rects.add(sq);
}
}
}
return rects;
}
}
This is the main sketch which moves forward the generation on mouse click -
ArrayList<Square> current;
void setup() {
size(600, 600);
current = new ArrayList<Square>();
current.add(new Square(0, 0, width));
}
void draw() {
background(255);
for (Square sq : current) {
sq.display();
}
}
void mousePressed() {
ArrayList<Square> next = new ArrayList<Square>();
for(Square sq: current) {
ArrayList<Square> rects = sq.generate();
next.addAll(rects);
}
current = next;
}
The problem :
The output that I am getting has very thin white lines which are not supposed to be there :
First generation -
Second generation -
Third generation -
My guess is that these lines are just the white background that shows up due to the calculations in generate() being off by a pixel or two. However I am not sure about how to get rid of these. Any help would be appreciated!
Here's a smaller example that demonstrates your problem:
size(1000, 100);
noStroke();
background(0);
float squareWidth = 9.9;
for(float squareX = 0; squareX < width; squareX += squareWidth){
rect(squareX, 0, squareWidth, height);
}
Notice that the black background is showing through the squares. Please try to post this kind of minimal example instead of your whole sketch in the future.
Anyway, there are three ways to fix this:
Option 1: Call the noSmooth() function.
By default, Processing uses anti-aliasing to make your drawings look smoother. Usually this is a good thing, but it can also add some fuzziness to the edges of shapes. If you disable anti-aliasing, your shapes will be more clear and you won't see the artifacts.
Option 2: Use a stroke with the same color as the fill.
As you've already discovered, this draws an outline around the shape.
Option 3: Use int values instead of float values.
You're storing your coordinates and sizes in float values, which can contain decimal places. The problem is, the screen (the actual pixels on your monitor) don't have decimal places (there is no such thing as half a pixel), so they're represented by int values. So when you convert a float value to an int, the decimal part is dropped, which can cause small gaps in your shapes.
If you just switch to using int values, the problem goes away:
size(1000, 100);
noStroke();
background(0);
int squareWidth = 10;
for(int squareX = 0; squareX < width; squareX += squareWidth){
rect(squareX, 0, squareWidth, height);
}

Resources