Processing For loop sequence - processing

I am attempting to draw several ellipses in sequence along the y and x axis of the canvas. The dots are drawn at randomised y positions.
I previously had the ellipses drawing at random heights sequentially along the x-axis. However, all ellipses along the y-axis were drawn at once.
for (int x = 0; x < xStep; x++) {
int mh = int(map(noise(offset+(x*0.05)), 0, 1, 0, h));
for (int y = mh; y > mh - 3; y--) {
ellipse(x*diam, y*diam, diam, diam);
}
}
xStep++;
if (xStep > w) {
xStep = 0;
offset = random(1000);
}
I then moved on to add another for loop to try sequence the ellipses along the y-axis as well as the x-axis. So visually each ellipse is drawn one after the other on the y-axis before the next column (x-axis) is drawn. However, using the code below what I get instead is the y and x-axis 'drawing' in sequence but at the same time so visually it does not look like one row completes before the next column is drawn.
//count rows and frames
if (counter > 7) {
counter = 0;
rowCounter++;
}
for (int j=0; j<7; j++) { //set values to match counter
if (j == counter){
for (int x = 0; x < xStep; x++) {
int mh = int(map(noise(offset+(x*0.05)), 0, 1, 0, h));
for (int y = mh; y > mh - 3; y--) {
y=y-j;
ellipse(x*diam, y*diam, diam, diam);
}
}
}
}
xStep++;
counter++;
if (rowCounter > 7) {
rowCounter = 0;
}
if (xStep > w) {
xStep = 0;
offset = random(1000);
}
Or if I try using a conditional for the xStep I only get one row of ellipses drawn.
//count rows and frames
if (counter > 7) {
counter = 0;
rowCounter++;
}
for (int j=0; j<7; j++) { //set values to match counter
if ((j == counter) && (xStep != lastXstep)) {
for (int x = 0; x < xStep; x++) {
int mh = int(map(noise(offset+(x*0.05)), 0, 1, 0, h));
for (int y = mh; y > mh - 3; y--) {
y=y-j;
ellipse(x*diam, y*diam, diam, diam);
xStep=lastXstep;
}
}
}
}
xStep++;
counter++;
if (rowCounter > 7) {
rowCounter = 0;
}
if (xStep > w) {
xStep = 0;
offset = random(1000);
}
Can anyone help point me in the direction of where I am going wrong with the for loop construction?
Thanks.

Keep in mind that every call to the draw() function draws a single frame. Processing is double-buffered, so the screen is not updated until the very end of the draw() function. That's why you're only seeing the end result instead of the in-between steps.
If you want to render the in-between steps, you're going to have to split it up into multiple frames. You'd do that by keeping track of the state of your program in a set of variables, changing those variables over time, and using those variables to draw each frame.
Shameless self-promotion: here is a tutorial on animation in Processing that describes the above approach in greater detail.

Related

How can I make a grid of tiles (that can be rotated randomly) in processing?

I have the following code in Processing that will produce a grid of randomly selected tiles from loaded files:
static int img_count = 6;
PImage[] img;
void setup() {
size(1200, 800);
img = new PImage[img_count];
for (int i = 0; i < img_count; i++) {
img[i] = loadImage("./1x/Artboard " + (i+1) + ".png");
}
}
void draw() {
for (int i = 0; i < 12; i++) {
for (int j = 0; j < 12; j++) {
int rand_index = int(random(img_count));
image(img[rand_index], 100 * i, 100 * j, 100, 100 );
}
}
}
By itself, it almost does what I want:
But I need that every tile be randomly rotated as well, so I tried this:
void draw() {
for (int i = 0; i < 12; i++) {
for (int j = 0; j < 12; j++) {
float r = int(random(4)) * HALF_PI; // I added this
rotate(r); // I added this
int rand_index= int(random(img_count));
image(img[rand_index], 100 * i, 100 * j, 100, 100 );
}
}
}
This second code doesn't act as I intended, as rotate() will rotate the entire image, including tiles that were already rendered. I couldn't find an appropriate way to rotate a tile the way I want, is there any way to rotate the tile before placing it?
You will probably need to translate before rotating.
The order of transformations is important (e.g. translating, then rotating will be a different location than rotation, then translating).
In your case image(img, x, y) makes it easy to miss that behind the scenes it's more like translate(x,y);image(img, 0, 0);.
I recommend:
void draw() {
for (int i = 0; i < 12; i++) {
for (int j = 0; j < 12; j++) {
float r = int(random(4)) * HALF_PI; // I added this
translate(100 * i, 100 * j); // translate first
rotate(r); // I added this
int rand_index= int(random(img_count));
image(img[rand_index], 0, 0, 100, 100 );
}
}
}
(depending on your setup, you might find imageMode(CENTER); (in setup()) handy to rotate from image centre (as opposed to top left corner (default)))

