Processing: Increment a counter when midpoint of ellipses are passed - processing

I've got some code that displays 10 ellipses in random locations on the screen, and a square that descends from the top of the screen to the bottom, at which point it resets back at the top. What I'm trying to do is get a counter to increment when that square passes any of the ellipses (by comparing their y-positions). However, the counter increases rapidly instead of steadily and just doesn't behave desirably in general.
Here's my draw() function. barriers[i][0] stores the x-pos, barriers[i][1] the y-pos obviously.
void draw()
{
background(255);
fill(0);
for(int i = 0; i < barriers.length; i++) {
// Draw barriers
ellipse(barriers[i][0], barriers[i][1], 50, 50);
// Did we pass a barrier? (doesn't work!)
if(y >= barriers[i][0] - 1 && y <= barriers[i][1] + 1) {
counter++;
}
}
// Draw the square
rect(x, y, 25, 25);
// Draw counter alongside square
fill(255, 0, 0);
text(counter, x + 25, y - 5);
// Reset
if(y < height) {
y+=5;
} else {
y = -25;
counter = 0;
}
}
Apologies if the solution is blindingly obvious, but I'm just not seeing the problem here...
Looking forward to some assistance.

Look at this section of code:
if(y >= barriers[i][0] - 1 && y <= barriers[i][1] + 1) {
counter++;
}
The draw() function fires 60 times a second, so this code will be fired 60 times per second. That means that while you're passing a barrier, the counter variable will increment 60 times per second!
Presumably you only want the counter to increase once for each barrier. There are a number of ways to do this. You could have another data structure that keeps track of whether each barrier has already been passed, and then only check barriers that haven't been passed yet. Or you could keep track of the previous positions of the square, and then use that to determine when the square starts passing a barrier.
Think about how you would do this in your head, without a computer. How do you know when the square is passing a circle? How do you, in your head, only count one for each barrier?

Following Kevin's advice, I was able to get it working using an array of booleans which I used to ensure I wasn't incrementing counter more than once:
Full code:
float barriers[][] = new float[10][2];
float x = 400;
float y = -25;
int counter = 0;
boolean barriersChecked[] = {false, false, false, false, false, false, false, false, false, false};
void setup()
{
size(800, 600);
genBarriers();
}
void genBarriers()
{
for (int i = 0; i < barriers.length; i++) {
barriers[i][0] = random(width);
barriers[i][1] = random(height);
}
}
void draw()
{
background(255);
fill(0);
for (int i = 0; i < barriers.length; i++) {
// Draw barriers
ellipse(barriers[i][0], barriers[i][1], 50, 50);
// Did we pass a barrier?
if (barriers[i][1] < y && !barriersChecked[i]) {
counter++;
barriersChecked[i] = true;
}
}
// Draw the square
rect(x, y, 25, 25);
// Draw counter alongside square
fill(255, 0, 0);
text(counter, x + 25, y - 5);
// Reset
if (y < height) {
y+=2;
} else {
y = -25;
genBarriers();
// Reset barriersChecked
for(int i = 0; i < barriersChecked.length; i++) {
barriersChecked[i] = false;
}
}
}
Out of curiosity, is there a more elegant (loopless) way of resetting every element in barriersChecked back to false?
Suggestions of additional improvements would also be greatly appreciated.

Related

Is it possible to split a line as high as the whole screen (from 0 to height) in a line as high as half the screen in Processing?

