在这一点上,您可能应该更多地担心学习编程的基础知识,而不是解决问题背后的数学。事实上,现在让我们把数学问题变得超级简单,这样代码就不会变得太复杂:假设你的图案是正方形,而你只对圆心到 ' 中心的距离感兴趣图案'/正方形。
例如, ellipse() 函数只会做一件事 - 将在屏幕上绘制一个椭圆,但您需要一些东西来跟踪您使用的椭圆的属性(如位置和大小)。
跟踪属性的一种方法是将它们存储在数组中:
int numEllipses = 100;
float[] ellipseXValues = new float[numEllipses];
float[] ellipseYValues = new float[numEllipses];
float[] ellipseSizeValues = new float[numEllipses];
//etc.
对于每个属性,您将使用一个数组,因为您将拥有多个椭圆“对象”。模式类似。如果您还不熟悉数组,那么以这种方式做事是一个很好的练习。你会注意到你的代码会很快变得很长,但是当你学习时,代码看起来并不重要:它更多的是理解和跟踪你所做的事情(而不是“咬得比咀嚼的多”)。
另一种方法是使用类。类很酷,因为它们允许您封装与您想到的想法相关的属性和功能。例如,您可以创建自己的Ellipse
类或一个Pattern
类,该类将包含您要使用的属性(如位置、颜色等),但也可以具有函数(如绘制()函数,椭圆将在屏幕上呈现自身)方式,但另一个模式)等等。这是一个例子:
class Circle{
float x,y,vx,vy,size;//store position(x,y), velocity(vx,vy) and size
color clr; //store color
Circle(float ax,float ay,float as,color ac){
x = ax;
y = ay;
size = as;
clr = ac;
vx = random(-.1,.1);//random velocity
vy = random(-.1,.1);
}
void update(int w,int h){
x += vx;//update position based on velocity
y += vy;
if(x < 0 || x > w) vx *= -1;//check bounds and flip velocity if there's a collision
if(y < 0 || y > h) vy *= -1;
}
void draw(){
pushStyle();//start isolating drawing commands
noStroke();
fill(clr);
ellipse(x,y,size,size);
popStyle();//stop isolating drawing commands
}
}
一个类就像一个模板/蓝图——它可以是你想要的任何东西。例如,您可以有一个Vehicle
类,该类具有一个属性,该属性numberOfWheels
确定从该类创建的实例/对象的外观:2 人的自行车,4 人的汽车等。类似地,您可以有一个Pattern
类,它可能具有各种属性/与之相关的变量:条纹/点的数量,颜色列表等。
下面是一个如何使用 Circle 类的基本示例:
Circle c;
void setup(){
size(400,400);
smooth();
c = new Circle(200,200,20,color(192));//create a new object from the template/class using the *new* keyword
}
void draw(){
background(255);
c.x = mouseX;//access and modify properties of the object
c.y = mouseY;
c.size = map(mouseX,0,width,20,200);
c.clr = color(map(mouseY,0,height,0,240));
c.draw();//call a function/method of the object
}
注意定义/类和对象(用new实例化)之间的区别。如果您不熟悉类,请查看Daniel Shiffman的优秀对象教程。在处理中,您可以探索示例 > 基础 > 对象 > 对象。
(不太重要:我正在使用map()函数轻松地将鼠标位置链接到圆的属性,如大小和颜色。)
现在您可以创建自己的类型/类,还可以创建此类对象的数组。Processing 附带一个基本示例:示例 > 基础 > 数组 > ArrayObjects
以下是我们如何在两个单独的数组中一起使用 Circle 类(和一个非常相似的 Square)类并检查距离:
int maxCircles = 20;
int maxSquares = 3;
float minDist = 50;
Circle[] circles = new Circle[maxCircles];//create an array Circle objects/instances
Square[] squares = new Square[maxSquares];
void setup(){
size(400,400);
smooth();
colorMode(HSB,360,100,100);
for(int i = 0; i < maxCircles; i++) circles[i] = new Circle(random(width),random(height),random(4,10),color(0,0,100));
for(int i = 0; i < maxSquares; i++) squares[i] = new Square(random(width),random(height),random(4,10),color(240));
}
void draw(){
background(0,0,95);
for(int i = 0; i < maxCircles; i++){
circles[i].update(width,height);
for(int j = 0; j < maxSquares; j++){
squares[j].update(width,height);
//use the dist() function to compute distances
float distance = dist(circles[i].x,circles[i].y,squares[j].x,squares[j].y);
if(distance < minDist){//based on that, if within a threshold, map colours/etc.
circles[i].clr = color( 0,map(distance,0,minDist,100,0),100);
}
squares[j].draw();
}
circles[i].draw();
}
}
class Circle{
float x,y,vx,vy,size;//store position(x,y), velocity(vx,vy) and size
color clr; //store color
Circle(float ax,float ay,float as,color ac){
x = ax;
y = ay;
size = as;
clr = ac;
vx = random(-.1,.1);//random velocity
vy = random(-.1,.1);
}
void update(int w,int h){
x += vx;//update position based on velocity
y += vy;
if(x < 0 || x > w) vx *= -1;//check bounds and flip velocity if there's a collision
if(y < 0 || y > h) vy *= -1;
}
void draw(){
pushStyle();//start isolating drawing commands
noStroke();
fill(clr);
ellipse(x,y,size,size);
popStyle();//stop isolating drawing commands
}
}
class Square{
float x,y,vx,vy,size;
color clr;
Square(float ax,float ay,float as,color ac){
x = ax;
y = ay;
size = as;
clr = ac;
vx = random(-.02,.02);//random velocity
vy = random(-.02,.02);
}
void update(int w,int h){
x += vx;
y += vy;
if(x < 0 || x > w) vx *= -1;
if(y < 0 || y > h) vy *= -1;
}
void draw(){
pushStyle();
noStroke();
fill(clr);
rect(x-size/2,y-size/2,size,size);
popStyle();
}
}
正如您在注释代码中看到的那样,在对复杂概念进行了某种简化/封装之后,只需循环遍历数组并检查距离(使用dist())。
这是一个快速预览,小方块“假装”成图案并影响其周围圆圈的颜色:
您也可以在线或以下运行代码:
var maxCircles = 20;
var maxSquares = 3;
var minDist = 150;
var circles = new Array(maxCircles);
var squares = new Array(maxSquares);
function setup(){
createCanvas(400,400);
smooth();
colorMode(HSB,360,100,100);
for(var i = 0; i < maxCircles; i++) circles[i] = new Circle(random(width),random(height),random(4,10),color(0,0,100));
for(i = 0; i < maxSquares; i++) squares[i] = new Square(random(width),random(height),random(4,10),color(240));
}
function draw(){
background(0,0,95);
for(var i = 0; i < maxCircles; i++){
circles[i].update(width,height);
for(var j = 0; j < maxSquares; j++){
squares[j].update(width,height);
var distance = dist(circles[i].x,circles[i].y,squares[j].x,squares[j].y);
if(distance < minDist){
circles[i].clr = color( 0,map(distance,0,minDist,100,0),100);
}squares[j].draw();
}
circles[i].draw();
}
}
function Circle(ax,ay,as,ac){
this.x = ax;
this.y = ay;
this.size = as;
this.clr = ac;
this.vx = random(-.1,.1);//random velocity
this.vy = random(-.1,.1);
this.update = function(w,h){
this.x += this.vx;
this.y += this.vy;
if(this.x < 0 || this.x > this.w) this.vx *= -1;
if(this.y < 0 || this.y > this.h) this.vy *= -1;
}
this.draw = function(){
push();
noStroke();
fill(this.clr);
ellipse(this.x,this.y,this.size,this.size);
pop();
}
}
function Square(ax,ay,as,ac){
this.x = ax;
this.y = ay;
this.size = as;
this.clr = ac;
this.vx = random(-.02,.02);//random velocity
this.vy = random(-.02,.02);
this.update = function(w,h){
this.x += this.vx;
this.y += this.vy;
if(this.x < 0 || this.x > this.w) this.vx *= -1;
if(this.y < 0 || this.y > this.h) this.vy *= -1;
}
this.draw = function(){
push();
noStroke();
fill(this.clr);
rect(this.x-this.size/2,this.y-this.size/2,this.size,this.size);
pop();
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.4.4/p5.min.js"></script>
希望这解释了处理该问题的一种基本方法。在您发现自己对语法和一些编程概念感到满意之后,应该更容易深入了解更多内容:
- 您可能会发现数组有些限制,因为它们的大小是固定的,并且可以探索ArrayList
- 您可能会发现基本距离函数对于您的复杂模式不够精确,并且可以找到其他计算距离的方法。
祝你好运