Circles not appearing on Canvas

I'm trying to build a connect4 game with processing, following a tutorial.
What I have so far is here.
The tutorial is here.
I stopped at the 4:05 mark to check my code but I noticed something...I don't know why but circles should pop up when I click but they aren't....can someone help pls? Thanks.
Just in case, here's the code:
int h = 6;
int w = 7;
int bs = 100;
int[][] board = new int[h][w];
int player = 1;
void setup() {
size(700, 600);
ellipseMode(CORNER);
}
int nextSpace(int x){
for (int y = h - 1; y >= 0; y--) if (board[y][x] == 0) return y;
return -1;
}
void mousePressed(){
int x = mouseX / bs;
int y = nextSpace(x);
if (y >= 0){
board[y][x] = player;
player = player == 1 ? 2 : 1;
}
}
void draw() {
for (int j = 0; j < h; j++){
for (int i = 0; i < w; i++){
fill(255);
rect(i * bs, j * bs, bs, bs);
if (board[j][i] > 0){
fill(board[j][i] == 1 ? 255 : 0, board[j][i] == 2 ? 255 : 0, 0);
ellipse(i * bs, j * bs, bs, bs);
}
}
}
}
Next time you have this kind of issue try to use a systematic approach to define where is your bug:
Is your draw() function broken? To check that put something in your board and see if it shows. For example add board[1][1]=1 in your setup() and you'll see a circle appearing so the issue is not in draw()
So if you click on the screen does it update your board as expected? The first thing is to add a simple println("Clicked"); in mousePressed(). Now you see that your click event is working well since the string is shown each time you click, so it must be an issue with how you get your x and y.
Use println(x); and println(y); in mousePressed() to have an idea of your values. You will notice that you don't get integers for x you get decimal number.
And this is your issue: you can not access board[1.543] it doesn't make sense, so you need to keep only the integer part of mouseX / bs. To do that you can use int() like this:
int x = int(mouseX / bs);
And your sketch is now working fine.

How can I create a game where you have to avoid circles with your mouse that move around randomly

I don't know how to make the circles move. I also don't know how to make the game end when the mouse touches a circle.
I already have the circles drawn on screen
for(int i = 0; i < 30; i++){
int x = (int)random(100);
int y = (int)random(100);
ellipse(x,y,25,25);
}
It shows a screen with circles. I need them to move around and have the game end when the mouse touches them.
In order to solve this problem you need to store the values of x and y in two arrays.
Next you need to initialize the arrays with a for loop (like your code).
In the order to have a continuous movement of the circle we add a little step each loop with another for loop.
And then you can calculate the distance between the mouse and each circle.
int[] x;//creation of arrays
int[] y;
int size = 30;
int nbBalls = 20;
void setup() {
size(400, 400);
x = new int [nbBalls];
y = new int [nbBalls];
for(int i=0;i<nbBalls;i++){//initialisation
x[i] = (int)random(400);
y[i] = (int)random(400);
}
}
void draw()
{
background(51);
for(int i = 0; i < nbBalls; i ++)//draw
ellipse(x[i],y[i],size,size);
for(int i = 0; i < nbBalls; i ++) {//move
x[i] = x[i] + (int)random(5)-2;
y[i] = y[i] + (int)random(5)-2;
}
for(int i = 0; i < nbBalls; i ++)//collision test
if(dist(mouseX,mouseY,x[i],y[i])<size)
noLoop();
}

Image rotation algorithm for a square pixel grid