I need some help with a code for an exam in my university.
What I'm trying to do here is a visual representation of a speech between two people. So the code starts when you press "L" and then works a bit like walkie talkie so when the other person speaks need to push "A", when the word goes back to the first person he needs to press "L" again and so on.
I like the result of the code so far but my professor told me to try something and I'm not able to do it.
He would like to see the coloured lines covering all the screen in vertical and not just a portion of it and when they reach the end of the screen on the right split in two so that the first row that just got created becomes half of the screen and the new one creating in the other half. When the second row finishes and the third row is created the screen must split in 3 and so on.
I tried to achieve this but I messed up the code so I will post here the last version of it working.
I hope you can help in any way, all kind of suggestion are appreciated, thank you!
import processing.sound.*;
AudioIn input;
Amplitude amp;
int y;
int x;
int incY = 141;
color bg = color(255, 0);
color high;
color low;
color mid;
void setup() {
size(1440, 846);
background(bg);
pixelDensity(displayDensity());
input = new AudioIn(this, 0);
input.start();
amp = new Amplitude(this);
amp.input(input);
}
void draw() {
textSize(40);
fill(0);
float volume = amp.analyze();
int lncolor = int(map(volume, 0, 0.05, 0, 3));
noFill();
strokeCap(SQUARE);
//strokeWeight(10);
if (lncolor==0) {
stroke(bg);
}
if (lncolor==1) {
stroke(low);
}
if (lncolor==2) {
stroke(mid);
}
if (lncolor==3) {
stroke(high);
}
if (key == 'a') {
x++;
if (x==width) {
x = 0;
y = y + incY;
}
line(x, y, x, y+incY);
high=color(72, 16, 255);
low= color(179, 155, 255);
mid = lerpColor(low, high, .5);
}
if (key == 'l') {
x++;
if (x==width) {
x = 0;
y = y + incY;
}
line(x, y, x, y+incY);
high=color(255, 128, 16);
low= color(255, 203, 156);
mid = lerpColor(low, high, .5);
}
}
The following code won't solve all of your problems, but does show how to keep splitting the screen into proportionate rectangles based on the number of times the graph exceeds the width of the screen. The advancing green bar at the top is where your current signal would be plotted. I'll leave it to you to figure out how to get all the old signal into its respective rectangle. I was unable to run the code that you posted; error message was "Audio Input not configured in start() method". All that I saw was a blank screen.
int x = 0;
int counter = 1;
void rectGrid(int t, int w, int h) {
int top;
for (int k = 0; k < counter; k++) {
top = t + k*h;
stroke(0);
strokeWeight(1);
fill(random(255));
rect( 0, top, w, h);
}
}
void setup() {
size(400, 400);
background(209);
}
void draw() {
fill(0, 255, 0);
rect(0, 0, x++, height/counter);
if (x == width) {
counter++;
println("count = ", counter + " : " + "height = ", height/counter);
x = 0;
background(209);
rectGrid(0, width, height/counter);
}
}

How to control how many times something is shown in Processing?

