1. 本课我们要学一个新的类,称为字符串(string)。对我们来说,这并不是一个全新的概念,之前我们也曾接触过它们:
println("printing some text to the message window!"); // 列印一个字符串
PImage img = loadImage("filename.jpg"); // 为文件名使用一个字符串
这样看起来,我们似乎可以简单的将字符串理解为“在双引号内的内容”。
2. 字符串的核心其实是储存字母数组,如果没有string类,那么我们要写一行字的代码可能会变成:
char[] sometext = { 'H', 'e', 'l', 'l' , 'o' , ' ', 'W' , 'o' , 'r', 'l' , 'd'};
这么搞绝对会被搞死,如果使用string对象,世界立马变得简单美好起来:
String sometext = " 如何做一个字符串? 在引号间输入字符!";
3. 我们必须记住,一个string是一个伴随方法(method)的对象。类似于PImage对象可以在存储一个图像数据的同时,还可以使用方法copy(), loadPixels()等等。对于string来说,一个方法是 charAt(),它可以返回一个字符串里给定序号的字母。同数组一样,字符串的第一个字母同为第0号。
4. 通过Daniel随后出的一题我意外的发现,在一个字符串内,空格也算一个“字母”,也占序号,无论这个空格出现在字符串内的任何地方。
5. 另一有用的方法是length()。这常会与数组length的属性混淆。不过你记得按一下方式呼叫它就对了:
String message = "这个字符串有十五个字符那么长。"; println(message.length());
通过笨办法——数数的方式,我们看到,句号也会被当作一个“字母”。因此我们可以推论,在一个字符串内任何占位符都会被当作一个“字母”被进行计数。
6. 顺序列印一个字符串的每一个字母:
String message = "一堆文字.";
for(int i = 0; i < message.length(); i++) {
char c = message.charAt(i);
println(c);
7. toUpperCase()可以使字符串内字母全大写:
String message = "a bunch of text here."; String uppercase = message.toLowerCase(); println(uppercase);
8. toLowerCase()可以使字符串内字母全小写,用法同上。
9. 细心的你可能会发现,在第7条的例子当中,为什么我们要用println(uppercase); ,而不用println(message);?因为string对象是一种特殊的不可变对象。所谓“不可变”是指它的数据永远都不可变。这就意味着任何时候我们要改变一个字符串,我们必须创建一个新的字符串。因此在转换大写的时候,方法toUpperCase()返回的是一个全大写的字符串对象的副本。
10. 最后,我们看看equals()。说到“等于”,也许你首先会想到这么写:
String one = "hello"; String two = "hello"; println(one == two);
从技术角度讲,当对对象使用"==",它比较的是每个对象的内存位置。尽管每个字符串包含相同的数据——"hello"——如果它们是不同的对象实例,则"=="可能会返回一个错误的对比。这样的时候,就是equals()发挥作用的时候,它用来对比两个字符串是否包含相同的数据,而无论它们存储的位置在哪里。
String one = "hello"; String two = "hello"; println(one.equals(two));
尽管以上两种方法都会返回正确的结果,但是用equals()更保险。基于string对象不同的创建方式,"=="不会始终保持正确。
11. 字符串还可用“+”号连接。
String helloworld = "Hello" + "World";
变量照使:
int x = 10; String message = "x的值是:" + x;
“图像”一课载入编号图像数组是这一用法一个很好的例子。
12. 要在萤幕上显示一些文本,我们需要做以下简单几步:
12.1. Tools > Creat Font 选择一个子体。这将创建并将字体文件放入你的data文件夹。p5的字体格式很特殊——"vlw",它使用图像来显示每个字母。因为如此,你同时还要指定你想要显示文字的大小。
12.2. 申明一个PFont类型的对象:
PFont f;
12.3. 用loadFont()载入字体。载入一次就够了,所以我门将它放在setup()里,和载入图像一个道理。
f = loadFont("ArialMT-16.vlw");
12.4. 用textFont()指定字体。两个引数,第一个字体变量,第二个字体大小(可选)。如果不指定字体大小,则字体会以最初载入的大小显示。指定一个与创建字体大小不同的字体大小会影像它的显示(和放大缩小图像一样)。
textFont(f,36);
12.5. 用fill()指定颜色。
12.6. 呼叫text()函数显示文本。三个引数:文本,x位置,y位置。
text( "呜呜呜... 字符串... " ,10,100);
12.7. 上完整的例子:
// Step 2: 申明PFont变量
PFont f;
void setup() {
size(200,200);
// Step 3: Load Font
f = loadFont( "ArialMT-16.vlw" );
}
void draw() {
background(255);
textFont(f,16); // Step 4: 指定要用的字体
fill(0); // Step 5: 指定字体颜色
// Step 6: 显示文本
text ( "oNEwAY is a Chinese Post-Rock Band" ,10,100);
}
通过上例,我发现这玩意不会自动换行,,多出来的部分就会显示在窗口之外而不可见。
13. 字体还可被createFont()函数创建:
myFont = createFont( "Georgia", 24, true); // 三个引数分别是:字体名字,字体大小,是否开启平滑的一个布尔表达式
createFont()允许你创建安装于本机却在p5默认选项中不支持的字体。另外,createFont()允许字体缩放到任意大小而不影响显示质量。更多介绍请参看p5在线手册.
14. PFont.list()可以查看所有可用的字体:
println(PFont.list()); // 列印全部可用于createFont() 的字体。
15. 下面这个练习在弹跳的球旁边伴随显示球的x,y位置(当然一个更好的显示方式是将文本位置固定):
PFont f;
float x = 100;
float y = 0;
float speed = 0;
float gravity = 0.05;
void setup() {
size(400,200);
f = createFont("Arial", 16, true);
smooth();
}
void draw() {
background(255);
stroke(175);
rectMode(CENTER);
ellipse(x,y,10,10);
y = y + speed;
// Add gravity to speed.
speed = speed + gravity;
// If square reaches the bottom
// Reverse speed
if (y > height) {
// Multiplying by -0.95 instead of -1 slows the square down each time it bounces (by decreasing speed).
// This is known as a "dampening" effect and is a more realistic simulation of the real world (without it, a ball would bounce forever).
speed = speed * -0.95;
}
textFont(f,10);
fill(0);
// 将浮点值转为整数并显示
text((int)x+", "+(int)y,x+8,y-8);
}
16. textAlign() —— 指定文本对齐模式:
PFont f;
void setup() {
size(400,200);
f = createFont("Arial", 16, true);
}
void draw() {
background(255);
stroke(175);
line(width/2,0,width/2,height);
textFont(f);
fill(0);
// textAlign()设置文本对齐模式. 它有一个引数: CENTER, LEFT, 或者 RIGHT.
textAlign(CENTER); // 居中
text("这是居中的文字." ,width/2,60);
textAlign (LEFT) ; // 居左
text("这是左对齐的文字." ,width/2,100);
textAlign(RIGHT); // 居右
text("这是右对齐的文字." ,width/2,140);
}
17. textWidth() —— 计算并返回任何字母或文本字符串的宽度。比如说我们要在萤幕下方做一个从右至左的新闻滚动条。当文字全部滚入左边后,从右边重新开始滚动。如果我们知道文本开头的x位置和文本的宽度,我们便可知道它什么时候会完全滚入左边。textWidth()给我们的正是这个宽度。
首先,我们在setup()内申明新闻,字体,x变量,并初始化它们。
// 一条新闻
String headline = "New study shows computer programming lowers cholesterol.";
PFont f; // 全局字体变量
float x; // 新闻的水平位置
void setup() {
f = createFont( "Arial",16,true); // 载入字体
x = width; // 将x放到右边
}
draw()里边:
// 在x位置显示新闻 textFont(f,16); textAlign(LEFT); text(headline,x,180);
让x减小,以使文本向左走:
x = x – 3;
稍微复杂一点的一步,测试文本是否已经全部滚入左侧,如果已经离开萤幕,重置其到最右边:
// 如果x小于文本宽度的负值,则这段文本便完全处于萤幕外
float w = textWidth(headline);
if (x < -w) {
x = width;
}
下例即以上代码的合体,唯一不同的是,它分别滚动两段不同的文本:
// 新闻数组
String[] headlines = {
"Processing downloads break downloading record." ,
"New study shows computer programming lowers cholesterol." ,
};
PFont f; // 全局字体变量
float x; // 水平位置
int index = 0;
void setup() {
size(400,200);
f = createFont( "Arial" ,16,true);
// 初始化x到最右
x = width;
}
void draw() {
background(255);
fill(0);
// 在x位置显示新闻
textFont(f,16);
textAlign (LEFT);
// 基于"index"变量的值显示数组的一个特定字符串
text(headlines[index],x,180);
// 递减x
x = x - 3;
// 如果x小于文本宽度的负值,则这段文本便完全处于萤幕外
// textWidth()被用来计算当前字符串的宽度.
float w = textWidth(headlines[index]);
if (x < -w) {
x = width;
// 递增index,这样当当前字符串离开萤幕便显示一个新的字符串。
index = (index + 1) % headlines.length;
}
}
18. 除了textAlign()和textWidth()外,还有textLeading(), textMode()和textSize()可用,自己看p5在线参考for more。
19. 习题17-6,做一个接头接尾持续滚动的文本条。看似简单,我却不会,,已经给了Daniel邮件,等他答案。
20. 结合像素数组,我们可以用字母做一个视频马赛克,代码长度不短:
import processing.video.*;
// 缩放值
int videoScale = 14;
// 我们系统中行和列的数量
int cols, rows;
// capture对象
Capture video;
// 马赛克模式中的源文本. 越长的字符串也许会出现越有趣的结果.
String chars = "fuckyoubaby" ;
PFont f;
void setup() {
size(640,480);
// 建立行和列
cols = width/videoScale;
rows = height/videoScale;
video = new Capture(this,cols,rows,15);
// 载入字体
// 使用一个固定宽度的字体. 对大多数字体来说, 不同的字母有不同的宽度.
// 在固定宽度字体钟, 所有字母等宽.
// 这对本例很有用,因为我们要在空间平均排布这些字母
f = loadFont("Courier-Bold-20.vlw");
}
void draw() {
background(0);
// 从摄像头读取图像
if (video.available()) {
video.read();
}
video.loadPixels();
// 使用一个计数器变量来数字符串中的字母
int charcount = 0;
// 开始循环行
for (int j = 0; j < rows; j ++ ) {
// 开始循环列
for (int i = 0; i < cols; i ++ ) {
// 我们在哪?
int x = i*videoScale;
int y = j*videoScale;
// 在像素数组内寻找合适的颜色
color c = video.pixels[i + j*video.width];
// 显示字符串中的各个字母来替代矩形
textFont(f);
fill(c);
// 文本内的一个字母在像素位置显示并被染色.
// 一个计数器变量—— "charcount"被用来每次触发一个字符串内的字母.
text(chars.charAt(charcount),x,y);
// 继续下一个字母
charcount = (charcount + 1) % chars.length();
}
}
}
21. 让字母根据亮度调整大小,你只需加入以下几行(如果你不想要彩色而只要黑白,那么将关于颜色的几行注释掉即可),不过记得使用createFont()函数创建字体,因为这样创建的字体不会因为缩放而失真:

float b = brightness(video.pixels[i + j*video.width]); float fontSize = 36 * (b / 255); textSize(fontSize);
虽然能运行成功,但我却持续的得到错误提示:“Thu Dec 3 23:53:34 xxx.local java[431]
22. 文本同样可以实现位移与旋转:
PFont f;
String message = "这段文本正在旋转";
float theta;
void setup() {
size(200,200);
f = createFont("Arial", 20, true);
}
void draw() {
background(255);
fill(0);
textFont(f); // 设置字体
translate(width/2,height/2); // 由中点旋转
rotate(theta); // 以theta旋转
textAlign(CENTER) ;
// 在平移和旋转后这段文本居中对齐并显示在(0,0).
// 如果你忘了平移和旋转,返回去复习一下吧.
text(message,0,0);
// 增加旋转(加 为顺时针)
theta += 0.05;
}
23. 是的,如上例可见,p5支持并可正确显示中文,但是它并不允许你在程序中直接输入中文,没事,在文本编辑器里写好再把它们粘贴进去就好了~
24. 如果你要新起一行,可以这么写:
String message = "这是第一行\n这是第二行";
“\”意思是"新的一行"。在Java中,不可见字母可以与一个“转义序列(escape sequence)”一起北河并到一个字符串内——一个斜杠"\"伴随一个字母。以下是一些基本用法:
\n—新的一行
\r—回车
\t—tab
\’—单引号
\”—双引号
\\—斜杠
25. 在一些制图软件中,要求一串文本中每个字符都得独立渲染。在p5中,这样的解决方式是循环一个字符串,每次显示一个字符。
// 第一个字母在位于10个像素的水平位置
int x = 10;
for (int i = 0; i < message.length(); i++ ) {
// 使用charAt()函数使每次显示一个字符
text(message.charAt(i), x, height/2);
// 每个字符间间隔10个像素
x += 10;
}
26. 呼叫每个字符的text()函数给了我们之后的例子更多的发挥空间(染色,设置大小,在一个字符串内单独放置字符)。10个像素的间隔不一定准确,因为不一定每个字符的宽度都是10。准确的间隔在下例中由textWidth()实现。注意它是如何在随机字符大小的情况下仍然保持合适的间隔的:
PFont f;
String message = "oNEwAY是一支来自昆明的后摇滚乐队";
void setup() {
size(500,200);
f = createFont( " Arial " ,12,true);
}
void draw() {
background(255);
fill(0);
textFont(f,12);
int x = 10;
for (int i = 0; i < message.length(); i++ ) {
textSize(random(12,36));
text(message.charAt(i), x, height/2);
x += textWidth(message.charAt(i));
}
}
我注意到如果让上边这段代码一直跑的话,最后会停止(因为出错了..),解决办法是,要么你加个noLoop();,要么你把它从draw()里边给整出来:
PFont f;
String message = "oNEwAY是一支来自昆明的后摇滚乐队";
size(500,200);
f = createFont( " Arial " ,12,true);
background(255);
fill(0);
textFont(f,12);
int x = 10;
for (int i = 0; i < message.length(); i++ ) {
textSize(random(12,36));
text(message.charAt(i), x, height/2);
x += textWidth(message.charAt(i));
}
然后我发现在这样的情形下,使用"\n"换行的方式是没用的。
27. 用自适应间隔重做第一个字母马赛克的例子:
import processing.video.*;
// 缩放比例
int videoScale = 16;
// 行数和列数
int cols, rows;
// capture对象
Capture video;
// 一个字符串和字体
String chars = "oNEwAYisapostrockbandfromkunmingyunnanchina";
PFont f;
void setup() {
size(640, 480);
//建立行和列
cols = width/videoScale;
rows = height/videoScale;
video = new Capture(this,cols,rows,15);
// 载入字体
f = createFont("Arial",18,true);
}
void draw(){
// 从摄像头读取图像
if (video.available()) {
video.read();
}
video.loadPixels();
//image(video,0,0,width,height);
background(0);
// 使用一个计数器
int charcount = 0;
// 开始循环行
for ( int j = 0; j < rows;j++) {
// 现在开始循环列, 而不是逐一循环像素
// 我们基于字符宽度使用一个浮点变量x来进行移动
float x = 0;
while (x < width) {
// 我们垂直位置在哪?
int y = j*videoScale;
// 我们水平位置在哪? 转化到整数, 缩小, 并确保我们始终位于萤幕内
int pix = constrain((int) (x / videoScale),0,cols-1);
// 在像素数组内选取正确的颜色
color c = video.pixels[pix+j*video.width];
// 显示字符串中的独立字符
// 替代矩形
textFont(f);
fill(c);
char ch = chars.charAt(charcount);
text(ch,x,y);
// 继续下一个字符, 到最末的时候重新从0开始循环
charcount = (charcount + 1) % chars.length();
// 依据字符宽度移动x
x += textWidth(ch);
}
}
}
28. 这种方法同样可以用于各个字符独立运动的案例。下边这个例子使用面向对象得方式制作,让字符串中的每一个字符成为一个对象,使它们既能在适当的位置显示又能在萤幕内独立运动:
PFont f;
String message = "oNEwAY是一支来自云南昆明的后摇滚乐队";
// 字母数组
Letter[] letters;
void setup() {
size(460,200);
// 载入字体
f = createFont("Arial", 20, true);
textFont(f);
// 创建与字符串同样大小的数组
letters = new Letter[message.length()];
// 在正确的x位置初始化字母
int x = 66;
for (int i = 0; i < message.length(); i ++ ) {
// 字符对象依它们在字符串中的位置及显示初始化
letters[i] = new Letter(x,100,message.charAt(i));
x += textWidth(message.charAt(i));
}
}
void draw() {
background(255);
for (int i = 0; i < letters.length; i ++ ) {
// 显示全部字符
letters[i].display();
// 如果鼠标按下,字符开始抖动
// 如果放开,它们回归原位
if (mousePressed) {
letters[i].shake();
} else {
letters[i].home();
}
}
}
// 一个描述单独字符的类
class Letter {
char letter;
// 对象知道它最初的位置
float homex,homey;
// 以及它现在的位置
float x,y;
Letter(float x_, float y_, char letter_) {
homex = x = x_;
homey = y = y_;
letter = letter_;
}
// 显示字符
void display() {
fill(0);
textAlign(LEFT);
text(letter,x,y);
}
// 随机移动字符
void shake() {
x += random(-2,2);
y += random(-2,2);
}
// 在任何一点, 通过呼叫home()函数便可将位置从当前重置到最初。
void home() {
x = homex;
y = homey;
}
}
29. 这种方法还允许我们将文字附于一个曲线上。在这么做之前,我们先看看如何将一系列矩形附于一个曲线上:
PFont f;
// 圆形的半径
float r = 100;
// 矩形的长、宽
float w = 40;
float h = 40;
void setup() {
size(320,320);
smooth();
}
void draw() {
background(255);
// 从中心开始并画圆
translate(width/2, height/2);
noFill();
stroke(0);
// 这个圆就是我们的曲线
ellipse(0, 0, r*2, r*2);
// 10个矩形围绕曲线
int totalBoxes = 10;
// 我们必须保持记录围绕曲线的位置
float arclength = 0;
// 为每个矩形
for (int i = 0; i < totalBoxes; i ++ ) {
// 每个盒子都居中,因此我们将它们移动半个身位
arclength += w/2;
// 角的弧度等于弧长除以半径
float theta = arclength / r;
pushMatrix();
// 极坐标到笛卡尔坐标的转换
translate(r*cos(theta) , r*sin(theta));
// 旋转矩形
rotate(theta);
// 显示矩形
fill(0, 100);
rectMode(CENTER);
rect(0, 0, w, h);
popMatrix();
// 再次移动半个身位
arclength += w/2;
}
}
30. 尽管你觉得这个例子的数学可能有点难,但它的运行结果已经向我们揭示了下一步。我们需要做的只是用字符来填入各个矩形。并且因为每个字符并非同等宽度,所以相对"w"这个常量,我们需要使用一个变量,这个宽度由textWidth()函数得到:
// 被显示的文本
String message = "围绕曲线的汉字们";
PFont f;
// 圆半径
float r = 100;
void setup() {
size(320,320);
f = createFont("Georgia",40,true);
textFont(f);
// 文本必须居中!
textAlign(CENTER);
smooth();
}
void draw() {
background(255);
// 从中心开始并绘制圆形
translate(width/2, height/2);
noFill();
stroke(0);
ellipse(0, 0, r*2, r*2);
// 保存位置
float arclength = 0;
// 为每个字
for (int i = 0; i < message.length(); i ++ ) {
// 字符及其宽度
char currentChar = message.charAt(i);
// 我们查询每个字符的宽度来替代固定的宽度.
float w = textWidth(currentChar);
// 每个字都是居中对齐的,所以我们移动半个身位
arclength += w/2;
// 角的弧度等于弧长除以半径
// 通过增加PI由圆形左边开始
float theta = PI + arclength / r;
pushMatrix();
// 极坐标到笛卡尔坐标的转换允许我们找到沿着曲线的点.
translate(r*cos(theta), r*sin(theta));
// 旋转文字 (抵消旋转90度)
rotate(theta + PI/2);
// 显示文字
fill(0);
text(currentChar,0,0);
popMatrix();
// 再次移动半个身位
arclength += w/2;
}
}
31. 下边是书里的练习,让随机位置的文本归位,然后继续上边那个例子,鼠标点击,抖动,放开,归位。还要用到一些新函数,哦也,我不会做,直接看答案,慢慢学习吧。。。:
PFont f;
String message = "呼啦啦啊呼啦啦,随机文字们各归其位!";
// 文字对象数组
Letter[] letters;
void setup() {
size(400, 200);
// 载入字体
f = createFont("Georgia",20,true);
textFont(f);
// 以字符串大小创建数组
letters = new Letter[message.length()];
// 在正确的x位置初始化数组
int x = 30;
for (int i = 0; i < message.length(); i++) {
letters[i] = new Letter(x,height/2,message.charAt(i));
x += textWidth(message.charAt(i));
}
}
void draw() {
background(255);
for (int i = 0; i < letters.length; i++) {
// Display all letters
letters[i].display();
// If the mouse is pressed the letters shake
// If not, they return to their original location
if (mousePressed) {
letters[i].shake();
} else {
letters[i].home();
}
}
}
// A class to describe a single Letter
class Letter {
char letter;
// The object knows its original "home" location
float homex,homey;
// As well as its current location
float x,y;
// And an angle of rotation
float theta;
Letter (float x_, float y_, char letter_) {
homex = x = x_;
homey = y = y_;
x = random(width);
y = random(height);
theta = random(TWO_PI);
letter = letter_;
}
// Display the letter
void display() {
fill(0);
textAlign(LEFT);
// 用户位移和旋转来绘制文字
pushMatrix();
translate(x,y);
rotate(theta);
text(letter,0,0);
popMatrix();
}
// 随机移动文字
void shake() {
x += random(-2,2);
y += random(-2,2);
theta += random(-0.5,0.5);
}
// 用lerp让文字归位!
void home() {
x = lerp(x,homex,0.05);
y = lerp(y,homey,0.05);
theta = lerp(theta,0,0.05);
}
}
lerp()——依一个特殊的增量计算两个数字间的一个数字。参数amt是两个值间的篡改(interpolate)总数,比如,0.0等于第一个值,0.1非常靠近第一个值,0.5在它们之间,等等。lerp函数便于创建直线运动以及绘制点状线。更多。
是的,貌似比较难理解,但我想了个笨办法,列印lerp出来的值,然后慢慢去琢磨它的用法。还是挺管用的~









这个博客不错,我也在学习processing,希望多交流。请问你是吧Daniel的书翻译过了吗?
边看边把重要的记录下来并发布到这里
你很强,我才看到第四章,很多概念理解得还不够
花时间的事情而已,学习并不能证明强弱,至少我现在还做不出什么让人耳目一新的东西来。。。一起加油吧~
我想知道怎么显示中文,还有我在网上看到一个小作品,它的字符串似乎不是用String message =..,而似乎是连到外面的文本文档了,StrArray = loadStrings(“affirmations.txt”);
请麻烦解释解释
@Blackburn,
1. 显示中文没问题,只是在p5环境中不支持中文输入到是真的,因此你只能将中文粘贴进代码中。
2. 关于读取外部txt文档,请看下一课。
感谢你的提醒,我已经用creatFont显示出了中文,但是我还是不太明白这个函数,所谓创造字体到底创造在哪里了,还是只是个名称而已,因为我再随意改动这个自造字体的名称,它依然可以显示出打好的中文,是不是也不需要data里的字体文件呢,另外似乎只能显示宋体的样子,这是否可以改呢;第二个问题就是读取外部文档,在代码中我依然用creatFont可是这时候连进来的中文显示的都是一个个小方块,这是怎么回事,当然,如果是loadFont就跟本不显示中文了
@Blackburn,
creatFont()用与字体创建工具同样的方式创建一个位图版本的字体。它依名字载入一个字体,并基于大小创建一系列的图像。在可能的情况下,函数text()将使用本地字体而不是创建的本地位图字体。例如,当使用默认渲染设置(JAVA2D)时,将使用本地字体,以提升绘图质量和性能。使用P2D,P3D和OPENGL渲染设置时,将使用位图版本。
PFont.list()可以查看所有可用的字体。理论上来说,能被列印出来的字体都是可用的。但由于Java的局限性,有时并非所有字体都可用,或者某些系统可用而其他系统却不可用。
loadStrings()创建的是一个字符串数组(每行为一个字符串形式的元素),用它读取txt文档后,用join()整合这个数组为一个长字符串后再输出看结果。
例如:
String[] lines = loadStrings(“text.txt”);
String onelongstring = join (lines, “”);
text(onelongstring,x,y);
我还是不会整合,因为我分不清你的例子哪个是函数哪个是名称,orz另外我不只要连接外部文本,还要根据外部文本的行数将字体随机显示在屏幕上,如果你有q的话希望可以把源文件传给你再看
@blackburn,
学到现在,你应该知道函数在P5内是以棕色高亮显示的,如果连这点都还不知道,那还是建议你从基础学起,不要急于求成。
您好,“习题17-6,做一个接头接尾持续滚动的文本条。” 您现在有进展么?我想了好久想不出来,能请教一下吗?
@四事一, 你好,这题我问过Daniel之后,他已经解答,看这里:http://www.learningprocessing.com/exercises/chapter-17/exercise-17-6/
请问文字沿弧形滚动应该怎么做啊T T
請問球碰到後要變小的程式如何寫?