初探 Processing · 重制版
这是一篇旧文,其中的内容可能已经过时。
See the Pen Stripes by HandsomeOne (@handsomeone) on CodePen.
原 Processing 代码丑,勿作参考
Processing 是一种开源编程语言,专门为电子艺术和视觉交互设计而创建,其目的是通过可视化的方式辅助编程教学,并在此基础之上表达数字创意。Processing 语言建立在 Java 语言的基础之上,但使用简化的语法和图形编程模型。
我在逛 Windows Store 时,发现了一款“精美、优雅如艺术品的”游戏 Strata - Elegant Puzzler。
受它启发,我试图在 Processing 中实现一个,能基于指定的 行数、列数、宽度、边距 和 阴影深度,生成 随机颜色、随机“叠放次序” 的彩带的程序。
生成的图像可以作为平铺图案来使用。
实现方法
彩带的条数等于行数加列数,首先生成这么多种随机颜色以备后用。
将每个交点处视作一个单元,每个单元内有两个互相垂直的彩带碎片,连同两边的阴影一起称作 piece
。根据位置和方向从先前的颜色列表中决定一种颜色,再随机决定它们的叠放次序。
int M = 21;
int N = 5;
int WIDTH = 23;
int MARGIN = 0;
int SHADOW = 0;
void config(int m, int n, int width, int margin, int shadow){
M = m;
N = n;
WIDTH = width;
MARGIN = margin;
SHADOW = shadow;
} // 这个函数留给 processing.js 调用
int SIZE;
int Y_AXIS = -1;
int X_AXIS = 1;
color C1 = color(52, 52, 52, 82);
color C2 = color(52, 52, 52, 1);
color[] C;
class piece {
int I;
int J;
int AXIS;
piece(int i, int j, int axis) {
I = i;
J = j;
AXIS = axis;
}
void display() {
noStroke();
// 用数值方法绕过了判断语句,但牺牲了可读性
// 大意为:
// 若 AXIS == 1(X_AXIS),则颜色为 C[J+M]
// 若 AXIS == -1(Y_AXIS),则颜色为 C[I]
// rect() 部分同理
fill(C[I * (1 - AXIS) / 2 + (J + M) * (1 + AXIS) / 2]);
rect((1 - AXIS) / 2 * MARGIN + SIZE * I, (1 + AXIS) / 2 * MARGIN + SIZE * J, (1 + AXIS) * MARGIN + WIDTH, (1 - AXIS) * MARGIN + WIDTH);
if (AXIS == X_AXIS) {
setGradient(SIZE * I, MARGIN - SHADOW + SIZE * J, SIZE-1, SHADOW, C2, C1, Y_AXIS);
setGradient(SIZE * I, WIDTH + MARGIN + SIZE * J, SIZE-1, SHADOW, C1, C2, Y_AXIS);
} else if (AXIS == Y_AXIS) {
setGradient(MARGIN - SHADOW + SIZE * I, SIZE * J, SHADOW, SIZE-1, C2, C1, X_AXIS);
setGradient(WIDTH + MARGIN + SIZE * I, SIZE * J, SHADOW, SIZE-1, C1, C2, X_AXIS);
}
}
}
void setup() {
SIZE = WIDTH + 2 * MARGIN;
C = new color[M + N];
for (int i = 0; i < M + N; i++) {
C[i] = color(random(0, 255), random(0, 255), random(0, 255));
}
size(SIZE * M, SIZE * N);
for (int i = 0; i < M; i++) {
for (int j = 0; j < N; j++) {
piece pX = new piece(i, j, X_AXIS);
piece pY = new piece(i, j, Y_AXIS);
if (random(-1, 1) < 0) {
// 运行顺序即叠放次序
pX.display();
pY.display();
} else {
pY.display();
pX.display();
}
}
}
onresize();
}
void draw(){}
void mousePressed () {
setup();
}
// setGradient() 参考自 http://processing.org/examples/lineargradient.html
void setGradient(int x, int y, float w, float h, color c1, color c2, int axis) {
noFill();
strokeCap(SQUARE);
if (axis == Y_AXIS) {
for (int i = y; i < y + h; i++) {
float inter = map(i, y, y + h - 1, 0, 1);
color c = lerpColor(c1, c2, inter);
stroke(c);
line(x, i, x + w, i);
}
} else if (axis == X_AXIS) {
for (int i = x; i < x + w; i++) {
float inter = map(i, x, x + w - 1, 0, 1);
color c = lerpColor(c1, c2, inter);
stroke(c);
line(i, y, i, y + h);
}
}
}
嵌入至网页
Processing.js 是 JQuery 的创始人 John Resig 的又一力作。它能将 Processing 代码转换为 Javascript,再借助 HTML5 中的 canvas
元素展现出来。以下是“生成”按钮调用的函数:
document.getElementById('generate').onclick = function () {
var m = +document.getElementById('m').value;
var n = +document.getElementById('n').value;
var width = +document.getElementById('width').value;
var margin = +document.getElementById('margin').value;
var shadow = +document.getElementById('shadow').value;
var pjs = Processing.getInstanceById('stripe');
pjs.config(m, n, width, margin, shadow);
pjs.setup();
};