本文概述
你在无聊中挣扎, 渴望使用你的创造力。你想要构建一些东西, 一些视觉上令人印象深刻的东西, 一些艺术性的东西。或者, 也许你想学习编程, 并尽快给人留下深刻的印象。如果是这样, 那么Processing语言就是必经之路。
在迄今为止我使用过的所有编程语言中, Processing无疑是最有趣的一种。它是一种简单易懂的语言, 易于学习, 理解和使用, 但功能非常强大。几乎就像你在带有代码行的空画布上绘画一样。没有严格的规则或准则限制你的创造力, 唯一的限制就是你的想象力。

在大学里, 我是一个计划的助教, 该计划聚集了高中学生并教他们Processing程序。他们中的大多数人没有很强的编程背景, 有些人以前甚至没有编写过一行代码。仅仅五天, 他们就有望学习语言并制作自己的简单游戏。成功率几乎是百分之一百, 我们很少面临失败。在本文中, 这正是我们要做的。我将整个程序分为两部分。第一部分, 我将讨论语言。我将提供基本概述, Processing过程的演练, 并提供一些提示和技巧。然后在下一部分中, 我们将逐步构建一个简单的游戏, 将详细解释每个步骤。我还将使用p5js将游戏代码转换为JavaScript, 以便我们的游戏可以在网络浏览器中运行。
你应该已经知道的
要理解并轻松阅读这些文章, 你应该具有编程的基本知识, 因为我不会在此谈论编程基础。我将基本上不涉及任何高级编程概念, 因此将有一个肤浅的理解。在某些部分中, 我谈论了一些低级的思想和概念, 例如面向对象编程(OOP), 但它们并不是至关重要的。这些是针对对语言结构感兴趣的好奇读者的。如果你不想知道, 则可以跳过这些部分。除此之外, 你唯一应该拥有的就是学习这种很棒的语言和创建自己的游戏的热情!
如何遵循
我一直主张通过尝试和尝试来学习编程。你越早投入自己的游戏, 就可以更快地适应”Processing”。因此, 这将是我的第一个建议, 请在你自己的环境中尝试每一个步骤。Processing具有一个简单易用的IDE(即代码编辑器), 这是你唯一需要下载和安装的内容。你可以在这里下载。
因此, 让我们开始吧!
什么是Processing语言?
本节包括对该语言的简要技术概述, 其结构以及有关编译和执行过程的一些说明。详细信息将包括一些有关编程和Java环境的高级知识。如果你暂时不关心细节, 又迫不及待地学习和编写自己的游戏, 则可以跳至”Processing基础知识”部分。
Processing是一种可视化的编程语言, 可以让你用代码进行素描。但是, 它本身并不完全是一种编程语言, 而是所谓的” Java风格”编程语言, 这意味着该语言是建立在Java平台之上的, 但本身并不是Java。它基于Java, 并且在你点击运行按钮时, 所有代码都经过预Processing, 并直接转换为Java代码。 Java的PApplet类是所有Processing草图的基类。举个例子, 让我们看几个基本的Processing代码块:
public void setup() {
// setup codes goes here
}
public void draw() {
// draw codes goes here
}
这些代码块将转换为如下形式:
public class ExampleFrame extends Frame {
public ExampleFrame() {
super("Embedded PApplet");
setLayout(new BorderLayout());
PApplet embed = new Embedded();
add(embed, BorderLayout.CENTER);
embed.init();
}
}
public class Embedded extends PApplet {
public void setup() {
// setup codes goes here
}
public void draw() {
// draw codes goes here
}
}
你会看到Processing代码块包裹着一个从Java的PApplet扩展的类。因此, 你在Processing代码中定义的所有类(如果有)将被视为内部类。
Processing是基于Java的事实为我们提供了很多优势, 特别是如果你是Java开发人员。语法不仅很熟悉, 而且还使你能够执行以下操作:在草图中嵌入Java代码, 库, JAR文件, 在Java应用程序中直接使用Processing小程序, 定义类以及使用标准数据类型(例如int) , float, char等。如果你想花费一些时间来设置它, 甚至可以直接从Eclipse编写Pocessing代码。你无法做的一件事是在Processing草图中使用AWT或Swing组件, 因为它们与Processing的循环特性冲突。但是请放心, 我们不会在本文中做任何花哨的事情。
加工基础
Processing代码包括两个主要部分, 设置和绘制块。当执行代码时, Setup块将运行一次, 而draw块将连续运行。Processing背后的主要思想是, 你在draw块中编写的内容将每秒从上到下执行60次, 直到程序终止。我们将利用这个想法来构建一切。我们将使用此功能使对象运动, 保持分数, 检测碰撞, 实现重力以及执行几乎所有其他操作。此刷新循环是我们项目的心跳。我将在后面的部分中说明如何使用此心跳使你的代码栩栩如生。首先, 让我向你介绍Processing IDE。
Processing IDE

