Oh!Coder

Coding Life

有趣的Processing-对象

| Comments

今天,我们来面一个对象。哦,如果你认为我们面的是一位姑娘,那可能让你失望了。不过呢,也不用悲观,经过这次学习,即便你没有对象,只要你愿意,我们自己也可以创造无数个对象。神奇么?好!让我们进入正题。

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

为了更好的展示代码,我们新建一个项目窗口。

processing-new-window

图片来源:Processing新项目窗口

然后向窗口中,添加如下代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
// 定义轿车的颜色
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,也就是类。我们定义一个类,也就是定义了一个模具,以后想要多少轿车,就可以用这个模具定制出多少轿车。妙哉吧!好,让我们看看这个类都包括哪些内容,具体怎么定义?

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

tab-new

图片来源:Processing PDE项目窗口

点击上图中箭头向下的图标,弹出目录中,点击New Tab,将此文件命名为Car

将下面代码填入其中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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
2
3
class Car{
  ...
}

第二部分,定义数据。

1
2
3
4
  color c;
  float xpos;
  float ypos;
  float xspeed;

第三部分,定义构造器。

1
2
3
4
5
6
 Car(color tempC, float tempXpos, float tempYpos, float tempXspeed){
    c = tempC;
    xpos = tempXpos;
    ypos = tempYpos;
    xspeed = tempXspeed;
  }

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

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

执行完上面这行代码,构造器会自动被调用,并对类的内部变量数值进行初始化。

第四部分,定义方法

最后一部分就是定义方法,比如Car这个类,一共包括了两个方法,分别是display()drive()。我们举其中一个方法display()为例。

1
2
3
4
5
  void display() {
    rectMode(CENTER);
    fill(c);
    rect(xpos, ypos, 20, 10);
  }

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

好,整个类的四个部分就介绍完了。最后,让我们看下,在程序的主体框架下,对象是如何创建的。

还是此项目,回到主体框架程序。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// 声明轿车变量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()方法分别进行了调用。这里要说的一点是,调用对象的方法需要在对象后面加一个.,然后紧跟方法名。

processing-window-menu

图片来源:Processing新项目窗口中的菜单栏

最后,点击菜单栏上的三角形图标,运行程序,如果一切顺利,将会看到类似于下面的运行效果。

processing-fun-object

图片来源:Processing程序执行结果

看起来还不错,哈!就是轿车简陋了一点,嘻嘻!如果你想要个对象呢?注意,这次我说的可是一个貌美如花的女朋友!那你就可以先定一个貌美如花的姑娘类,然后通过这个类,创建一个女朋友对象,想要多少有多少!嗯,全看你的了。

总结

这次我们学习了什么是类,如何定义一个类,类中都包括了哪些主要部分,每个部分的概念和定义方式,以及通过类,如何在主体框架里创建对象。对于没有太多编程基础的朋友,这次的内容还是不少的,需要好好的消化一下。

下期预告

经过过去几次的学习,我们了解了基本图形的创建,颜色的填充,以及类和对象的创建。下一次,我们将进一步学习,如何与这些基本图形进行交互。

Comments