使用 push/popmatrix 和 for 循环旋转正方形
rotate squares with push/popmatrix and for loop
我试图让我的网格中的每个方块随机旋转,所以每个方块都有不同的角度,但我旋转了我所有的方块。
我不明白为什么,因为旋转和矩形在 for 循环内一次绘制一次?
int xStep = 110;
int yStep = 110;
int rectSize = 100;
int marginX = 65;
int marginY = 65;
float rando = (random(55));
void setup() {
size(900, 900);
noStroke();
fill(40);
rectMode(CENTER);
}
void draw() {
background(255);
for (int x=marginX; x<width; x+=xStep) {
for (int y=marginY; y<height; y+=yStep) {
pushMatrix();
rotate(radians(rando));
rect(x, y, rectSize, rectSize, 10);
popMatrix();
}
}
}
使用 pushMatrix()
/popMatrix()
来隔离每个方块的坐标,您走在正确的轨道上。
问题在于 rect()
,因为它“隐藏”了翻译。
这一行:
rotate(radians(rando));
rect(x, y, rectSize, rectSize, 10);
大致相当于:
rotate(radians(rando));
translate(x, y);
rect(0, 0, rectSize, rectSize, 10);
并且(如您在 2D Transformations tutorials 中所见)操作顺序很重要。
在你的情况下,你想先平移,然后旋转(从那个平移的位置):
translate(x, y);
rotate(radians(rando));
rect(0, 0, rectSize, rectSize, 10);
总之,您的代码如下所示:
int xStep = 110;
int yStep = 110;
int rectSize = 100;
int marginX = 65;
int marginY = 65;
float rando = (random(55));
void setup() {
size(900, 900);
noStroke();
fill(40);
rectMode(CENTER);
}
void draw() {
background(255);
for (int x=marginX; x<width; x+=xStep) {
for (int y=marginY; y<height; y+=yStep) {
pushMatrix();
translate(x, y);
rotate(radians(rando));
rect(0, 0, rectSize, rectSize, 10);
popMatrix();
}
}
}
更新
如果你想用不同的随机值旋转每个方块,你需要为每个方块计算一个值。
你可以这样:
int xStep = 110;
int yStep = 110;
int rectSize = 100;
int marginX = 65;
int marginY = 65;
float rando = (random(55));
void setup() {
size(900, 900);
noStroke();
fill(40);
rectMode(CENTER);
}
void draw() {
background(255);
for (int x=marginX; x<width; x+=xStep) {
for (int y=marginY; y<height; y+=yStep) {
rando = random(55);
pushMatrix();
translate(x, y);
rotate(radians(rando));
rect(0, 0, rectSize, rectSize, 10);
popMatrix();
}
}
}
很简单,对吧? Re-calculate值!这里也有一个问题 :)
如果你这样做,随机 re-calculated 不仅是每个方块一次,而且是每帧一次,所以你最终会得到非常不稳定的方块。
那就是你需要一次又一次地 re-draw 相同的方块(即使内容没有改变)。如果你只是想要一个静态图像,你可以跳过 draw()
并只使用 setup()
:
int xStep = 110;
int yStep = 110;
int rectSize = 100;
int marginX = 65;
int marginY = 65;
void setup() {
size(900, 900);
noStroke();
fill(40);
rectMode(CENTER);
background(255);
for (int x=marginX; x<width; x+=xStep) {
for (int y=marginY; y<height; y+=yStep) {
pushMatrix();
translate(x, y);
rotate(radians(random(55)));
rect(0, 0, rectSize, rectSize, 10);
popMatrix();
}
}
}
即使没有 setup()
的“立即模式”也会产生相同的图像:
int xStep = 110;
int yStep = 110;
int rectSize = 100;
int marginX = 65;
int marginY = 65;
size(900, 900);
noStroke();
fill(40);
rectMode(CENTER);
background(255);
for (int x=marginX; x<width; x+=xStep) {
for (int y=marginY; y<height; y+=yStep) {
pushMatrix();
translate(x, y);
rotate(radians(random(55)));
rect(0, 0, rectSize, rectSize, 10);
popMatrix();
}
}
假设您确实需要 draw()
,因为您可能希望使用键盘快捷键或单击鼠标来获得 re-randomise 值。
要绕过限制,您需要为每个方块计算一次随机值,然后在渲染时简单地检索这些值。
这意味着你需要一个结构来存储每个方块的每个随机值,你在 setup()
中写入一次值并在 draw()
中重复读取:数组可以轻松解决你的问题。
由于您使用的是嵌套 for 循环,因此您可以使用二维数组。请记住,循环中的 x,y
计数器是绝对像素坐标,您需要单独的索引来访问数组。这很容易:只需将 x,y
除以像素增量,它就会 'step' 计数器:
int xStep = 110;
int yStep = 110;
int rectSize = 100;
int marginX = 65;
int marginY = 65;
// store random values for each square
float[][]randos;
void setup() {
size(900, 900);
// initialise random array
randos = new float[width / xStep][height / yStep];
for (int x=marginX; x<width; x+=xStep) {
for (int y=marginY; y<height; y+=yStep) {
// calculate array indices
int xIndex = x / xStep;
int yIndex = y / yStep;
// write random values
randos[yIndex][xIndex] = random(55);
}
}
noStroke();
fill(40);
rectMode(CENTER);
}
void draw() {
background(255);
for (int x=marginX; x<width; x+=xStep) {
for (int y=marginY; y<height; y+=yStep) {
// calculate array indices
int xIndex = x / xStep;
int yIndex = y / yStep;
pushMatrix();
translate(x, y);
// read random values
rotate(radians(randos[xIndex][yIndex]));
rect(0, 0, rectSize, rectSize, 10);
popMatrix();
}
}
}
数组也可以是一维的,只是需要不同的计数:
int xStep = 110;
int yStep = 110;
int rectSize = 100;
int marginX = 65;
int marginY = 65;
// store random values for each square
float[] randos;
void setup() {
size(900, 900);
// initialise random array
int numSquares = (width / xStep) * (height / yStep);
randos = new float[numSquares];
int index = 0;
for (int x=marginX; x<width; x+=xStep) {
for (int y=marginY; y<height; y+=yStep) {
randos[index++] = random(55);
}
}
noStroke();
fill(40);
rectMode(CENTER);
}
void draw() {
background(255);
int index = 0;
for (int x=marginX; x<width; x+=xStep) {
for (int y=marginY; y<height; y+=yStep) {
pushMatrix();
translate(x, y);
rotate(radians(randos[index++]));
rect(0, 0, rectSize, rectSize, 10);
popMatrix();
}
}
}
(作为下一步,您可以将使用随机值初始化数组的设置部分封装到一个函数中:这将允许您在再次调用此函数时 reset/recalculate 新的随机值(例如在鼠标上click/key press/etc.)
我试图让我的网格中的每个方块随机旋转,所以每个方块都有不同的角度,但我旋转了我所有的方块。 我不明白为什么,因为旋转和矩形在 for 循环内一次绘制一次?
int xStep = 110;
int yStep = 110;
int rectSize = 100;
int marginX = 65;
int marginY = 65;
float rando = (random(55));
void setup() {
size(900, 900);
noStroke();
fill(40);
rectMode(CENTER);
}
void draw() {
background(255);
for (int x=marginX; x<width; x+=xStep) {
for (int y=marginY; y<height; y+=yStep) {
pushMatrix();
rotate(radians(rando));
rect(x, y, rectSize, rectSize, 10);
popMatrix();
}
}
}
使用 pushMatrix()
/popMatrix()
来隔离每个方块的坐标,您走在正确的轨道上。
问题在于 rect()
,因为它“隐藏”了翻译。
这一行:
rotate(radians(rando));
rect(x, y, rectSize, rectSize, 10);
大致相当于:
rotate(radians(rando));
translate(x, y);
rect(0, 0, rectSize, rectSize, 10);
并且(如您在 2D Transformations tutorials 中所见)操作顺序很重要。
在你的情况下,你想先平移,然后旋转(从那个平移的位置):
translate(x, y);
rotate(radians(rando));
rect(0, 0, rectSize, rectSize, 10);
总之,您的代码如下所示:
int xStep = 110;
int yStep = 110;
int rectSize = 100;
int marginX = 65;
int marginY = 65;
float rando = (random(55));
void setup() {
size(900, 900);
noStroke();
fill(40);
rectMode(CENTER);
}
void draw() {
background(255);
for (int x=marginX; x<width; x+=xStep) {
for (int y=marginY; y<height; y+=yStep) {
pushMatrix();
translate(x, y);
rotate(radians(rando));
rect(0, 0, rectSize, rectSize, 10);
popMatrix();
}
}
}
更新 如果你想用不同的随机值旋转每个方块,你需要为每个方块计算一个值。
你可以这样:
int xStep = 110;
int yStep = 110;
int rectSize = 100;
int marginX = 65;
int marginY = 65;
float rando = (random(55));
void setup() {
size(900, 900);
noStroke();
fill(40);
rectMode(CENTER);
}
void draw() {
background(255);
for (int x=marginX; x<width; x+=xStep) {
for (int y=marginY; y<height; y+=yStep) {
rando = random(55);
pushMatrix();
translate(x, y);
rotate(radians(rando));
rect(0, 0, rectSize, rectSize, 10);
popMatrix();
}
}
}
很简单,对吧? Re-calculate值!这里也有一个问题 :) 如果你这样做,随机 re-calculated 不仅是每个方块一次,而且是每帧一次,所以你最终会得到非常不稳定的方块。
那就是你需要一次又一次地 re-draw 相同的方块(即使内容没有改变)。如果你只是想要一个静态图像,你可以跳过 draw()
并只使用 setup()
:
int xStep = 110;
int yStep = 110;
int rectSize = 100;
int marginX = 65;
int marginY = 65;
void setup() {
size(900, 900);
noStroke();
fill(40);
rectMode(CENTER);
background(255);
for (int x=marginX; x<width; x+=xStep) {
for (int y=marginY; y<height; y+=yStep) {
pushMatrix();
translate(x, y);
rotate(radians(random(55)));
rect(0, 0, rectSize, rectSize, 10);
popMatrix();
}
}
}
即使没有 setup()
的“立即模式”也会产生相同的图像:
int xStep = 110;
int yStep = 110;
int rectSize = 100;
int marginX = 65;
int marginY = 65;
size(900, 900);
noStroke();
fill(40);
rectMode(CENTER);
background(255);
for (int x=marginX; x<width; x+=xStep) {
for (int y=marginY; y<height; y+=yStep) {
pushMatrix();
translate(x, y);
rotate(radians(random(55)));
rect(0, 0, rectSize, rectSize, 10);
popMatrix();
}
}
假设您确实需要 draw()
,因为您可能希望使用键盘快捷键或单击鼠标来获得 re-randomise 值。
要绕过限制,您需要为每个方块计算一次随机值,然后在渲染时简单地检索这些值。
这意味着你需要一个结构来存储每个方块的每个随机值,你在 setup()
中写入一次值并在 draw()
中重复读取:数组可以轻松解决你的问题。
由于您使用的是嵌套 for 循环,因此您可以使用二维数组。请记住,循环中的 x,y
计数器是绝对像素坐标,您需要单独的索引来访问数组。这很容易:只需将 x,y
除以像素增量,它就会 'step' 计数器:
int xStep = 110;
int yStep = 110;
int rectSize = 100;
int marginX = 65;
int marginY = 65;
// store random values for each square
float[][]randos;
void setup() {
size(900, 900);
// initialise random array
randos = new float[width / xStep][height / yStep];
for (int x=marginX; x<width; x+=xStep) {
for (int y=marginY; y<height; y+=yStep) {
// calculate array indices
int xIndex = x / xStep;
int yIndex = y / yStep;
// write random values
randos[yIndex][xIndex] = random(55);
}
}
noStroke();
fill(40);
rectMode(CENTER);
}
void draw() {
background(255);
for (int x=marginX; x<width; x+=xStep) {
for (int y=marginY; y<height; y+=yStep) {
// calculate array indices
int xIndex = x / xStep;
int yIndex = y / yStep;
pushMatrix();
translate(x, y);
// read random values
rotate(radians(randos[xIndex][yIndex]));
rect(0, 0, rectSize, rectSize, 10);
popMatrix();
}
}
}
数组也可以是一维的,只是需要不同的计数:
int xStep = 110;
int yStep = 110;
int rectSize = 100;
int marginX = 65;
int marginY = 65;
// store random values for each square
float[] randos;
void setup() {
size(900, 900);
// initialise random array
int numSquares = (width / xStep) * (height / yStep);
randos = new float[numSquares];
int index = 0;
for (int x=marginX; x<width; x+=xStep) {
for (int y=marginY; y<height; y+=yStep) {
randos[index++] = random(55);
}
}
noStroke();
fill(40);
rectMode(CENTER);
}
void draw() {
background(255);
int index = 0;
for (int x=marginX; x<width; x+=xStep) {
for (int y=marginY; y<height; y+=yStep) {
pushMatrix();
translate(x, y);
rotate(radians(randos[index++]));
rect(0, 0, rectSize, rectSize, 10);
popMatrix();
}
}
}
(作为下一步,您可以将使用随机值初始化数组的设置部分封装到一个函数中:这将允许您在再次调用此函数时 reset/recalculate 新的随机值(例如在鼠标上click/key press/etc.)