如果你到目前为止已经阅读但仍未下载Processing IDE, 请继续进行。在整篇文章中, 我将概述一些简单的任务供你自己尝试, 只有在IDE正常运行的情况下, 你才可以练习。这是ProcessingIDE的简要介绍。这很简单, 很容易解释, 因此我将简短。
就像你期望的那样, 运行和停止按钮可以完成建议的操作。当你单击运行按钮时, 你的代码将被编译并执行。从本质上讲, Processing程序永远不会终止, 它们会永远运行直到受到干扰。你可以通过编程方式终止它, 但是如果没有, 则可以使用停止按钮。
调试器是运行和停止右侧的蝴蝶按钮。使用调试器还需要其他专门的文章。它不在本文的讨论范围之内, 因此你现在可以忽略它。调试器按钮旁边的下拉菜单是你添加/设置mod的地方。 Mods为你提供了某些特定功能, 允许你为Android编写代码, 允许你以Python编写代码, 等等。 Mod也不在范围之内, 因此你可以将其保持在默认Java模式下, 也可以将其忽略。
代码编辑器上的窗口通常是草图运行的地方。图片中为空白, 因为我们没有设置尺寸或背景色之类的属性, 或者没有绘制任何内容。
关于代码编辑器, 没什么可谈的, 只是你编写代码的地方。有行号(!)较旧的Processing版本没有该行号, 你无法想象我第一次看到它们时会多么高兴。
下面的黑框是控制台。我们将使用它来打印出东西, 以进行快速调试。控制台旁边的错误选项卡将显示你的错误。这也是Processing 3.0附带的新有用功能。在较旧的版本中, 错误被打印到控制台, 并且很难跟踪它们。
设置块
如前所述, 设置块在程序启动时执行一次。你可以使用它来进行配置以及只想运行一次的事情, 例如加载图像或声音。这是一个示例设置块。在你自己的环境中运行此代码, 然后亲自查看结果。
public void setup() {
// Size of our sketch will be 800x600, // and use the P2D rendering engine.
size(800, 600, P2D);
// We could have used this function instead of size()
// fullScreen(P2D);
// The background color of our sketch will be black
// by default, unless specified otherwise
background(0);
// We could have used this to set a background image.
// Note that size of our sketch should be the same as the image.
// background(loadImage("test.jpg"));
// Shapes and objects will be filled with red by default, // unless specified otherwise.
fill(255, 0, 0);
// Shaped and objects will have a white border by default, // unless specified otherwise.
stroke(255);
}
与样式(背景, 填充, 笔触)有关的方法将在”属性和设置”部分中进行说明。现在, 你需要知道的是我们在此处设置的设置和配置如何影响我们的整个草图。此处编写的代码用于设置一些适用于整个草图的基本规则集。在本节中, 你还应该了解以下列出的方法:
size()-顾名思义, 此函数用于配置草图的大小。它必须在设置代码块的第一行中。它可以以以下形式使用:
- 尺寸(宽度, 高度);
- 尺寸(宽度, 高度, 渲染器);
宽度和高度值可以以像素为单位。 Size函数接受第三个参数renderer, 该参数用于设置草图将使用的渲染引擎。默认情况下, 渲染器设置为P2D。可用的渲染器包括P2D(Processing2D), P3D(Processing3D, 如果你的草图将包括3D图形, 则应使用)和PDF(将2D图形直接绘制到Acrobat PDF文件中。有关更多信息, 请参见此处)。 P2D和P3D渲染器使用OpenGL兼容的图形硬件。
fullScreen()-从Processing 3.0开始, 现在可以使用fullScreen函数代替size()函数。就像size()函数一样, 它也应该位于setup块的第一行。用法如下:
- 全屏();
- 全屏(显示);
- fullScreen(renderer);
- fullScreen(display, renderer);
如果不带任何参数使用它, 则Processing草图将仅在全屏模式下运行, 并在主显示屏上运行。 “显示”参数用于设置草图将在哪个显示器上运行。例如, 如果将外部显示器连接到计算机, 则可以将显示变量设置为2(或3、4等), 然后草图将在此处运行。 ” renderer”参数如上面的size()部分所述。
设置块
这是新版本的Processing中引入的另一个功能。就像设置和绘制一样, 它是一个代码块。当你想使用可变参数定义size()或fullScreen()方法时, 此功能很有用。如果你使用的是Processing自己的IDE以外的任何环境(例如Eclipse), 那么还必须在此代码块中定义size()和其他样式属性, 例如smooth()。但是你在大多数情况下都不需要它, 在本文中绝对不需要。
抽签
关于抽奖块没有什么特别的, 但是关于它的一切都是特别的。抽签是所有魔术发生的地方。这是程序的心脏, 每秒跳动60次。此代码块包含你的所有代码逻辑。你所有的形状, 对象等都将写入此处。
我们将在本文中讨论的大多数代码都将来自draw块, 因此重要的是要清楚地了解此代码块的工作方式。为了给你示范, 你可以尝试以下方法。首先请注意, 我们可以使用print()或println()方法将任何内容打印到控制台。打印方法仅打印到控制台, 但是println打印并在末尾添加换行符, 因此每个println()将在单独的行中打印。
因此, 请看下面的代码块。首先, 尝试猜测它将在控制台中显示什么。然后, 继续尝试:
void setup(){
}
void draw(){
int x = 0;
x += 1;
print(x+" ");
}
如果你猜到” 1 2 3 4…”, 我就知道了!这是Processing中的困惑之一。还记得此块反复执行吗?在此处定义变量时, 将在每个循环中一次又一次地定义它。在每次迭代中, x设置为0, 以1递增, 并打印到控制台。因此, 我们得到的结果是” 1 1 1 1…”。这个例子有些明显, 但是当事情变得有些复杂时, 它可能会造成混乱。
我们不希望x被覆盖, 那么我们如何实现这一点并得到结果” 1 2 3 4…”?通过使用全局变量。没什么特别的, 我们只在draw块之外定义变量, 这样就不会在每次迭代时都重新定义它。同样, 在整个草图中, 变量的范围也可以达到。请参见下面的代码:
int x = 0;
void setup(){
}
void draw(){
x += 1;
print(x+" ");
}
你可能会问自己, 在我们的块之外定义的变量如何工作?为什么不使用setup()块, 因为它在开始时执行一次?答案与面向对象的编程和范围有关, 如果你不熟悉, 则可以跳过本段。请参阅我解释了如何将Processing代码转换为Java的部分。还记得他们是如何用Java类包装的吗?我们在setup()和draw()块之外编写的变量也被包装, 因此将它们视为包装我们的代码的外部类的字段。使用x + = 1与使用this.x + = 1相同。在我们的情况下, 它的功能也相同, 在draw()的范围内未定义任何名为x的变量, 而是搜索外部范围(即此范围)。为什么不在setup()部分中定义变量x?如果这样做的话, 定义x的范围将是setup函数的范围, 并且不能从draw()块中访问它。
绘图形状和文字