void setup() {
background(0);
fullScreen();
}
void draw() {
int g = 0;
float cCount = map(mouseY, 0, height, 1, 20);
for (int i = 0; i < width; i+=50) {
while(g < cCount) {
circle(i, mouseY, 20);
}
}
}
So what I'm trying to do is change the number of times circles are shown on the screen as I move the mouse. When the mouse moves down, more circles are shown on the screen all with the same Y coordinate but the distance between each circle is 50. As I move the mouse up, less circles are shown. Max circles is 20 and min is 1. I don't know how to set up a way for the number of circles to change as I move the mouse?
I think your approach is correct, but your code has some bugs that are not related to the problem itself.
In your while (g < cCount) loop, neither g nor cCount is updated, resulting in an infinite loop, but you don't really need that while loop anyway.
The following should work (but I haven't checked running the code myself, so it might have some bugs.
void draw() {
int circleCount = round(map(mouseY, 0, height, 1, 20));
for (int i = 0; i < circleCount; i+=1) {
circle(i*50, mouseY, 20);
}
}

Hold noLoop() for certain amount of time

I'm attempting to create a very simple "whack-a-mole" type game, designed for students new to p5.js, and Processing in general.
Currently, I've created an array, and a random search within that array that randomly picks a square and makes it brown (a "mole", for now).
How do I make it so that after selecting a square, it stays there for a couple seconds, and then jumps to the next one, using basic p5?
I've managed to implement noLoop(), which can stop the search, but after a certain time I want it to resume.
Here's the code I have so far:
function setup() {
createCanvas(610,610)
}
function draw() {
var grid = []
for (var x = 0; x < 6; x += 1){
grid[x]=0;
for (var y = 0; y < 6; y += 1){
rand=round(random(360))
grid[x][y]=0
if (rand==0){
grid[x]=1
grid[y]=1
noLoop()
}
if (grid[x]==0 || grid[y]==0){
fill(76,153,0)
rect((x*100+10),(y*100+10),90,90)
}
if (grid[x]>0 && grid[y]>0){
fill(102,51,0)
rect((x*100+10),(y*100+10),90,90)
}
}
}
}
Instead of using noLoop(), you could keep looping at 60 frames per second, but then use the millis() function to keep track of the elapsed time.
Here's an example that shows a circle for 1 second whenever the user clicks:
var clickTime;
function mousePressed(){
clickTime = millis();
}
function draw() {
background(0);
if(millis() < clickTime + 1000){
ellipse(width/2, height/2, width/4, height/4);
}
}
Edit: Another approach is to use the % operator along with the frameCount variable in order to do something every X frames. This examples draws a circle in a random position every 60 frames:
function draw() {
if (frameCount % 60 == 0) {
background(0);
ellipse(random(width), random(height), width / 4, height / 4);
}
}

animation of vertical bars using processing

I am basically trying to make a animation of vertical bars across the screen which should be equally spaced and continue until some key is pressed etc.. in the processing.org tool for animation.
I was able to get a kind of animation, but with hard coded values and had to write the same code again and again to generate the animation of bars for the whole frame/screen. I need to make it generic, so that changing the screen width or the size of the bars would not make me change the whole code but just the variables which control the parameters. Below is my code. I have written the code for three vertical bars but that needs to be done for the whole screen..
int a;
int i;
int j;
void setup() {
size(640, 360);
a = width/2;
i = 0;
}
void draw() {
background(51);
//need to avoid these repetitions each time for each bar
rect(a , 0, 25, width);
a = a - 1;
if (a < 0) {
a = width;
}
rect(i= a+50, 0, 25, width);
i = i - 1;
if (i < 0) {
i = width + a;
}
rect(j = i + 50, 0, 25, width);
j = j - 1;
if (a < 0) {
j = width + i;
}
}
It sounds like you're looking for an array.
An array is like a variable, only it can hold multiple values in its indexes. You can then use a for loop to iterate over the array and do stuff based on the values in the array.
Here's an example that uses an array to keep track of the line positions:
float[] linePositions = new float[10];
float lineWidth = 25;
float lineSpacing = 25;
float lineSpeed = 1;
void setup() {
size(640, 360);
for (int i = 0; i < linePositions.length; i++) {
linePositions[i] = width/2 + (lineWidth+lineSpacing)*i;
}
}
void draw() {
background(51);
//loop through the lines
for (int i = 0; i < linePositions.length; i++) {
//draw the line
rect(linePositions[i], 0, lineWidth, width);
//move the line
linePositions[i] -= lineSpeed;
//wrap the line
if ( linePositions[i] < 0) {
linePositions[i] = width;
}
}
}
More info on arrays can be found in the Processing reference.

Changing the Z perspective in processing

I'm fairly new to processing but I am having trouble shifting the z position on one of my line sets.
The x axis lines look as I need it to, but I am basically trying to bring up the Y set of lines so they arent just going downwards but are more linked up with the first set of lines. I hope I'm making sense, It's kind of hard to explain. Thanks!
Edit: Basically what Im trying to make is a tiled floor.
int grid = 80;
void setup() {
size (1024, 900, P3D);
}
void draw() {
int movement = mouseY-500;
background(0);
strokeWeight(2.5);
stroke(100, 255, 0, 60);
//floorx
for (int i = 0; i < width; i+=grid) {
line (i , height/2 , 0, i , height, 5000);
}
//floory
for (int i = 0; i < height; i+=grid) {
line (0, i + height/2, 0, width, i + height/2,0 );
}
}
I think that you want the grid to appear more geometrically correct. To achieve this you need different distances between the horizontal lines.
Try this in your floory part:
grid = 40;
//floory
for (int i = 0; i < height; i+=grid) {
line (0, i + height/2, 0, width, i + height/2, 0 );
grid += 20;
}

Resources