Franchesca 的建议很好。您应该知道原点在哪里以及您应用的坐标空间变换如何影响它,至少在您感觉到它并完全控制之前。
我也热烈推荐这个Processing tutorial on 2d transformations
现在,回到你的代码 :)
您可以改进的第一件事是习惯 for 循环和数组。
一开始它们可能看起来很吓人,但一旦你掌握了它们的窍门,它们就很容易了。
只要您能想到需要重复的情况,您都可以使用 for 循环让您的生活更轻松。
在您的情况下,可以使用循环和数组来生成三角形并存储它们。
For 循环的语法如下:
for keyword (3 elements: a start point,an end point(condition) and an increment,(separated by the ; character)
假设您想一次一步从 a(0) 移动到 b(10):
for(int currentPos = 0 ; currentPos < 10; currentPos++){
println("step: " + currentPos);
}
如果你会走路,你也可以跳过:)
for(int currentPos = 0 ; currentPos < 10; currentPos+=2){
println("step: " + currentPos);
}
如果你愿意,甚至可以倒退:
for(int currentPos = 10 ; currentPos > 0; currentPos--){
println("step: " + currentPos);
}
这在遍历各种数据(场景中的三角形、三角形中的顶点等)时非常有用
您如何组织数据?你把它放在一个列表或数组中。
数组包含相同类型的元素并具有固定的长度。
声明数组的语法如下:
ObjectType[] nameOfArray;
你可以初始化一个空数组:
int[] fiveNumbers = new int[5];//new keyword then the data type and length in sq.brackets
或者你可以用值初始化数组:
String[] words = {"ini","mini","miny","moe"};
您可以使用方括号和要访问的列表中对象的索引来访问数组中的元素。数组具有长度属性,因此您可以轻松计算对象。
background(255);
String[] words = {"ini","mini","miny","moe"};
for(int i = 0 ; i < words.length; i++){
fill(map(i,0,words.length, 0,255));
text(words[i],10,10*(i+1));
}
现在回到你原来的问题。
这是使用 for 循环和数组简化的主要代码:
//Declare
int numTri = 6;//number of triangles
tri[] triangles = new tri[numTri];//a list/an array of tri objects (currently empty)
float angleIncrement = TWO_PI/numTri;
float radius = 100;
void setup() {
size(600, 600);
smooth();
//Initialise
for(int i = 0 ; i < numTri; i++){
triangles[i] = new tri();//allocate/initialise each tri object into it's 'slot' in the list/array
}
}
void draw() {
background(0);
translate(width * .5, height * .5);//move everything to the centre
for(int i = 0 ; i < numTri; i++){
pushMatrix();
rotate(angleIncrement * i);//rotate from the last offset(centre)
translate(radius,0);//move on (rotated) X axis away from the centre
triangles[i].run();
popMatrix();
}
}
void drawAxes(int size){
pushStyle();
stroke(255,0,0);
line(0,0,size,0);
stroke(0,255,0);
line(0,0,0,size);
popStyle();
}
请注意,我在 push/pop matrix 调用中缩进了代码。
这不是必需的,但我已经添加了这一点,因此您可以了解坐标空间是如何嵌套的。
这些调用非常有用,因为它们为您处理幕后的细节数学部分。请注意我是如何在不使用极坐标到笛卡尔转换公式(cos(angle) * radius, sin(angle) * radius)的情况下将符号放在一个圆圈中的。
您可以使用其他选项卡中的此代码进行测试:
class tri {
//Variables
float ax, ay, bx, by, cx, cy; //triangle point coordinates
float theta; //triangle angle
float pi = PI; //pi reference
//Construct
tri() {
theta = PI/6;
ax = 0;
ay = 0;
bx = -50*(sin(theta));
by = +50*(cos(theta));
cx = +50*(sin(theta));
cy = +50*(cos(theta));
}
//Functions
void run() {
pushMatrix();
revolve(); //revolve triangle about centre
// pulse(); //move triangle in/out
display(); //show triangle
popMatrix();
}
void revolve() {
translate(-2*by, 0);
float angle = millis()*0.005;
float cos = cos(angle);
float sin = sin(angle);
ax = ax + 2*sin;
ay = ay + 4*cos;
bx = bx + 2*sin;
by = by + 4*cos;
cx = cx + 2*sin;
cy = cy + 4*cos;
translate(2*by, 0);
}
void pulse() {
ay = ay + 5*sin(millis()*0.005);
by = by + 5*sin(millis()*0.005);
cy = cy + 5*sin(millis()*0.005);
}
void display() {
fill(255);
strokeWeight(0.8);
triangle(ax, ay, bx, by, cx, cy);
}
}
还请注意,我添加了一个 drawAxes 函数。这只是一个实用程序,可以让您更容易理解您的绘图在哪个坐标空间中。
再次回到数组和 for 循环,这里是您的代码的修改版本:
class tri {
//Variables
float ai = TWO_PI/3;//angle increment
float r = 50;
float sr = r * 1.5;//spin radius
float vt = 5;//vertical translation(for pulse)
PVector[] verts = new PVector[3];
boolean rotateAroundCentre = true;
boolean translateAroundCentre = false;
boolean translateVertically = false;
//Construct
tri() {
for(int i = 0 ; i < 3; i++){
verts[i] = new PVector(cos(ai * i) * r,sin(ai * i) * r);
}
}
//Functions
void run() {
pushMatrix();
float angle = millis()*0.0005;
if(rotateAroundCentre) rotate(angle);
if(translateVertically) translate(sin(angle)*vt,0);
if(translateAroundCentre){
// translate(cos(angle) * sr,sin(angle) * r);
// or
rotate(angle);
translate(sr,0);
}
display(); //show triangle
popMatrix();
}
void display() {
fill(255);
strokeWeight(0.8);
triangle(verts[0].x, verts[0].y, verts[1].x, verts[1].y, verts[2].x, verts[2].y);
drawAxes(10);
}
}
您可以随意使用 boolean rotateAroundCentre、translateAroundCentre、translateVertically 变量,玩转坐标和几何图形:)
例如,这是一个草图版本,您可以使用键盘上的 1/2/3 键切换上述 3 个选项:
//Declare
int numTri = 6;//number of triangles
tri[] triangles = new tri[numTri];//a list/an array of tri objects (currently empty)
float angleIncrement = TWO_PI/numTri;
float radius = 100;
boolean[] options = {false,false,false};
void setup() {
size(600, 600);
smooth();
//Initialise
for(int i = 0 ; i < numTri; i++){
triangles[i] = new tri();//allocate/initialise each tri object into it's 'slot' in the list/array
}
}
void draw() {
background(0);
translate(width * .5, height * .5);//move everything to the centre
for(int i = 0 ; i < numTri; i++){
pushMatrix();
rotate(angleIncrement * i);//rotate from the last offset(centre)
translate(radius,0);//move on (rotated) X axis away from the centre
drawAxes(20);
triangles[i].run();
popMatrix();
}
}
void drawAxes(int size){
pushStyle();
stroke(255,0,0);
line(0,0,size,0);
stroke(0,255,0);
line(0,0,0,size);
popStyle();
}
void keyReleased(){
for(int i = 0 ; i < 3; i++) if(key == (49+i)) options[i] = !options[i];//quick'n'dirty option toggling
for(int i = 0; i < numTri; i++) {
triangles[i].rotateAroundCentre = options[0];
triangles[i].translateAroundCentre = options[1];
triangles[i].translateVertically = options[2];
}
}
class tri {
//Variables
float ai = TWO_PI/3;//angle increment
float r = 50;
float sr = r * 1.5;//spin radius
float vt = 5;//vertical translation(for pulse)
PVector[] verts = new PVector[3];
boolean rotateAroundCentre = false;
boolean translateAroundCentre = false;
boolean translateVertically = false;
//Construct
tri() {
for(int i = 0 ; i < 3; i++){
verts[i] = new PVector(cos(ai * i) * r,sin(ai * i) * r);
}
}
//Functions
void run() {
pushMatrix();
float angle = millis()*0.0005;
if(rotateAroundCentre) rotate(angle);
drawAxes(30);
if(translateVertically) translate(sin(angle)*vt,0);
drawAxes(40);
if(translateAroundCentre){
// translate(cos(angle) * sr,sin(angle) * r);
// or
rotate(angle);
drawAxes(40);
translate(sr,0);
}
display(); //show triangle
popMatrix();
}
void display() {
fill(255);
strokeWeight(0.8);
triangle(verts[0].x, verts[0].y, verts[1].x, verts[1].y, verts[2].x, verts[2].y);
drawAxes(10);
}
}