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)))
Related
I have this for() loop where I am randomizing the selection of slices of a picture, to display 16 slices of an image in a random order.
I'm picking those slices from an array and I have a variable that picks up what slice is going to be selected in the array.
The problem being that I'd think that the random function would be triggered for every frame, but it's triggered only once.
Here's the code :
void setup() {
size(720,720);
slices = new PImage[16];
slices[0] = loadImage("1.png");
slices[1] = loadImage("2.png");
slices[2] = loadImage("3.png");
slices[3] = loadImage("4.png");
slices[4] = loadImage("5.png");
slices[5] = loadImage("6.png");
slices[6] = loadImage("7.png");
slices[7] = loadImage("8.png");
slices[8] = loadImage("9.png");
slices[9] = loadImage("10.png");
slices[10] = loadImage("11.png");
slices[11] = loadImage("12.png");
slices[12] = loadImage("13.png");
slices[13] = loadImage("14.png");
slices[14] = loadImage("15.png");
slices[15] = loadImage("16.png");
frameRate(1);
}
void draw() {
for (int a = 0; a < 16; a++){
int rand = int(random(slices.length));
image(slices[rand],x,y,size,size);
x += size;
if (a % 4 == 3){
y += size;
x = 0;
}
}
It's dispalying the randomized slices only once and then I end up with a fix image. What I'd like to have is random slices appearing at every frame.
Thanks for your help !
You have 2 problems in your code.
First, you may not want to choose a random index.
This is because the same image could be chosen twice.
Instead, you could shuffle the array before drawing the images, like this:
for (int i = slices.length; i > 1; i--) {
//choose a random index for the i-th element to be swapped with
int j = (int)random(i);
//swap them
PImage temp = slices[j];
slices[j] = slices[i-1];
slices[i-1] = temp;
}
Second, the index is chosen on every frame, and the images are drawn, too, but you can't see it, because your code never resets y back to 0, meaning that they are below the screen.
You can fix this by adding
y = 0;
to the top or bottom of your draw().
Could it be because you've forgot to clear the screen (e.g. calling background()) (meaning once you've drawn an image it will stay rendered) ?
You could also make use of the for loop in setup to avoid repeating yourself:
int numSlices = 16;
PImage[] slices = new PImage[numSlices];
float x, y;
float size = 180;
void setup() {
size(720, 720);
for(int i = 0 ; i < numSlices; i++){
slices[i] = loadImage((i+1) + ".png");
}
frameRate(1);
}
void draw() {
background(255);
for (int a = 0; a < numSlices; a++) {
int rand = int(random(numSlices));
image(slices[rand], x, y, size, size);
x += size;
if (a % 4 == 3) {
y += size;
x = 0;
}
}
y = 0;
}
Additionally you could easily format your code (via CMD+T on OSX or Ctrl+T on Windows/Linux)
Update Kamakura (+1) correctly pointing out y not being reset to 0.
As a distraction I though't point you to IntList's shuffle() method:
int numSlices = 16;
PImage[] slices = new PImage[numSlices];
float x, y;
float size = 180;
IntList indices = new IntList();
void setup() {
size(720, 720);
for(int i = 0 ; i < numSlices; i++){
slices[i] = loadImage((i+1) + ".png");
indices.append(i);
}
frameRate(1);
}
void draw() {
background(255);
// shuffle list
indices.shuffle();
// reset y
y = 0;
for (int a = 0; a < numSlices; a++) {
int rand = indices.get(a);
image(slices[rand], x, y, size, size);
x += size;
if (a % 4 == 3) {
y += size;
x = 0;
}
}
}
Extra reason to play with it, other than a learning experience is that fact that it will be unlikely to get the same random index repeated.
Regarding splicing/shuffling, here's a modified version of the Load and Display example:
/**
* Load and Display
*
* Images can be loaded and displayed to the screen at their actual size
* or any other size.
*/
PImage img; // Declare variable "a" of type PImage
// shuffled image
PImage imgShuffled;
// list of indices to shuffle
IntList shuffleIndices = new IntList();
// configure image slicing rows/columns
int rows = 4;
int cols = 4;
// total sections
int numSections = rows * cols;
// image section dimensions
int sectionWidth;
int sectionHeight;
void setup() {
size(640, 360);
frameRate(1);
// The image file must be in the data folder of the current sketch
// to load successfully
img = loadImage("https://processing.org/examples/moonwalk.jpg"); // Load the image into the program
// calculate section dimensions
sectionWidth = img.width / cols;
sectionHeight = img.height / rows;
// allocate a separate image to copy shuffled pixels into
imgShuffled = createImage(img.width, img.height, RGB);
// populate image section indices
for(int i = 0 ; i < numSections; i++){
shuffleIndices.append(i);
}
}
void shuffleImage(){
// shuffle the list
shuffleIndices.shuffle();
// Ta-da!
println(shuffleIndices);
// loop through each section
for(int i = 0 ; i < numSections; i++){
// index to row, col conversion
int srcCol = i % cols;
int srcRow = i / cols;
// convert to pixel coordinates to copy from
int srcX = srcCol * sectionWidth;
int srcY = srcRow * sectionHeight;
// get random / shuffled index
int index = shuffleIndices.get(i);
// same row, col, to pixel conversion to copy to
int dstCol = index % cols;
int dstRow = index / cols;
int dstX = dstCol * sectionWidth;
int dstY = dstRow * sectionHeight;
// copy from original image to shuffled pixel coordinates
imgShuffled.copy(img,srcX,srcY,sectionWidth,sectionHeight,dstX,dstY,sectionWidth,sectionHeight);
}
}
void draw() {
shuffleImage();
// Displays the image at its actual size at point (0,0)
image(imgShuffled, 0, 0);
}
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();
}
I need an !effective! algorithm to smooth a line renderer (basically, the given Vector3 which holds the points of the renderer)
something like that
Here is my code, but the fps with it is very low:
public static List<Vector3> MakeSmoothCurve(Vector3[] arrayToCurve, float smoothness)
{
List<Vector3> points;
List<Vector3> curvedPoints;
int pointsLength = 0;
int curvedLength = 0;
if (smoothness < 1.0f) smoothness = 1.0f;
pointsLength = arrayToCurve.Length;
curvedLength = (pointsLength * Mathf.RoundToInt(smoothness)) - 1;
curvedPoints = new List<Vector3>(curvedLength);
float t = 0.0f;
for (int pointInTimeOnCurve = 0; pointInTimeOnCurve < curvedLength + 1; pointInTimeOnCurve++)
{
t = Mathf.InverseLerp(0, curvedLength, pointInTimeOnCurve);
points = new List<Vector3>(arrayToCurve);
for (int j = pointsLength - 1; j > 0; j--)
{
for (int i = 0; i < j; i++)
{
points[i] = (1 - t) * points[i] + t * points[i + 1];
}
}
curvedPoints.Add(points[0]);
}
return (curvedPoints);
}
You can use a CurveField
https://docs.unity3d.com/ScriptReference/EditorGUILayout.CurveField.html
With that you can easily edit/test your curve and retrieve a point at given time.
https://docs.unity3d.com/ScriptReference/AnimationCurve.Evaluate.html
I have a piece of processing code that I was given, which appears to be setting up a randomized Fourier series. Unfortunately, despite my efforts to improve my mathematical skills, I have no idea what it is doing and the articles I have found are not much help.
I'm trying to extend this code so that I can draw a line tangent to a point on the slope created by the code bellow. The closest I can find to answering this is in the mathematics forum. Unfortunately, I don't really understand what is being discussed or if it really is relevant to my situation.
Any assistance on how I would go about calculating a tangent line at a particular point on this curve would be much appreciated.
UPDATE As of 06/17/13
I've been trying to play around with this, but without much success. This is the best I can do, and I doubt that I'm applying the derivative correctly to find the tangent (or even if I have found the derivative at the point correctly). Also, I'm beginning to worry that I'm not drawing the line correctly even if I have everything else correct. If anyone can provide input on this I'd appreciate it.
final int w = 800;
final int h = 480;
double[] skyline;
PImage img;
int numOfDeriv = 800;
int derivModBy = 1; //Determines how many points will be checked
int time;
int timeDelay = 1000;
int iter;
double[] derivatives;
void setup() {
noStroke();
size(w, h);
fill(0,128,255);
rect(0,0,w,h);
int t[] = terrain(w,h);
fill(77,0,0);
for(int i=0; i < w; i++){
rect(i, h, 1, -1*t[i]);
}
time = millis();
timeDelay = 100;
iter =0;
img = get();
}
void draw() {
int dnum = 0; //Current position of derivatives
if(iter == numOfDeriv) iter = 0;
if (millis() > time + timeDelay){
image(img, 0, 0, width, height);
strokeWeight(4);
stroke(255,0,0);
point((float)iter*derivModBy, height-(float)skyline[iter*derivModBy]);
strokeWeight(1);
stroke(255,255,0);
print("At x = ");
print(iter);
print(", y = ");
print(skyline[iter]);
print(", derivative = ");
print((float)derivatives[iter]);
print('\n');
lineAngle(iter, (int)(height-skyline[iter]), (float)derivatives[iter], 100);
lineAngle(iter, (int)(height-skyline[iter]), (float)derivatives[iter], -100);
stroke(126);
time = millis();
iter += 1;
}
}
void lineAngle(int x, int y, float angle, float length)
{
line(x, y, x+cos(angle)*length, y-sin(angle)*length);
}
int[] terrain(int w, int h){
width = w;
height = h;
//min and max bracket the freq's of the sin/cos series
//The higher the max the hillier the environment
int min = 1, max = 6;
//allocating horizon for screen width
int[] horizon = new int[width];
skyline = new double[width];
derivatives = new double[numOfDeriv];
//ratio of amplitude of screen height to landscape variation
double r = (int) 2.0/5.0;
//number of terms to be used in sine/cosine series
int n = 4;
int[] f = new int[n*2];
//calculating omegas for sine series
for(int i = 0; i < n*2 ; i ++){
f[i] = (int) random(max - min + 1) + min;
}
//amp is the amplitude of the series
int amp = (int) (r*height);
int dnum = 0; //Current number of derivatives
for(int i = 0 ; i < width; i ++){
skyline[i] = 0;
double derivative = 0.0;
for(int j = 0; j < n; j++){
if(i % derivModBy == 0){
derivative += ( cos( (f[j]*PI*i/height) * f[j]*PI/height) -
sin(f[j+n]*PI*i/height) * f[j+n]*PI/height);
}
skyline[i] += ( sin( (f[j]*PI*i/height) ) + cos(f[j+n]*PI*i/height) );
}
skyline[i] *= amp/(n*2);
skyline[i] += (height/2);
skyline[i] = (int)skyline[i];
horizon[i] = (int)skyline[i];
derivative *= amp/(n*2);
if(i % derivModBy == 0){
derivatives[dnum++] = derivative;
derivative = 0;
}
}
return horizon;
}
void reset() {
time = millis();
}
Well it seems in this particular case that you don't need to understand much about the Fourier Series, just that it has the form:
A0 + A1*cos(x) + A2*cos(2*x) + A3*cos(3*x) +... + B1*sin(x) + B2*sin(x) +...
Normally you're given a function f(x) and you need to find the values of An and Bn such that the Fourier series converges to your function (as you add more terms) for some interval [a, b].
In this case however they want a random function that just looks like different lumps and pits (or hills and valleys as the context might suggest) so they choose random terms from the Fourier Series between min and max and set their coefficients to 1 (and conceptually 0 otherwise). They also satisfy themselves with a Fourier series of 4 sine terms and 4 cosine terms (which is certainly easier to manage than an infinite number of terms). This means that their Fourier Series ends up looking like different sine and cosine functions of different frequencies added together (and all have the same amplitude).
Finding the derivative of this is easy if you recall that:
sin(n*x)' = n * cos(x)
cos(n*x)' = -n * sin(x)
(f(x) + g(x))' = f'(x) + g'(x)
So the loop to calculate the the derivative would look like:
for(int j = 0; j < n; j++){
derivative += ( cos( (f[j]*PI*i/height) * f[j]*PI/height) - \
sin(f[j+n]*PI*i/height) * f[j+n]*PI/height);
}
At some point i (Note the derivative is being taken with respect to i since that is the variable that represents our x position here).
Hopefully with this you should be able to calculate the equation of the tangent line at a point i.
UPDATE
At the point where you do skyline[i] *= amp/(n*2); you must also adjust your derivative accordingly derivative *= amp/(n*2); however your derivative does not need adjusting when you do skyline[i] += height/2;
I received an answer to this problem via "quarks" on processing.org form. Essentially the problem is that I was taking the derivative of each term of the series instead of taking the derivative of the sum of the entire series. Also, I wasn't applying my result correctly anyway.
Here is the code that quarks provided that definitively solves this problem.
final int w = 800;
final int h = 480;
float[] skyline;
PImage img;
int numOfDeriv = 800;
int derivModBy = 1; //Determines how many points will be checked
int time;
int timeDelay = 1000;
int iter;
float[] tangents;
public void setup() {
noStroke();
size(w, h);
fill(0, 128, 255);
rect(0, 0, w, h);
terrain(w, h);
fill(77, 0, 0);
for (int i=0; i < w; i++) {
rect(i, h, 1, -1*(int)skyline[i]);
}
time = millis();
timeDelay = 100;
iter =0;
img = get();
}
public void draw() {
if (iter == numOfDeriv) iter = 0;
if (millis() > time + timeDelay) {
image(img, 0, 0, width, height);
strokeWeight(4);
stroke(255, 0, 0);
point((float)iter*derivModBy, height-(float)skyline[iter*derivModBy]);
strokeWeight(1);
stroke(255, 255, 0);
print("At x = ");
print(iter);
print(", y = ");
print(skyline[iter]);
print(", derivative = ");
print((float)tangents[iter]);
print('\n');
lineAngle(iter, (int)(height-skyline[iter]), (float)tangents[iter], 100);
lineAngle(iter, (int)(height-skyline[iter]), (float)tangents[iter], -100);
stroke(126);
time = millis();
iter += 1;
}
}
public void lineAngle(int x, int y, float angle, float length) {
line(x, y, x+cos(angle)*length, y-sin(angle)*length);
}
public void terrain(int w, int h) {
//min and max bracket the freq's of the sin/cos series
//The higher the max the hillier the environment
int min = 1, max = 6;
skyline = new float[w];
tangents = new float[w];
//ratio of amplitude of screen height to landscape variation
double r = (int) 2.0/5.0;
//number of terms to be used in sine/cosine series
int n = 4;
int[] f = new int[n*2];
//calculating omegas for sine series
for (int i = 0; i < n*2 ; i ++) {
f[i] = (int) random(max - min + 1) + min;
}
//amp is the amplitude of the series
int amp = (int) (r*h);
for (int i = 0 ; i < w; i ++) {
skyline[i] = 0;
for (int j = 0; j < n; j++) {
skyline[i] += ( sin( (f[j]*PI*i/h) ) + cos(f[j+n]*PI*i/h) );
}
skyline[i] *= amp/(n*2);
skyline[i] += (h/2);
}
for (int i = 1 ; i < w - 1; i ++) {
tangents[i] = atan2(skyline[i+1] - skyline[i-1], 2);
}
tangents[0] = atan2(skyline[1] - skyline[0], 1);
tangents[w-1] = atan2(skyline[w-2] - skyline[w-1], 1);
}
void reset() {
time = millis();
}
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;
}
}