现在我们知道了如何使用设置块来配置草图, 并且知道绘制块的作用。因此, 现在该是一点点视觉效果并了解Processing的有趣部分:如何绘制形状的时候了。
在开始之前, 你应该了解坐标系。在”Processing”中, 确定在屏幕上绘制的每个对象的坐标。坐标系以像素为单位。原点(即起点)在左上角, 你应该给出相对于该点的坐标。你应该知道的另一件事是, 每个形状都有不同的参考点。例如, rect()以其左上角作为参考点。对于ellipse(), 它是中心。可以使用rectMode()和ellipseMode()之类的方法更改这些参考点, 我将在属性和设置部分对此进行说明。提供了一个示例图来帮助你更好地理解。
本文是Processing的基本概述, 因此我们不会涉及任何复杂的形状, 例如顶点或3D形状。基本的2D形状实际上足以让我们创建自己的游戏。在图中, 你可以看到有关如何绘制形状的示例。每个形状都有其自己的语法要创建, 但是基本思想是给出其坐标或大小, 或同时给出两者。这是你应该熟悉的一些形状(对于下面给出的所有值, ” x”和” y”表示以像素为单位的x和y坐标, ” w”和” h”也表示以像素为单位的宽度和高度值):
point()-简单点, 只需要一个坐标。用法:
- 点(x, y)
- point(x, y, z)-如果你使用3维。
line()-用于创建一条线。你可以创建仅包含起点和终点的线。用法:
- 线(x1, y1, x2, y2)
- line(x1, y1, z1, x2, y2, z2)-如果使用3个尺寸。
triangle()-用于创建三角形。用法:三角形(x1, y1, x2, y2, x3, y3)
quad()-用于创建四边形。用法:quad(x1, y1, x2, y2, x3, y3, x4, y4)
rect()-用于创建矩形。默认情况下, 参考点是左上角(请参见该图)。这是用法:
- rect(x, y, w, h)
- rect(x, y, w, h, r)-” r”表示使圆角变圆的半径(以像素为单位)。
- rect(x, y, w, h, tl, tr, br, bl)-半径分别为左上角, 右上角, 右下角和左下角。这也是以像素为单位。
ellipse()-用于创建椭圆形状。这也用于创建一个圆, 应给出相同的宽度和高度值。默认情况下, 此形状的参考点是中心(请参见该图)。这是用法:
- 椭圆(x, y, w, h)
arc()-绘制一条弧。用法:
- arc(x, y, w, h, start, stop)-“开始”和”停止”用于确定开始和停止绘制弧线的角度。值以弧度为单位。可以使用诸如” PI, HALF_PI, QUARTER_PI和TWO_PI”的常量。
- arc(x, y, w, h, start, stop, mode)-” mode”变量用于确定弧(字符串)的渲染样式。可用的选项是” OPEN, CHORD, PIE”。 OPEN将使未拉伸零件无边界。 CHORD将用边框完成未绘制的部分。 PIE将使你的弧形看起来像饼图。
在屏幕上显示文本类似于显示形状, 基本思想是确定要在其上显示文本的坐标。但是, 还有更多Processing文本的内容。在”属性和设置”部分之后, 你将对文本有更多的控制权, 在这里你将学习如何将设置和属性应用于对象。现在, 我将展示显示文本的基础知识。有很多方法可以做到, 我只说明要点。
text()-显示文本。用法:
- text(c, x, y)-” c”表示字符, 将显示任何字母数字字符。
- text(c, x, y, z)-如果你使用3维。
- text(str, x, y)-‘str’是要显示的字符串。
- text(str, x, y, z)-如果你使用3维。
- text(num, x, y)-” num”是要显示的数值。
- text(num, x, y, z)-如果你使用3维。
属性和设置
在本节中应该解释的第一件事是设置对象属性的逻辑。填充颜色, 背景颜色, 边框, 边框宽度, 边框颜色, 形状的对齐方式, 边框样式等可能是这些属性的一些示例。
设置属性时, 必须记住该代码将自上而下执行。假设你将” fill”属性设置为红色, 则在该行下方绘制的所有对象将被填充为红色, 直到被另一个fill属性覆盖。同样的情况也适用于其他属性, 但是请注意, 并非所有属性都会相互覆盖。例如, “笔画”属性不会覆盖”填充”属性, 而是可以一起使用。这是你理解逻辑的直观表示:

如你在图像中看到的, 第一行将填充颜色设置为红色, 第二行将描边颜色设置为蓝色。现在, 我们有两个活动设置:填充红色和蓝色笔触。如你所料, 无论我们的对象在下一行是什么, 它都会被红色填充并带有蓝色笔触(如果适用)。你可以继续以这种方式检查图像, 并且你将掌握逻辑。
以下是一些常用的基本属性和设置:
样式设定
fill()-将填充颜色设置为对象。此设置也用于为文本着色。现在, 我们只需要知道以下用法:
- fill(r, g, b)-红色, 绿色和蓝色值作为整数
- fill(r, g, b, a)-附加的alpha值, 最大值为255
noFill()-将填充颜色设置为透明。
stroke()-将笔触颜色设置为对象。笔触属性适用于对象周围的线条和边框。现在, 我们只需要知道以下用法:
- stroke(r, g, b)-红色, 绿色和蓝色值(整数)。
- stroke(r, g, b, a)-附加的alpha值, 最大值为255
noStroke()-删除笔划。
strokeWeight()-设置笔触的宽度。用法:
- strokeWeight(x)-x是一个整数, 表示像素的宽度。
background()-设置背景颜色。现在, 我们只需要知道以下用法:
- background(r, g, b)-红色, 绿色和蓝色值(整数)。
- background(r, g, b, a)-附加的alpha值, 最大值为255
对齐设置
ellipseMode()-设置将椭圆对齐为参考点的位置。用法:
- ellipseMode(mode)-参数” mode”, 以下是可用的参数:
- CENTER(默认):以中心为参考点。
- RADIUS:这也以中心为参考点, 但是在这种模式下, 你指定的w和h值被视为一半(即半径而不是直径)
- 角:以左上角为参考点。
- 角:将前两个参数(x和y)设置为椭圆的左上角位置, 将后两个参数(w和h)设置为椭圆的左下角位置。因此, 此模式”宽度”和”高度”无关。在这种情况下, 将其视为椭圆(x_tl, y_tl, x_br, y_br)更有意义。
rectMode()-设置将对齐矩形作为参考点的位置。用法:
- rectMode(mode)-” mode”是参数, 以下是可用的参数:
- 中心:以中心为参考点。
- RADIUS:这也以中心为参考点, 但是在此模式下, 你指定的w和h值将被视为一半
- CORNER(默认):以左上角为参考点。
- 角:将前两个参数(x和y)设置为椭圆的左上角位置, 将后两个参数(w和h)设置为椭圆的左下角位置。因此, 此模式”宽度”和”高度”无关。在这种情况下, 将其视为rect(x_tl, y_tl, x_br, y_br)更有意义。
文字相关设置
textSize()-设置文本的字体大小。用法:
- textSize(size)-所需大小的整数值。
textLeading()-设置文本的行高。用法:
- textLeading(lineheight)-行之间空间的像素值。
textAlign()-设置将文本对齐为参考点的位置。用法。
- textAlign(alignX)-” alignX”用于水平对齐。可用:左, 中, 右
- textAlign(alignX, alignY)-‘alignY’用于垂直对齐。可用:顶部, 底部, 中心, 基线。
动画制作
到目前为止, 我们学习了如何绘制对象和文本。但是它们的问题在于它们是静态的。现在我们如何使它们移动?很简单, 我们不用变量作为整数, 而是使用变量, 以便可以增加/减少它们。说得通?看下面的代码:
// initialize x and y as 0
int x=0;
int y=0;
void setup(){
size(800, 600);
background(255); // set background color to white
}
void draw(){
fill(255, 0, 0); // fill color red
stroke(0, 0, 255); // stroke color blue
ellipseMode(CENTER); // ref. point to ellipse is its center
ellipse(x, y, 20, 20); // draw the ellipse
// increment x and y
x+=5;
y+=5;
}
你看到我们如何管理动画吗?我们将x和y设置为全局变量并将其初始值设置为0。在绘制循环中, 我们创建了椭圆, 将填充颜色设置为红色, 将笔触颜色设置为蓝色, 并将坐标设置为x和y。当我们增加x和y时, 球只是改变其位置。但是这段代码有问题, 你能注意到吗?作为你自己的一个简单挑战, 请尝试找出问题所在并进行测试。结果如下:

我打算让这种情况发生是为了让你意识到Processing的循环本质是如何工作的。参考”绘制块”部分的示例, 你还记得为什么我们得到” 1 1 1…”而不是” 1 2 3…”吗?球留下痕迹的原因相同。每次绘制块迭代时, x和y都会增加5, 因此球会被向下和向右重画为5个像素。但是, 先前迭代中绘制的球仍保留在视图中。我们如何使它们消失?有什么猜想吗?
为了消除球留下的痕迹, 我们只需从设置块中删除background(255), 然后将其粘贴到绘制块的第一行即可。当我们的背景代码在setup块中时, 它在开始时运行了一次, 使我们的背景变成白色。但这还不够, 我们需要将每个循环的背景设置为白色, 以覆盖从先前循环中提取的球。背景是第一行, 意味着它先运行, 然后成为基础层。在每个循环中, 我们的画布都被涂成白色, 并且在白色背景上绘制了新元素。因此, 我们没有标记。
这就是在”Processing”中对事物进行动画Processing, 以编程方式操纵对象的坐标以更改其位置的背后思想。但是, 我们将如何做一些花哨的事情, 例如将球保持在屏幕前呢?还是实施重力?我将在本文的下一部分中教如何做这些事情。我们将通过尝试和建设来学习。我们将学习如何做并将其立即应用于我们的游戏。最后, 我们将提供一个完整, 可玩且充满希望的有趣游戏。
键盘和鼠标互动
Processing中的键盘和鼠标交互非常简单明了。你可以为每个事件调用一些方法, 并且在事件发生时, 你在其中编写的内容将被执行一次。还有一些全局变量, 例如mousePressed和keyPressed, 你可以在绘图块中使用它来利用循环。以下是一些带有说明的方法:
void setup() {
size(500, 500);
}
void draw() {
if (mousePressed) {
// Codes here will be executed as long as the mouse
// button is pressed
if (mouseButton == LEFT){
// This lines will be executed as long as
// the clicked mouse button is the left mouse
// button.
}
}
if (keyPressed) {
// Codes here will be executed as long as a key
// on the keyboard is pressed
if (key == CODED) {
// This if statement checks if the pressed key
// is recognised by Processing.
if (keyCode == ENTER) {
// This lines will be executed if the pressed key
// is the enter key.
}
}
else{
// This lines will be executed if the pressed key
// is not recognised by processing.
}
}
}
void mousePressed() {
// These codes will be executed once, when mouse
// is clicked. Note that mouseButton variable is
// also be used here.
}
void keyPressed() {
// These codes will be executed once, when a key
// is pressed. Note that key and keyCode variables
// are also usable here.
}
如你所见, 检查是单击鼠标还是按下哪个键非常容易。但是, mousePressed和keyCode变量还有更多选项可用。 mousePressed的可用选项为LEFT, RIGHT和CENTER。 keyCode还有更多可用的内容。上, 下, 左, 右, ALT, 控制, SHIFT, BACKSPACE, TAB, ENTER, 返回, ESC和DELETE。
关于鼠标变量, 要知道的一件事是, 如何获取鼠标的坐标, 我们将经常使用它。为了获得光标的精确坐标, 我们可以直接在draw()块中使用mouseX和mouseY变量。最后但并非最不重要的一点是, 你还应查看许多其他有用的方法。它们全部记录在”Processing参考”中。
总结
你现在应该已经熟悉Processing。但是, 如果你在这里停留, 所有这些知识将飞走。我强烈建议你继续练习, 尝试学习的知识。为了帮助你练习, 我将为你提供两个练习。你应该尽力自己做。如果你遇到困难, 则Google和Processing Reference应该是你最好的朋友。我将为第一个提供代码, 但是查看它们应该是你要做的最后一件事。
推荐练习1
你应该制作4个颜色不同的球, 从屏幕的4个角开始以不同的速度穿过中心。单击并按住鼠标按钮时, 球应冻结。当你放开鼠标时, 球可能会回到其初始位置并继续移动。因此, 我正在寻找类似的东西。
自己尝试练习之后, 可以在此处签出代码。
推荐练习2
还记得著名的DVD屏幕保护程序, DVD徽标在屏幕周围弹跳, 我们都在拼命等待它的出现?我希望你复制该屏幕保护程序, 但仅使用矩形而不是DVD徽标。启动应用程序时, 屏幕应为黑色, 矩形应在随机位置开始。矩形每次碰到角时, 都应更改其颜色(明显是方向)。当你四处移动鼠标时, 矩形应消失, 背景颜色应变为白色(是屏幕保护程序, 不是吗?)。在本文中, 我不会提供此练习的代码。你应该尽力实现它, 并且该代码将在本文的第二部分中提供。
《Processing终极指南》的第二部分是逐步构建一个简单游戏的教程, 已经出版。