趣味编程指南(5-2)-程序的流程控制-循环语句2
本帖最后由 kaka 于 2017-8-18 08:25 编辑继续上一节的内容
制造简单笔刷 再回到 for 循环。前面例举的示例都是没有交互的,要让结果更有趣可不能忘记将 mouseX,mouseY 结合到代码中。
--代码示例(5-10):
void setup(){
size(700, 700);
background(255);
noStroke();
}
void draw(){
for(int i = 0; i < 1000; i++){
fill(0, 30);
float x = mouseX + random(-50, 50);
float y = mouseY + random(-50, 50);
ellipse(x, y, 2, 2);
}
}
一个“散点”笔刷就诞生了。由于每个细密的圆点坐标都是基于鼠标位置,往左右上下四个方向随机移动有限的距离,所以笔刷最终的形状分布就会近似于方形。
--代码示例(5-11):
void setup(){
size(700, 700);
background(255);
noStroke();
}
void draw(){
for(int i = 0; i < 1000; i++){
float ratio = mouseX/(float)width;
float x = mouseX + random(-50, 50);
float y = mouseY + random(-50, 50);
fill(0, ratio * 255, 255 * (1 - ratio), 30);
ellipse(x, y, 2, 2);
}
}
若是用 mouseX 的值来影响填充颜色,会得到更迷幻的色彩渐变
for 循环的嵌套 for 循环是可以嵌套的。可以在 for 循环里面再写一个 for 循环。当你需要绘制二维的矩阵就可以采取这种写法。
--代码示例(5-12):
void setup(){
size(700, 700);
background(202, 240, 107);
}
void draw(){
fill(0);
for(int i = 0;i < 5;i++){
for(int j = 0;j < 5;j++){
float x = 150 + i * 100;
float y = 150 + j * 100;
ellipse(x, y , 60, 60);
println(i + ":" + j);
}
}
}
初次使用嵌套循环,需要理清其中的逻辑关系。程序中的代码执行顺序始终是由上至下的,因此首先执行的必定是最外层的循环。外循环每执行一次,内循环就要持续执行直到不满足条件为止,此后才执行第二次的外循环。第二次开始后,内循环又会继续从头执行直到条件不满足,如此反复,直到所有条件都不满足,跳出循环为止。
上面的代码,外循环中的循环体一共执行了 5 次,而内循环中的循环体则执行了 25 次。这 25 次中,根据 i ,j 的数值不同,分别用来确定圆的横纵坐标。例子中嵌入了一段 print ,你可以观察输出的数值揣摩其中的变化。仅仅用两个循环嵌套,就能将 i,j 的数值组合都遍历了。
[*]Tips
[*]第二层的 for 循环一般在开头键入 Tab 进行缩进,这样做可以使代码结构更清晰
[*]两层 for 循环中的局部变量必须起不同的变量名。其中,”i”,“j”,“k” 是最为常用的
灵活运用 “i” ,”j” “i”,“j” 这两个变量名指代的是两层 for 循环中的局部变量。下面的例子会加深你对 “i””j” 的理解。根据“i” ,“j” 值的不同,可以传入参数来对元素进行“分组”。
--代码示例(5-13):
void setup() {
size(700, 700);
background(0);
noStroke();
}
void draw() {
background(0);
fill(250, 233, 77);
for (int i = 0; i < 7; i++) {
for (int j = 0; j < 7; j++) {
pushMatrix();
translate(50 + i * 100, 50 + j * 100);
// 设置 1
//float angle = sin(millis() / 1000.0) * PI/2;
// 设置 2
//float ratio = i/7.0;
//float angle = sin(millis() / 1000.0 + ratio * (PI/2)) * PI/2;
// 设置 3
float ratio = (i * 7 + j)/49.0;
float angle = sin(millis() / 1000.0 +ratio * (PI/2)) * PI/2;
rotate(angle);
rectMode(CENTER);
// 绘制图形 1
rect(0, 0, 80, 80);
// 绘制图形 2
// rect(0, 0, 100, 20);
// 绘制图形 3
//rect(0, 0, ratio * 50, ratio * 50);
popMatrix();
}
}
}
代码说明
[*]rectMode(CENTER) 可以改变矩形的绘制方式,原来 rect 的前两个参数是用来确定矩形左上角的坐标。开启此命令后,这两个参数会用于设定矩形中心的坐标。由于这里是通过 rotate 来对图形进行旋转操作的,所以就需要通过这种方式,将矩形的中心绘制到坐标原点上。
[*]millis() 获取的是程序从运行到当前所经过的时间,单位是毫秒。此值会影响 sin 输出值的变化速度,若直接写 millis ,变化幅度则太大,因此将它除以 1000.0
这段代码中运用注释符 “//” 隐藏了多个设置。你可以通过开启或是关闭去快速地切换效果。例如开启了 “设置 3” 后的语句,就需要把 “设置 1” 和 “设置 2” 后的代码块用注释符关闭掉。对于这类程序结构相似而局部代码有所区别的例子,就可以用这种形式去写,这样就无需分别保存多个工程文件了。练习和创作的时候可以多运用这种技巧,以此来保存一些自己满意的参数设置。
其中 i,j 值对程序的影响,主要通过切换 “设置1(设置2)(设置3)” 来体现。可以对比下面的输出结果
绘制图形 1:设置 1
绘制图形 1:设置 2
绘制图形 1:设置 3
绘制图形 2:设置 1
绘制图形 2:设置 2
绘制图形 2:设置 3
在设置 1 中,没有使用到 i 或 j 去影响每个元素的旋转角度。因此可以看到每个元素的运动效果都是一致的。而设置 2 用到了 i 值,设置 3 同时用到了 i 和 j。它们最终通过 ratio 值去影响 sin 函数的参数输入,以此改变 angle 的周期变化。由于设置 2 与设置 3 的具体效果在动图中并不明显,我们可以通过下面的截图去观察。
绘制图形2( 左图:设置2 - 右图:设置3 )
绘制图形3( 左图:设置2 - 右图:设置3 )
第一张图中,ratio 用于影响矩形的旋转角度。而第二张图,则直接用来控制圆形的半径大小。可以看到,只使用了 i 值的语句:
float ratio = i/7.0;
它的纵向元素的变化都是完全一致,因为控制图形横坐标的只依赖 i 值,所以横坐标相同的图形,ratio 的值也相同,旋转角度,圆的半径大小也相同。
而同时用到 i,j 的语句
float ratio = (i * 7 + j)/49.0;
它可以描述“渐变”,这里通过相乘一个系数的方式,将行与列的影响组合到了一起。使每个元素都有所区别。
While 循环 for 循环还有一个兄弟。那就是 while 循环。for 循环能做的事,while 循环也能做。只是 while 循环的在 creativeCoding 中的使用频率并没有 for 循环高。
--代码示例(5-14):
void setup(){
int a = 0;
while(a < 10){
println(a);
a++;
}
}
while 的语法结构其实比 for 更好理解。while 语句的前面先创建变量,接着中括号内填写一个表达式,当满足时就执行循环体中的语句,最后在循环体内放上一个对变量进行更新的表达式,这样 while 循环就完成了。对于循环次数确定的,多用 for 循环。当变量的数值不确定时,更推荐使用 while 循环。转自www.inslab.cn
请问如何把动画效果输出成可以直接运行的程序或文件? gray6666 发表于 2017-3-22 08:53
请问如何把动画效果输出成可以直接运行的程序或文件?
有个打包发布的功能 kaka 发表于 2017-3-27 09:14
有个打包发布的功能
找到个生成EXE的功能,转GIF的功能模块如何用 ? gray6666 发表于 2017-3-29 14:33
找到个生成EXE的功能,转GIF的功能模块如何用 ?
转GIF需要把每一帧保存下来,然后自己做,也有一个库,欢迎继续关注,我后面会介绍 kaka 发表于 2017-3-29 17:37
转GIF需要把每一帧保存下来,然后自己做,也有一个库,欢迎继续关注,我后面会介绍 ...
继续关注,感谢回复 你好,想问一下,在for循环里是不是能不能加“-”减号的,比如“for (int y=90;y<100;y-=1)”这样是错的?
页:
[1]