Processing-对象(class)

Processing 允许使用面向对象编程(OOP)技术来使 Processing 应用程序更易于开发和维护。与其他面向对象的语言一样,Processing 使用 Class 的概念来定义对象模板。

我们先来看一个例子:假设平坦的马路上跑着一辆轿车,轿车的颜色为白色,当前速度为1公里每小时,轿车类型为自动挡。现在我们想在Processing里绘制这样一个场景,如何做呢?

// 定义轿车的颜色
color c;
// 定义轿车的x坐标位置
float xpos;
// 定义轿车的y坐标位置
float ypos;
// 定义轿车的车速
float xspeed;
// 环境初始化。
// 此方法在软件启动时,被系统调用一次。
void setup() {
  // 初始化窗口大小
  size(200, 200);
  // 初始化轿车颜色
  c = color(255);
  // 初始化轿车的x坐标
  xpos = width/2;
  // 初始化轿车的y坐标
  ypos = height/2;
  // 初始化轿车的车速
  xspeed = 1;
}
// 画图。
// 此方法被系统默认循环调用。
void draw() {
  // 设置窗体背景色为黑色
  background(0);
  // 调用display()方法
  display();
  // 调用drive()方法
  drive();
}
// 自定义显示轿车的方法
void display(){
  // 设置轿车的锚定点为矩形中心
  rectMode(CENTER);
  // 设置轿车的颜色
  fill(c);
  // 将轿车画成矩形
  rect(xpos, ypos, 20, 10);
}
// 自定义轿车的制动方法
void drive(){
  // 轿车将在x轴上向前移动,
  // 移动的速度为xspeed
  xpos = xpos + xspeed;
  // 判断轿车是否超出了窗体的右侧,
  // 若超出,则轿车将从窗体左侧重新驶入。
  if(xpos > width){
  // 将轿车的位置重新设置为窗体的左侧
    xpos = 0;
  }
}

上面的这段代码,就是我们通常最先想到的方法。这种方式很显然不太友好,为什么这么说呢?假设我们想要再创建一辆轿车,颜色为红色,速度为2公里每小时,那岂不是还要再定义一遍上面用到的变量?比如,车的颜色为了分别记录两辆车,所以要定义两个color,位置记录也要重新定义一遍,车速的变量也要重新定义一遍。以此类推,要是定义五辆轿车,那就要写五遍同样的变量。嗯,这确实是个问题。那应该怎么办呢?

嗯,这就涉及到今天所要讲的内容,对象。

真实的世界里,每个具体的事物都是对象,某一辆轿车,是一个对象,再一辆轿车,又是一个对象,多辆轿车,就是多个对象,以此类推。如果我们定义一个模具,通过这个模具可以马上定制出,具有不同属性的轿车,那不就方便了么?到那个时候,我们想要多少轿车,就可以很容易的定制出多少轿车。那这个模具,在Processing这里,称之为class,也就是类。我们定义一个类,也就是定义了一个模具,以后想要多少轿车,就可以用这个模具定制出多少轿车。妙哉吧!好,让我们看看这个类都包括哪些内容,具体怎么定义?

一般来说,一个类包括四部分,分别为,类名,数据,构造器,方法。那么,接下来让我们讲上面的示例改造成一个轿车的类,方便我们以后使用。

class Car{
  color c;
  float xpos;
  float ypos;
  float xspeed;

 Car(color tempC, float tempXpos, float tempYpos, float tempXspeed){
    c = tempC;
    xpos = tempXpos;
    ypos = tempYpos;
    xspeed = tempXspeed;
  }

  void display() {
    rectMode(CENTER);
    fill(c);
    rect(xpos, ypos, 20, 10);
  }

  void drive(){
    xpos = xpos + xspeed;
    if (xpos > width) {
        xpos = 0;
    }
  }
}

上面代码中,分别定义数据、定义构造器、定义方法。

1)构造器:

其命名要与类名保持一样,然后会在定义对象的时候,自动调用。除此之外,构造器还可以进行初始化变量。定义一个新的对象,需要用到new关键字,紧接着就是类名,类名后面的括号,可以传入构造器中,括号里定义的参数。比如定义一个新的轿车对象,示例代码如下:

myCar = new Car(color(255, 0, 0), 0, 100, 1);

2)方法:

每个方法都有返回数值,关键字void比较特殊,它定义了此方法可以没有返回值,或者说,返回值可以为空。紧接着,后面的display()为方法名,括号里可以放传入的参数,此处为空。如果方法的返回类型不是void,则需要在方法的最后一行添加一条return语句,return后面有一个空格,然后是需要返回的结果。由于此方法的返回类型为void,所以方法的最后一行的省掉了return语句。

好了,回到项目主体

// 声明轿车变量myCar
Car myCar1;
Car myCar2;
// 环境初始化。
// 此方法在软件启动时,被系统调用一次。
void setup() {
  // 设置窗口
  size(200, 200);
  // 创建myCar对象。
  // 并传入四个参数:
  // tempC = color(255, 0, 0)
  // tempXpos = 0
  // tempYpos = 100
  // tempXspeed = 1
  myCar1 = new Car(color(255, 0, 0), 0, 100, 1);
  // 参见上面myCar1的注释
  myCar2 = new Car(color(0, 255, 0), 0, 150, 1.5);
}
// 画图
// 此方法被系统默认循环调用
void draw() {
  // 设置背景色为黑色
  background(0);
  // 调用myCar1对象的drive()方法
  myCar1.drive();
  // 调用myCar对象的display()方法
  myCar1.display();
  // 调用myCar2对象的drive()方法
  myCar2.drive();
  // 调用myCar2对象的display()方法
  myCar2.display();
}

在上面的主体框架中,创建了两个轿车对象,一个是myCar1,另一个是myCar2。在框架setup中进行创建,并初始化相应参数。在框架draw()方法中,对两个对象的drive()方法和display()方法分别进行了调用。这里要说的一点是,调用对象的方法需要在对象后面加一个.,然后紧跟方法名。

参考:http://ohcoder.com/blog/2016/03/18/processing-fun-object/

最后,我们举一个水滴扩散的例子:

class Drop {
 
  int x, y;     // Coordinate (center of circle)
  int diameter;     // Diameter of circle (unused == 0).
   
  void init( int ix, int iy ) {
   x = ix;
   y = iy;
   diameter = 1;
  }
   
  void spread() {
    if (diameter > 0) diameter += 1;
  }
   
  void show() {
    if (diameter > 0) {
      ellipse( x, y, diameter, diameter );
      if (diameter > 500) diameter = 0;
    }
  }
   
}

现在我们来看一下如何使用 Drop 类来构建一些利用用户输入的图形。清单 4 给出使用 Drop 类的应用程序。第一步是创建一个水滴数组(称为 drops)。之后进行几个定义(drops 数组中的水滴数和工作索引)。在 setup 函数中,您可以创建显示窗口并初始化 drops 数组(所有直径为 0 或未使用)。draw 函数相当简单,因为水滴的核心功能在类本身内部(清单 3 中的 spread 和 show)最后,添加 UI 部分,该部分允许用户定义水滴从何处开始。mousePressed 回调函数通过当前鼠标位置(目前有一个直径且是使用过的)初始化水滴,然后递增当前水滴索引。

Drop[] drops;
int numDrops = 30;
int curDrop = 0;
 
void setup() {
  size(400, 400);
  ellipseMode(CENTER);
  smooth();
  drops = new Drop[numDrops];
  for (int i = 0 ; i < numDrops ; i++) {
    drops[i] = new Drop();
    drops[i].diameter = 0;
  }
}
 
void draw() {
  background(0);
  for (int i = 0 ; i < numDrops ; i++) {
      drops[i].spread();
      drops[i].show();
  }
}
 
void mousePressed() {
  drops[curDrop].init( mouseX, mouseY );
  if (++curDrop == numDrops) curDrop = 0;
}

参考:

https://www.ibm.com/developerworks/cn/opensource/os-datavis2/index.html

猜你喜欢

转载自blog.csdn.net/liuxiao723846/article/details/82051791