I'm currently working on my own little online pixel editor.
Now I'm trying to add a rotation function.
But I can't quite figure out how to realize it.
Here is the basic query for my pixel grid:
for (var y = 0;y < pixelAmount;y++) {
for (var x = 0;x < pixelAmount;x++) {
var name = y + "x" + x;
newY = ?? ;
newX = ?? ;
if ($(newY + "x" + newX).style.backgroundColor != "rgb(255, 255, 255)")
{ $(name).style.backgroundColor = $(newY + "x" + newX).style.backgroundColor; }
}
}
How do I calculate newY and newX?
How do you rotate a two dimensional array?
from this^ post I got this method (in c#):
int a[4][4];
int n=4;
int tmp;
for (int i=0; i<n/2; i++){
for (int j=i; j<n-i-1; j++){
tmp=a[i][j];
a[i][j]=a[j][n-i-1];
a[j][n-i-1]=a[n-i-1][n-j-1];
a[n-i-1][n-j-1]=a[n-j-1][i];
a[n-j-1][i]=tmp;
}
}
or this one:
int[,] array = new int[4,4] {
{ 1,2,3,4 },
{ 5,6,7,8 },
{ 9,0,1,2 },
{ 3,4,5,6 }
};
int[,] rotated = RotateMatrix(array, 4);
static int[,] RotateMatrix(int[,] matrix, int n) {
int[,] ret = new int[n, n];
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
ret[i, j] = matrix[n - j - 1, i];
}
}
return ret;
}
the first method doesn't use a second array (/matrix) to save memory..
Take a look at this doc (Section 3: Rotating a bitmap with an angle of any value). It walks you through how to do the math and gives you some sample code (C++, but it should be good enough for what you need).
If very quick performance is not of huge importance (which is the case by default), you can consider rotating the picture clockwise by flipping it against the main diagonal and then horizontally. To rotate counterclockwise, flip horizontally, then against the main diagonal. The code is much simpler.
For diagonal flip you exchange the values of image[x,y] with image[y,x] in a loop like this
for( var x = 0; x < pixelAmount; ++x )
for( var y = x + 1; y < pixelAmount; ++y )
swap(image[x,y],image[y,x]);
For horizontal flip you do something like
for( var y = 0; y < pixelAmount; ++y )
{
i = 0; j = pixelAmount - 1;
while( i < j ) {
swap( image[i,y], image[j,y] );
++i; --j;
}
}

cvDilate/cvErode: How to avoid connection between separated objects?

I would like to separate objects in OpenCv like the following image it shows:
But if I am using cvDilate or cvErode the objects grow together... how to do that with OpenCv?
It looks like you will need to write your own dilate function and then add xor functionality yourself.
Per the opencv documentation, here is the rule that cvdilate uses:
dst=dilate(src,element): dst(x,y)=max((x',y') in element))src(x+x',y+y')
Here is pseudocode for a starting point (this does not include xor code):
void my_dilate(img) {
for(i = 0; i < img.height; i++) {
for(j = 0; j < img.width; j++) {
max_pixel = get_max_pixel_in_window(img, i, j);
img.pixel(i,j) = max_pixel;
}
}
}
int get_max_pixel_in_window(img, center_row, center_col) {
int window_size = 3;
int cur_max = 0;
for(i = -window_size; i <= window_size; i++) {
for(j = -window_size; j <= window_size; j++) {
int cur_col = center_col + i;
int cur_row = center_row + j;
if(out_of_bounds(img, cur_col, cur_row)) {
continue;
}
int cur_pix = img.pixel(center_row + i, center_col + j);
if(cur_pix > cur_max) {
cur_max = cur_pix;
}
}
}
return cur_max;
}
// returns true if the x, y coordinate is outside of the image
int out_of_bounds(img, x, y) {
if(x >= img.width || x < 0 || y >= img.height || y <= 0) {
return 1;
}
return 0;
}
As far as I know OpenCV does not have "dilation with XOR" (although that would be very nice to have).
To get similar results you might try eroding (as in 'd'), and using the eroded centers as seeds for a Voronoi segmentation which you could then AND with the original image.
after erosion and dilate try thresholding the image to eliminate weak elements. Only strong regions should remain and thus improve the object separation. By the way could you be a little more clear about your problem with cvDilate or cvErode.

Resources