Processing 编程学习指南 (丹尼尔·希夫曼 著)

https://processing.org/reference/

第1章 像素 (已看)

第2章 Processing (已看)

第3章 交互 (已看)

第4章 变量 (已看)

第5章 条件语句 (已看)

第6章 循环 (已看)

第7章 函数 (已看)

第8章 对象 (已看)

第9章 数组 (已看)

第10章 算法 (已看)

第11章 调试 (已看)

第12章 库 (已看)

第13章 数学 (已看)

第14章 三维平移和旋转 (已看)

第15章 图像 (已看)

第16章 视频  (已看)

第17 章 文本 (已看)

第18章 数据输入 (已看)

第19章 数据流

第20章 声音

第21章 导出

第22章 高级的面向对象编程

第23章 Java

 

第1章 像素

  1.1 坐标纸

  1.2 绘制基本图形

point(4,5);
line(1,3,8,3);
rect(2,3,4,5);

rectMode(CENTER);
rect(3,3,5,5);

rectMode(CORNERS);
rect(5,5,8,7);

ellipseMode(CENTER);
ellipse(3,3,5,5);

ellipseMode(CORNER);
ellipse(3,3,4,4);

ellipseMode(CORNERS);
ellipse(5,5,8,7);
View Code

  1.3 灰度模式

灰度(grayscale).数值0代表黑色,数值255代表白色,而在此之间的其他数值(50,87,162,209等)代表的是由黑色逐渐到白色的过堵色

size(400,400);

background(255);
stroke(0);
fill(150);
rect(50,50,75,100);

noFill();
ellipse(60,60,100,100);
View Code

  1.4 RGB颜色

size(400,400);

background(255);
noStroke();

fill(255,0,0);
ellipse(20,20,16,16);

fill(127,0,0);
ellipse(40,20,16,16);

fill(255,200,200);
ellipse(60,20,16,16);
View Code

  1.5 颜色透明度

size(400,400);

background(0);
noStroke();

fill(0,0,255);
rect(0,0,100,100);

fill(255,0,0,255);
rect(0,0,200,40);

fill(255,0,0,191);
rect(0,50,200,40);

fill(255,0,0,127);
rect(0,100,200,40);

fill(255,0,0,63);
rect(0,150,200,40);
View Code

  1.6 自定义颜色取值范围

colorMode(RGB,100);
colorMode(RGB,100,500,10,255);
View Code

HSB颜色模式(三个字母分别对应:hue(色调),saturation(饱和度)和brightness(亮度)).虽然HSB的取值范围默认也是0~255,但是常用的颜色取值范围如下所示:

  色调-颜色本身的色调(红色,蓝色,橙色等)取值范围为0~360(将360°想象成一个颜色轮盘)

  饱和度-颜色的鲜艳程度,取值范围为0~100(可以想象成百分比)

  亮度-颜色的亮度值,取值范围为0~100

size(400,400);

background(255);
ellipseMode(CENTER);
rectMode(CENTER);
stroke(0);
fill(150);
rect(100,100,20,100);
fill(255);
ellipse(100,70,60,60);
fill(0);
ellipse(81,70,16,32);
ellipse(119,70,16,32);
stroke(0);
line(90,150,80,160);
line(110,150,120,160);
View Code

第2章 Processing

  2.1 让Processing来拯救你

  2.2 如何下载Processing

  2.3 Processing 应用程序

  2.4 速写本

  2.5 Processing中的代码

  2.6 错误提示

  2.7 Processing参考文档

  2.8 "运行"按钮

  2.9 你的第一个草图

size(200,200);  // Set the size of the window
background(255);  // Draw a white background

// Set ellipses and rects to CENTER mode
ellipseMode(CENTER);
rectMode(CENTER);

// Draw Zoog's body
stroke(0);
fill(150);
rect(100,100,20,100);

// Draw Zoog's head
fill(255);
ellipse(100,70,60,60);

// Draw Zoog's eyes
fill(0);
ellipse(81,70,16,32);
ellipse(119,70,16,32);

// Draw Zoog's legs
stroke(0);
line(90,150,80,160);
line(110,150,120,160);
View Code

第3章 交互

  3.1 程序的运行流程

  3.2 我们的好朋友:setup()和draw()

  3.3 跟随鼠标移动

void setup() {
  size(200,200);  
}

void draw() {
  background(255);
  
  // Body
  stroke(0);
  fill(175);
  rectMode(CENTER);
  rect(mouseX,mouseY,50,50);
}
View Code
void setup() {
  size(200,200);  
}

void draw() {
  background(255);
  
  ellipseMode(CENTER);
  rectMode(CENTER);
  
  stroke(0);
  fill(175);
  rect(mouseX,mouseY,20,100);
  
  stroke(0);
  fill(255);
  ellipse(mouseX,mouseY - 30,60,60);
  
  fill(0);
  ellipse(81,70,16,32);
  ellipse(119,70,16,32);
  
  stroke(0);
  line(90,150,80,160);
  line(110,150,120,160);
}
View Code
void setup() {
  size(200,200);
  background(255);
}

void draw() {
  stroke(0);
  line(pmouseX,pmouseY,mouseX,mouseY);
}
View Code

  3.4 鼠标点击和键盘操作

void setup() {
  size(200,200);
  background(255);
}

void draw() {
  
}

void mousePressed() {
  stroke(0);
  fill(175);
  rectMode(CENTER);
  rect(mouseX,mouseY,16,16);
}

void keyPressed() {
  background(255); 
}
View Code
void setup() {
  size(200,200);
  frameRate(30);
}

void draw() {
  background(255);
  
  ellipseMode(CENTER);
  rectMode(CENTER);
  
  stroke(0);
  fill(175);
  rect(mouseX,mouseY,20,100);
  
  stroke(0);
  fill(255);
  ellipse(mouseX,mouseY-30,60,60);
  
  fill(mouseX,0,mouseY);
  ellipse(mouseX-19,mouseY-30,16,32);
  ellipse(mouseX+19,mouseY-30,16,32);
  
  stroke(0);
  line(mouseX-10,mouseY+50,pmouseX-10,pmouseY+60);
  line(mouseX+10,mouseY+50,pmouseX+10,pmouseY+60);
}
View Code

第4章 变量

  4.1 什么是变量

  4.2 变量的声明和初始化

boolean 
char
byte
short
int
long
float
double
View Code

  4.3 使用变量

int circleX = 0;
int circleY = 100;

void setup() {
  size(200,200); 
}

void draw() {
  background(255);
  stroke(0);
  fill(175);
  ellipse(circleX,circleY,50,50);
  
  circleX = circleX + 1;
}
View Code

  4.4 多种变量

  4.5 系统变量

void setup() {
  size(200,200); 
}

void draw() {
  background(255);
  stroke(255);
  fill(frameCount/2);
  rectMode(CENTER);
  
  rect(width/2,height/2,mouseX+10,mouseY+10);
}

void keyPressed() {
  println("You pressed " + key); 
}
View Code

  4.6 随机:多样化为生活增加趣味性

float r;
float g;
float b;
float a;

float diam;
float x;
float y;

void setup() {
  size(400,400);
  background(255);
}

void draw() {
  r = random(255);
  g = random(255);
  b = random(255);
  a = random(255);
  
  diam = random(20);
  x = random(width);
  y = random(height);
  
  noStroke();
  fill(r,g,b,a);
  ellipse(x,y,diam,diam);
}
View Code

  4.7 使用变量来创建Zoog

float zoogX;
float zoogY;

float eyeR;
float eyeG;
float eyeB;

void setup() {
  size(200,200);
  zoogX = width/2;
  zoogY = height + 100;
}

void draw() {
  background(255);
  
  ellipseMode(CENTER);
  rectMode(CENTER);
  
  stroke(0);
  fill(150);
  rect(zoogX,zoogY,20,100);
  
  stroke(0);
  fill(255);
  ellipse(zoogX,zoogY-30,60,60);
  
  eyeR = random(255);
  eyeG = random(255);
  eyeB = random(255);
  fill(eyeR,eyeG,eyeB);
  ellipse(zoogX-19,zoogY-30,16,32);
  ellipse(zoogX+19,zoogY-30,16,32);
  
  stroke(150);
  line(zoogX-10,zoogY+50,zoogX-10,height);
  line(zoogX+10,zoogY+50,zoogX+10,height);
  
  zoogY = zoogY -1;
}
View Code

  4.8 坐标平移

void setup() {
  size(200,200); 
}

void draw() {
  background(255);
  rectMode(CENTER);
  ellipseMode(CENTER);
  
  translate(mouseX,mouseY);
  
  stroke(0);
  fill(175);
  rect(0,0,20,100);
  
  stroke(0);
  fill(255);
  ellipse(0,-30,60,60);
  
  stroke(0);
  fill(0);
  ellipse(-19,-30,16,32);
  ellipse(19,-30,16,32);
  
  stroke(0);
  line(-10,50,-20,60);
  line(10,50,20,60);
}
View Code

第5章 条件语句

  5.1 布尔表达式

  5.2 条件语句:if,else,else if

  5.3 草图中的条件语句

  5.4 逻辑运算符

  5.5 多个鼠标翻转效果的实现

  5.6 布尔变量

  5.7 弹力球

int x = 0;
int speed = 1;

void setup() {
  size(200,200); 
}

void draw() {
  background(255);
  
  x = x + speed;
  
  if(x > width || x < 0) {
      speed = speed * -1;  
  }
  
  stroke(0);
  fill(175);
  ellipse(x,100,32,32);
}
View Code
float c1 = 0;
float c2 = 255;

float c1Change = 1;
float c2Change = -1;

void setup() {
  size(200,200); 
}

void draw() {
  noStroke();
  
  fill(c1,0,c2);
  rect(0,0,100,100);
  
  fill(c2,0,c1);
  rect(100,0,100,200);
  
  c1 = c1 + c1Change;
  c2 = c2 + c2Change;
  
  if(c1 < 0 || c1 > 255) {
    c1Change *= -1; 
  }
  
  if(c2 < 0 || c2 > 255) {
    c2Change *= -1; 
  }
}
View Code

  5.8 物理学基础

float x = 100;
float y = 0;

float speed = 0;
float gravity = 0.1;

void setup() {
  size(200,200); 
}

void draw() {
  background(255);
  
  fill(0);
  noStroke();
  ellipse(x,y,10,10);
  
  y = y + speed;
  speed = speed + gravity;
  
  if(y > height) {
    speed = speed * -0.95;
    
    y = height;
  }
}
View Code

第6章 循环

  6.1 什么是迭代

迭代(iteration)是指将一系列规则或者步骤不断重复产生的过程.

  6.2 while循环:你唯一真正需要的循环

  6.3 "退出"条件

  6.4 for循环

  6.5 局域变量与全局变量

  6.6 draw()循环内部的循环

  6.7 长出胳膊的Zoog

第7章 函数

  7.1 将代码分解

  7.2 用户自定义函数

  7.3 定义函数

  7.4 简单的模块化

  7.5 实参

  7.6 传递副本

  7.7 返回类型

  7.8 重新整理Zoog

第8章 对象

  8.1 掌握面向对象编程

  8.2 使用对象

  8.3 编写饼干模具的程序

  8.4 使用一个对象的具体步骤

  8.5 使用标签进行组合

  8.6 构造函数参数

  8.7 对象也是数据类型

  8.8 面向对象的Zoog

第9章 数组

  9.1 数组的作用

  9.2 数组是什么

  9.3 声明和创建数组

  9.4 初始化数组

  9.5 数组运算

  9.6 简单的数组示例:蛇

  9.7 对象数组

  9.8 交互式对象

  9.9 Processing的数组函数

  9.10 1001个Zoog

第10章 算法

  10.1 我们现在在哪里?我们将要去哪里

  10.2 算法;跟着你自己的节奏跳舞

  10.3 从概念到部分

  10.4 第1部分:雨水采集器

  10.5 第2部分:相交

  10.6 第3部分:计时器

  10.7 第4部分:雨滴

  10.8 整合

  10.9 为下一步做好准备

Catcher catcher;
Timer timer;
Drop[] drops;

int totalDrops = 0;

void setup() {
  size(400,400);
  
  catcher = new Catcher(32);
  drops = new Drop[1000];
  timer = new Timer(300);
  timer.start();
}

void draw() {
  background(255);
  catcher.setLocation(mouseX,mouseY);
  catcher.display();
  
  if(timer.isFinished()) {
     drops[totalDrops] = new Drop();
     totalDrops++;
     
     if(totalDrops >= drops.length) {
       totalDrops = 0; 
     }
     timer.start();
  }
  
  for(int i = 0; i < totalDrops; i++) {
    drops[i].move();
    drops[i].display();
    if(catcher.intersect(drops[i])) {
      drops[i].caught();
    }
  }
    
}

class Catcher {
  float r;
  color col;
  float x,y;
  
  Catcher(float tempR) {
    r = tempR;
    col = color(50,10,10,150);
    x = 0;
    y = 0;
  }
  
  void setLocation(float tempX,float tempY) {
    x = tempX;
    y = tempY;
  }
  
  void display() {
    stroke(0);
    fill(col);
    ellipse(x,y,r * 2,r * 2);
  }
  
  boolean intersect(Drop d) {
    float distance = dist(x,y,d.x,d.y);
    if(distance < r + d.r) {
      return true; 
    } else {
      return false; 
    }
  }
}

class Drop {
  float x,y;
  float speed;
  color c;
  float r;
  
  Drop() {
    r = 8;
    x = random(width);
    y = -r * 4;
    speed = random(1,5);
    c = color(50,100,150);
  }
  
  void move() {
    y += speed; 
  }
  
  void display() {
    fill(c);
    noStroke();
    
    for(int i = 2; i < r; i++) {
      ellipse(x,y + i * 4,i * 2,i * 2); 
    }
  }
  
  void caught() {
    speed = 0;
    y = -1000;
  }
}

class Timer {
  int savedTime;  // when timer started
  int totalTime;  // how long timer should last
  
  Timer(int tempTotalTime) {
    totalTime = tempTotalTime; 
  }
  
  void start() {
    savedTime = millis(); 
  }
  
  boolean isFinished() {
    int passedTime = millis() - savedTime;
    if(passedTime > totalTime) {
      return true; 
    } else {
      return false; 
    }
  }
}
View Code

第11章 调试

  11.1 建议1:休息一下

  11.2 建议2:让另外一个人参与进来

  11.3 建议3:简化

  11.4 建议4:println()是你的朋友

第12章 库

  12.1 库概述

  12.2 内置库

  12.3 第三方库

  12.4 手动安装库

第13章 数学

  13.1 数学和编程

  13.2 模数

float[] randoms = new float[4];
int index = 0;

void setup() {
  size(200,200);
  for(int i = 0; i < randoms.length; i++) {
    randoms[i] = random(0,256); 
  }
  frameRate(1);
}

void draw(){
  background(randoms[index]);
  index = (index + 1) % randoms.length;
}
View Code

  13.3 随机数

float[] randomCounts;

void setup() {
  size(200,200);
  randomCounts = new float[20];
}

void draw() {
  background(255);
  
  int index = (int)random(randomCounts.length);
  randomCounts[index]++;
  
  stroke(0);
  fill(175);
  for(int x = 0; x < randomCounts.length; x++) {
    rect(x * 10,0,9,randomCounts[x]); 
  }
}
View Code

  13.4 概率回顾

  13.5 代码中的事件概率

void setup() {
  size(200,200);
  background(255);
  noStroke();
}

void draw() {
  float red_prob = 0.60;
  float green_prob = 0.10;
  float blue_prob = 0.30;
  
  float num = random(1);
  
  if(num < red_prob) {
    fill(255,53,2,150); 
  } else if(num < green_prob + red_prob) {
    fill(156,255,28,150); 
  } else {
    fill(10,52,178,150); 
  }
  
  ellipse(random(width),random(height),64,64);
}
View Code

  13.6 Perlin噪声

float time = 0.0;
float increment = 0.01;

void setup() {
  size(200,200); 
}

void draw() {
  background(255);
  float n = noise(time) * width;
  
  fill(0);
  ellipse(width / 2,height / 2,n,n);
  
  time += increment;
}
View Code

  13.7 map()函数

void setup() {
  size(640,360); 
}

void draw() {
  float r = map(mouseX,0,width,0,255);
  float b = map(mouseY,0,height,255,0);
  background(r,0,b);
}
View Code

  13.8 角度

  13.9 三角学

极坐标(polar coordinate),平面上任一点的位置就用该点距离极点的长度,以及该点和极点连线与极轴形成的角度来确定

float r = 75;
float theta = 0;

void setup() {
  size(200,200);
  background(200);
}

void draw() {
  float x = r * cos(theta);
  float y = r * sin(theta);
  
  noStroke();
  fill(0);
  ellipse(x + width / 2,y + height / 2,16,16);
  
  theta += 0.01;
}
View Code

  13.10 振荡

float theta = 0;

void setup() {
  size(200,200); 
}

void draw() {
  background(255);
  
  float x = map(sin(theta),-1,1,0,200);
  
  theta += 0.05;
  
  fill(0);
  stroke(0);
  line(width / 2,0,x,height / 2);
  ellipse(x,height/2,16,16);
}
View Code

  13.11 递归

void setup() {
  size(200,200);
}

void draw() {
  background(255);
  stroke(0);
  noFill();
  drawCircle(width / 2,height / 2,100);
}

void drawCircle(float x,float y,float radius) {
  ellipse(x,y,radius,radius);
  if(radius > 2) {
    drawCircle(x + radius / 2,y,radius / 2);
    drawCircle(x - radius / 2,y,radius / 2);
  }
}
View Code

  13.12 二维数组

Cell[][] grid;

int cols = 10;
int rows = 10;

void setup() {
  size(200,200);
  grid = new Cell[cols][rows];
  for(int i = 0; i < cols; i++) {
    for(int j = 0; j < rows; j++) {
      grid[i][j] = new Cell(i * 20,j * 20,20,20,i + j); 
    }
  }
}

void draw() {
  background(0);
  for(int i = 0; i < cols; i++) {
    for(int j = 0; j < rows; j++) {
      grid[i][j].oscillate();
      grid[i][j].display();
    }
  }
}


class Cell {
  float x,y,w,h;
  float angle;
  
  Cell(float tempX,float tempY,float tempW,float tempH,float tempAngle) {
    x = tempX;
    y = tempY;
    w = tempW;
    h = tempH;
    angle = tempAngle;
  }
  
  void oscillate() {
    angle += 0.02; 
  }
  
  void display() {
    stroke(255);
    
    float bright = map(sin(angle),-1,1,0,255);
    
    fill(bright);
    rect(x,y,w,h);
  }
}
View Code

第14章 三维平移和旋转

  14.1 z坐标轴

void setup() {
  size(200,200); 
}

void draw() {
  background(255);
  stroke(0);
  fill(175);
  
  int mx = constrain(mouseX,0,width);
  int my = constrain(mouseY,0,height);
  
  translate(mx,my);
  ellipse(0,0,8,8);
  
  translate(100,0);
  ellipse(0,0,8,8);
  
  translate(0,100);
  ellipse(0,0,8,8);
  
  translate(-100,0);
  ellipse(0,0,8,8);
}
View Code

  14.2 P3D究竟是什么

像素密度和像素分辨率是不同的,像素分辨率是以像素为单位,由一张图片的实际宽度和高度来定义的.像素密度是通过DPI("每英寸点数"(dots per inch))来衡量的.这里的密度指的是,你显示器的每个物理英寸中有多个像素(也就是点).

  14.3 顶点形状

void setup( ){
  size(200,200,P3D);
}

void draw() {
  beginShape();
  vertex(50,50);
  vertex(150,50);
  vertex(150,150);
  vertex(50,150);
  endShape(CLOSE);
}

void setup( ){
  size(200,200,P3D);
}

void draw() {
  stroke(0);
  fill(175);
  beginShape();
  vertex(50,50);
  vertex(150,25);
  vertex(150,175);
  vertex(25,150);
  endShape(CLOSE);
}

void setup( ){
  size(200,200,P3D);
}

void draw() {
  stroke(0);
  
  for(int i = 0; i < 10; i++) {
    beginShape();
    fill(175);
    vertex(i * 20,10 - i);
    vertex(i * 20 + 15,10 + i);
    vertex(i * 20 + 15,180 + i);
    vertex(i * 20,180 - i);
    endShape(CLOSE);
  }
}

void setup( ){
  size(200,200,P3D);
}

void draw() {
  stroke(0);
  
  beginShape(LINES);
  for(int i = 10; i < width; i += 20) {
    vertex(i,10);
    vertex(i,height - 10);
  }
  endShape();
}


void setup( ){
  size(200,200,P3D);
}

void draw() {
  noFill();
  stroke(0);
  
  beginShape();
  for(int i = 10; i < width; i += 20) {
    vertex(i,10);
    vertex(i,height - 10);
  }
  endShape();
}

void setup( ){
  size(200,200,P3D);
}

void draw() {
  noFill();
  stroke(0);
  beginShape();
  for(int i = 10; i < width; i += 20) {
    curveVertex(i,10);
    curveVertex(i,height - 10);
  }
  endShape();
}
View Code

  14.4 自定义三维图形

  14.5 简单的旋转

void setup() {
  size(200,200); 
}

void draw() {
  background(255);
  stroke(0);
  fill(175);
  
  // Translate origin to center
  translate(width / 2,height / 2);
  
  // theta is a common name of variable to store an angle
  float theta = map(mouseX,0,width,0,TWO_PI);
  
  rotate(theta);
  
  rectMode(CENTER);
  rect(0,0,100,100);
}
View Code

  14.6 围绕不同的轴旋转

float theta = 0.0;

void setup() {
  size(200,200,P3D); 
}

void draw() {
  background(255);
  theta += 0.01;
  
  translate(100,100,0);
  rotateX(theta);
  rotateY(theta);
  drawPyramid(50);
  
  translate(50,50,20);
  drawPyramid(10);
}

void drawPyramid(int t) {
  stroke(0);
  fill(150,0,0,127);
  
  beginShape(TRIANGLES);
  vertex(-t,-t,-t);
  vertex(t,-t,-t);
  vertex(0,0,t);
  
  fill(0,150,0,127);
  vertex(t,-t,-t);
  vertex(t,t,-t);
  vertex(0,0,t);
  
  fill(0,0,150,127);
  vertex(t,t,-t);
  vertex(-t,t,-t);
  vertex(0,0,t);
  
  fill(150,0,150,127);
  vertex(-t,t,-t);
  vertex(-t,-t,-t);
  vertex(0,0,t);
  
  endShape();
}
View Code

  14.7 scale()函数

float r = 0.0;

void setup() {
  size(200,200); 
}

void draw() {
  background(0);
  
  translate(width / 2,height / 2);
  
  scale(r);
  
  stroke(255);
  fill(100);
  rectMode(CENTER);
  rect(0,0,10,10);
  
  r += 0.2;
}
View Code

  14.8 pushMatrix()和popMatrix()函数

float theta1 = 0;
float theta2 = 0;

void setup() {
  size(200,200,P3D); 
}

void draw() {
  background(255);
  stroke(0);
  fill(175);
  rectMode(CENTER);
  
  pushMatrix();
  
  translate(50,50);
  rotateZ(theta1);
  rect(0,0,60,60);
  
  popMatrix();
  
  pushMatrix();
  
  translate(150,150);
  rotateY(theta2);
  rect(0,0,60,60);
  
  popMatrix();
  
  theta1 += 0.02;
  theta2 += 0.02;
}
View Code

  14.9 用Processing模拟太阳系

Planet[] planets = new Planet[8];

void setup() {
  size(200,200);
  
  for(int i = 0; i < planets.length; i++) {
    planets[i] = new Planet(20 + i * 10,i + 8); 
  }
}


void draw() {
  background(255);
  
  pushMatrix();
  translate(width / 2,height / 2);
  stroke(0);
  fill(255);
  ellipse(0,0,20,20);
  
  for(int i = 0; i < planets.length; i++) {
     planets[i].update();
     planets[i].display();
  }
  
  popMatrix();
}

class Planet {
  float theta;
  float diameter;
  float distance;
  float orbitspeed;
  
  Planet(float distance_,float diameter_) {
    distance = distance_;
    diameter = diameter_;
    theta = 0;
    orbitspeed = random(0.01,0.03);
  }
  
  void update() {
    theta += orbitspeed; 
  }
  
  void display() {
    pushMatrix();
    rotate(theta);
    translate(distance,0);
    stroke(0);
    fill(175);
    ellipse(0,0,diameter,diameter);
    popMatrix();
  }  
}
View Code

  14.10 PShape类

PShape star;

void setup() {
  size(200,200);
  star = createShape();
  
  star.beginShape();
  star.fill(102);
  star.stroke(0);
  star.strokeWeight(2);
  
  star.vertex(0,-50);
  star.vertex(14,-20);
  star.vertex(47,-15);
  star.vertex(23,7);
  star.vertex(29,40);
  star.vertex(0,25);
  star.vertex(-29,40);
  star.vertex(-23,7);
  star.vertex(-47,-15);
  star.vertex(-14,-20);
  star.endShape(CLOSE);
}

void draw() {
  background(255);
  translate(mouseX,mouseY);
  shape(star);
}
View Code

第15章 图像

  15.1 图像入门

PImage img;

void setup() {
  size(320,240);
  img = loadImage("runde_bird_cliffs.jpg");
}

void draw() {
  background(0);
  image(img,0,0);
}
View Code
PImage head;
float x,y;
float rot;

void setup() {
  size(200,200);
  head = loadImage("face.jpg");
  x = 0;
  y = width / 2;
  rot = 0;
}

void draw() {
  background(255);
   
  translate(x,y);
  rotate(rot);
  imageMode(CENTER);
  image(head,0,0);
  
  x += 1.0;
  rot += 0.01;
  
  if(x > width) {
     x = 0; 
  }
}
View Code

  15.2 图像的动画效果

  15.3 我的第一个图像处理滤镜

  15.4 图像数组

  size(200,200);
  loadPixels();


  for(int i = 0; i < pixels.length; i++) {
    float rand = random(255);
    color c = color(rand);
    pixels[i] = c;
  }
  
  updatePixels();
View Code  

  15.5 像素,像素,更多的像素

size(200,200);
loadPixels();

for(int x = 0; x < width; x++) {
  for(int y = 0; y < height; y++) {
    int loc = x + y * height; 
    
     if(x % 2 == 0) {
       pixels[loc] = color(255); 
     } else {
       pixels[loc] = color(0); 
     }
  }
}

updatePixels();
View Code

  15.6 图像处理简介

 

PImage img;

void setup() {
  size(200,200);
  img = loadImage("sunflower.jpg");
}

void draw() {
  loadPixels();
  img.loadPixels();
  
  for(int x = 0; x < height; x++) {
    for(int y = 0; y < width; y++) {
      int loc = x + y * height;
      
      float r = red(img.pixels[loc]);
      float g = green(img.pixels[loc]);
      float b = blue(img.pixels[loc]);
      
      pixels[loc] = color(r,b,r);
    }
  }
  
  updatePixels();
}
View Code

  15.7 另外一个图像处理滤镜:制作属于你自己的tint()函数

PImage img;

void setup() {
  size(200,200);
  img = loadImage("sunflower.jpg");
}

void draw() {
  loadPixels();
  img.loadPixels();
  
  for(int x = 0; x < img.width; x++) {
    for(int y = 0; y < img.height; y++) {
      int loc = x + y * img.height;
      
      float r = red(img.pixels[loc]);
      float g = green(img.pixels[loc]);
      float b = blue(img.pixels[loc]);
      
      float distance = dist(x,y,mouseX,mouseY);
      float adjustBrightness = map(distance,0,50,8,0);
      
      r *= adjustBrightness;
      g *= adjustBrightness;
      b *= adjustBrightness;
      
      color c = color(r,g,b);
      pixels[loc] = c;
    }
  }
  
  updatePixels();
}
View Code

  15.8 写入另外一个PImage对象的像素

PImage source;
PImage destination;

void setup() {
  size(200,200);
  source = loadImage("sunflower.jpg");
  destination = createImage(source.width,source.height,RGB);
}

void draw() {
  float threshold = 127;
  source.loadPixels();
  destination.loadPixels();
  
  for(int x = 0; x < source.width; x++) {
    for(int y = 0; y < source.height; y++) {
      int loc = x + y * height;
      
      if(brightness(source.pixels[loc]) > threshold) {
        destination.pixels[loc] = color(255);
      } else {
        destination.pixels[loc] = color(0); 
      }
    }
    
    destination.updatePixels();
    image(destination,0,0);
  }
}
View Code

  15.9 第二阶段:像素组处理

PImage img;         // Source image
PImage destination; // Destination image

void setup() {
  size(200,200);
  img = loadImage("sunflower.jpg");
  destination = createImage(img.width, img.height, RGB);
}

void draw() {
  
  // We are going to look at both image's pixels
  img.loadPixels();
  destination.loadPixels();
  
  // Since we are looking at left neighbors
  // We skip the first column
  for (int x = 1; x < width; x++ ) {
    for (int y = 0; y < height; y++ ) {
      
      // Pixel location and color
      int loc = x + y*img.width;
      color pix = img.pixels[loc];
      
      // Pixel to the left location and color
      int leftLoc = (x - 1) + y*img.width;
      color leftPix = img.pixels[leftLoc];
      
      // New color is difference between pixel and left neighbor
      float diff = abs(brightness(pix) - brightness(leftPix));
      destination.pixels[loc] = color(diff); 
    }
  }
  
  // We changed the pixels in destination
  destination.updatePixels();
  // Display the destination
  image(destination,0,0);
}
View Code

PImage img;
int w = 80;

float[][] matrix = {{-1,-1,-1},
                    {-1,9,-1},
                    {-1,-1,-1}};
                    
void setup() {
  size(200,200);
  img = loadImage("sunflower.jpg");
}

void draw() {
  image(img,0,0);
  
  int xstart = constrain(mouseX - w/2,0,img.width);
  int ystart = constrain(mouseY - w/2,0,img.height);
  int xend = constrain(mouseX + w/2,0,img.width);
  int yend = constrain(mouseY + w/2,0,img.height);
  int matrixsize = 3;
  
  loadPixels();
  for(int x = xstart; x < xend; x++) {
    for(int y = ystart; y < yend; y++) {
      color c = convolution(x,y,matrix,matrixsize,img);
      int loc = x + y * img.width;
      pixels[loc] = c;
    }
  }
  
  updatePixels();
  
  stroke(0);
  noFill();
  rect(xstart,ystart,w,w);
}

color convolution(int x,int y,float[][] matrix,int matrixsize,PImage img) {
  float rtotal = 0.0;
  float gtotal = 0.0;
  float btotal = 0.0;
  
  int offset = matrixsize / 2;
  
  for(int i = 0; i < matrixsize; i++) {
    for(int j = 0; j < matrixsize; j++) {
      int xloc = x + i - offset;
      int yloc = y + j - offset;
      int loc = xloc + img.width * yloc;
      
      loc = constrain(loc,0,img.pixels.length - 1);
      
      rtotal += (red(img.pixels[loc]) * matrix[i][j]);
      gtotal += (green(img.pixels[loc]) * matrix[i][j]);
      btotal += (blue(img.pixels[loc]) * matrix[i][j]);
      
    }
  }
  
  rtotal = constrain(rtotal,0,255);
  gtotal = constrain(gtotal,0,255);
  btotal = constrain(btotal,0,255);
  
  return color(rtotal,gtotal,btotal);
}
View Code

  15.10 具有创意的可视化

PImage img;
int pointillize = 16;

void setup() {
  size(200,200);
  img = loadImage("sunflower.jpg");
  background(0);
}

void draw() {
  int x = int(random(img.width));
  int y = int(random(img.height));
  int loc = x + y * img.width;
  
  img.loadPixels();
  float r = red(img.pixels[loc]);
  float g = green(img.pixels[loc]);
  float b = blue(img.pixels[loc]);
  
  noStroke();
  fill(r,g,b,100);
  ellipse(x,y,pointillize,pointillize);
}
View Code

PImage img;
int cellsize = 2;
int cols,rows;

void setup() {
  size(200,200,P3D);
  img = loadImage("sunflower.jpg");
  cols = width / cellsize;
  rows = height / cellsize;
}

void draw() {
  background(255);
  img.loadPixels();
  for(int i = 0; i < cols; i++) {
    for(int j = 0; j < rows; j++) {
       int x = i * cellsize + cellsize / 2;
       int y = j * cellsize + cellsize / 2;
       int loc = x + y * width;
       color c = img.pixels[loc];
       
       float z = map(brightness(img.pixels[loc]),0,255,0,mouseX);
       
       pushMatrix();
       translate(x,y,z);
       fill(c);
       noStroke();
       rectMode(CENTER);
       rect(0,0,cellsize,cellsize);
       popMatrix();
    }
  }
}
View Code

第16章 视频

  16.1 视频直播

import processing.video.*;

Capture video;

void captureEvent(Capture video) {
   video.read(); 
}

void setup() {
  size(320,240);
  video = new Capture(this,320,240);
  video.start();
}



void draw() {
  image(video,0,0);
}
View Code
import processing.video.*;

Capture video;

void setup() {
  size(320,240);
  video = new Capture(this,320,240);
  video.start();
}

void captureEvent(Capture video) {
  video.read(); 
}

void draw() {
  background(255);
  
  tint(mouseX,mouseY,255);
  translate(width / 2,height / 2);
  imageMode(CENTER);
  rotate(PI / 4);
  image(video,0,0,mouseX,mouseY);
}
View Code
import processing.video.*;

Capture video;

void setup() {
  size(320,240);
  
  video = new Capture(this,320,240);
  video.start();
}

void captureEvent(Capture video) {
  video.read(); 
}

void draw() {
  loadPixels();
  video.loadPixels();
  
  for(int x = 0; x < video.width; x++) {
    for(int y = 0; y < video.height; y++) {
      int loc = x + y * video.width;
      
      float r = red(video.pixels[loc]);
      float g = green(video.pixels[loc]);
      float b = blue(video.pixels[loc]);
      
      float d = dist(x,y,mouseX,mouseY);
      float adjustbrightness = map(d,0,100,4,0);
      r *= adjustbrightness;
      g *= adjustbrightness;
      b *= adjustbrightness;
      
      r = constrain(r,0,255);
      g = constrain(g,0,255);
      b = constrain(b,0,255);
      
      color c = color(r,g,b);
      pixels[loc] = c;
    }
  }
  
  updatePixels();
}
View Code

  16.2 已录制的视频

import processing.video.*;

Movie movie;

void setup() {
  size(320,240);
  movie = new Movie(this,"cat.mov");
  movie.loop();
}

void movieEvent(Movie movie) {
  movie.read(); 
}

void draw() {
  image(movie,0,0); 
}
View Code

  16.3 软件镜像

int videoScale = 8;
int cols,rows;

void setup() {
  size(640,480);
  cols = width / videoScale;
  rows = height / videoScale;
}

void draw() {
  for(int i = 0; i < cols; i++) {
    for(int j = 0; j < rows; j++) {
      int x = i * videoScale;
      int y = j * videoScale;
      fill(255);
      stroke(0);
      rect(x,y,videoScale,videoScale);
    }
  }
}
View Code
import processing.video.*;

int videoScale = 4;
int cols,rows;
Capture video;

void setup() {
  size(640,480);
  cols = width / videoScale;
  rows = height / videoScale;
  background(0);
  video = new Capture(this,cols,rows);
  video.start();
}

void captureEvent(Capture video) {
  video.read(); 
}

void draw() {
  video.loadPixels();
  
  for(int i = 0; i < cols; i++) {
    for(int j = 0; j < rows; j++) {
      int x = i * videoScale;
      int y = j * videoScale;
      
      color c = video.pixels[i + j * video.width];
      
      fill(c);
      stroke(0);
      rect(x,y,videoScale,videoScale);
    }
  }
}
View Code
import processing.video.*;

int videoScale = 4;
int cols,rows;
Capture video;

void setup() {
  size(640,480);
  cols = width / videoScale;
  rows = height / videoScale;
  background(0);
  video = new Capture(this,cols,rows);
  video.start();
}

void captureEvent(Capture video) {
  video.read(); 
}

void draw() {
  video.loadPixels();
  
  for(int i = 0; i < cols; i++) {
    for(int j = 0; j < rows; j++) {
      int x = i * videoScale;
      int y = j * videoScale;

      int loc = (video.width - i - 1) + j * video.width;
      
      color c = video.pixels[loc];
      float sz = (brightness(c) / 255) * videoScale;
      
      rectMode(CENTER);
      fill(255);
      noStroke();
      rect(x + videoScale / 2,y + videoScale / 2,sz,sz);
    }
  }
}
View Code

float x,y;

void setup() {
  size(320,240);
  background(255);
  x = width / 2;
  y = height / 2;
}

void draw() {
  float newx = constrain(x + random(-20,20),0,width);
  float newy = constrain(y + random(-20,20),0,height);
  
  stroke(0);
  strokeWeight(4);
  line(x,y,newx,newy);
  
  x = newx;
  y = newy;
}
View Code

import processing.video.*;

float x,y;

Capture video;

void setup() {
  size(320,240);
  background(0);
  x = width / 2;
  y = height / 2;
  
  video = new Capture(this,width,height);
  video.start();
}

void captureEvent(Capture video) {
  video.read(); 
}

void draw() {
  video.loadPixels();
  
  float newx = constrain(x + random(-20,20),0,width - 1);
  float newy = constrain(y + random(-20,20),0,height - 1);
  
  int midx = int((newx + x) / 2);
  int midy = int((newy + y) / 2);
  color c = video.pixels[(width - 1 - midx) + midy * video.width];
  
  stroke(c);
  strokeWeight(4);
  line(x,y,newx,newy);
  
  x = newx;
  y = newy;
}
View Code

  16.4 视频作为传感器和计算机视觉

  16.5 背景消除

import processing.video.*;

Capture video;
PImage backgroundImage;
float threshold = 20;

void setup() {
  size(320,240);
  video = new Capture(this,width,height);
  video.start();
  
  backgroundImage = createImage(video.width,video.height,RGB);
}

void captureEvent(Capture video) {
  video.read(); 
}

void draw() {
  loadPixels();
  video.loadPixels();
  backgroundImage.loadPixels();
  
  image(video,0,0);
  
  for(int x = 0; x < video.width; x++) {
    for(int y = 0; y < video.height; y++) {
      int loc = x + y * video.width;
      
      color fgColor = video.pixels[loc];
      color bgColor = backgroundImage.pixels[loc];
      
      float r1 = red(fgColor);
      float g1 = green(fgColor);
      float b1 = blue(fgColor);
      
      float r2 = red(bgColor);
      float g2 = green(bgColor);
      float b2 = blue(bgColor);
      
      float diff = dist(r1,g1,b1,r2,g2,b2);
      
      if(diff < threshold) {
        pixels[loc] = fgColor;
      } else {
        pixels[loc] = color(0,255,0); 
      }
    }
  }
  
  updatePixels();
}

void mousePressed() {
  backgroundImage.copy(video,0,0,video.width,video.height,0,0,video.width,video.height);
  backgroundImage.updatePixels();
}
View Code

  16.6 运动检测

import processing.video.*;

Capture video;
PImage prevFrame;
float threshold = 50;

void setup() {
  size(320,240);
  video = new Capture(this,width,height,30);
  video.start();
  
  prevFrame = createImage(video.width,video.height,RGB);
}

void captureEvent(Capture video) {
  prevFrame.copy(video,0,0,video.width,video.height,0,0,video.width,video.height);
  prevFrame.updatePixels();
  video.read();
}

void draw() {
  loadPixels();
  video.loadPixels();
  prevFrame.loadPixels();
  

  for(int x = 0; x < video.width; x++) {
    for(int y = 0; y < video.height; y++) {
      int loc = x + y * video.width;
      
      color current = video.pixels[loc];
      color previous = prevFrame.pixels[loc];
      
      float r1 = red(current);
      float g1 = green(current);
      float b1 = blue(current);
      float r2 = red(previous);
      float g2 = green(previous);
      float b2 = blue(previous);
      
      float diff = dist(r1,g1,b1,r2,g2,b2);
      
      if(diff > threshold) {
        pixels[loc] = color(0); 
      } else {
        pixels[loc] = color(255); 
      }
    }
  }
  
  updatePixels();
}
View Code
import processing.video.*;

Capture video;
PImage prevFrame;
float threshold = 50;

void setup() {
  size(320,240);
  video = new Capture(this,width,height);
  video.start();
  prevFrame = createImage(video.width,video.height,RGB);
}

void captureEvent(Capture video) {
  prevFrame.copy(video,0,0,video.width,video.height,0,0,video.width,video.height);
  prevFrame.updatePixels();
  video.read();
}

void draw() {
  background(0);
  image(video,0,0);
  
  loadPixels();
  video.loadPixels();
  prevFrame.loadPixels();
  
  float totalMotion = 0;
  
  for(int i = 0; i < video.pixels.length; i++) {
    color current = video.pixels[i];
    color previous = prevFrame.pixels[i];
    
    float r1= red(current);
    float g1 = green(current);
    float b1 = blue(current);
    
    float r2 = red(previous);
    float g2 = green(previous);
    float b2 = blue(previous);
    
    float diff = dist(r1,g1,b1,r2,g2,b2);
    
    totalMotion += diff;
  }
  
  float avgMotion = totalMotion / video.pixels.length;
  
  fill(0);
  float r = avgMotion * 2;
  ellipse(width / 2,height / 2,r,r);
}
View Code

  16.7 计算机视觉库

第17 章 文本

  17.1 字符串从哪来

  17.2 什么是字符串

  17.3 显示文字

PFont f;

void setup() {
  size(200,200);
  f = createFont("Georgia",16);
}

void draw() {
  background(255);
  textFont(f,16);
  fill(0);
  text("To be or not to be.",10,100);
}
View Code

  17.4 文字的动态效果

PFont f;

void setup() {
  size(400,200);
  f = createFont("Georgia",16);
}

void draw() {
  background(255);
  
  stroke(175);
  line(width / 2,0,width / 2,height);
  
  textFont(f);
  fill(0);
  
  textAlign(CENTER);
  text("This text is centered",width / 2,60);
  
  textAlign(LEFT);
  text("This text is left aligned",width / 2,100);
  
  textAlign(RIGHT);
  text("This text is right aligned",width / 2,140);
}
View Code
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);
  x = width;
}

void draw() {
  background(255);
  fill(0);
  
  textFont(f,16);
  textAlign(LEFT);
  text(headlines[index],x,180);
  
  x = x - 3;
  
  float w = textWidth(headlines[index]);
  
  if(x < -w) {
    x = width;
    index = (index + 1) % headlines.length;
  }
}
View Code

  17.5 文字马赛克

import processing.video.*;

int videoScale = 4;
int cols,rows;
Capture video;

String chars = "helloworld";
PFont f;

void setup() {
  size(640,480);
  cols = width / videoScale;
  rows = height / videoScale;
  video = new Capture(this,cols,rows);
  video.start();
  f = createFont("Courier",16);
}

void captureEvent(Capture video) {
  video.read(); 
}

void draw() {
  background(0);
  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);
      text(chars.charAt(charcount),x,y);
      charcount = (charcount + 1) % chars.length();
    }
  }
}
View Code

  17.6 旋转文字

PFont f;
String message = "this text is spinning";
float angle;

void setup() {
  size(200,200);
  f = createFont("Arial",20);
}

void draw() {
  background(255);
  fill(0);
  
  textFont(f);
  translate(width / 2,height / 2);
  rotate(angle);
  textAlign(CENTER);
  text(message,0,0);
  angle += 0.05;
}
View Code

  17.7 按字符逐一显示文字

PFont f;
String txt = "Each character is not written individually.";

void setup() {
  size(400,200);
  f = createFont("Arial",20);
}

void draw() {
  background(255);
  fill(0);
  textFont(f);
  
  int x = 10;
  for(int i = 0; i < txt.length(); i++) {
    textSize(random(12,36));
    text(txt.charAt(i),x,height / 2);
    x += textWidth(txt.charAt(i));
  }
}
View Code

PFont f;
String message = "click mouse to shake it up";
Letter[] letters;

void setup() {
  size(260,200);
  f = createFont("Arial",20);
  textFont(f);
  
  letters = new Letter[message.length()];
  
  int x = 16;
  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);
  }
  
  void home() {
    x = homex;
    y = homey;
  }
}
View Code

PFont f;
float r = 100;
float w = 40;
float h = 40;

void setup() {
  size(320,320); 
}

void draw() {
  background(255);
  translate(width / 2,height / 2);
  noFill();
  stroke(0);
  ellipse(0,0,r * 2,r * 2);
  
  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;
  }
}
View Code

String message = "text along a curve";
PFont f;
float r = 100;

void setup() {
  size(320,320);
  f = createFont("Georgia",40,true);
  textFont(f);
  textAlign(CENTER);
}

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;
    float theta = PI + arcLength / r;
    
    pushMatrix();
    translate(r * cos(theta),r * sin(theta));
    
    rotate(theta + PI / 2);
    fill(0);
    text(currentChar,0,0);
    popMatrix();
    arcLength += w / 2;
  }
}
View Code

第18章 数据输入

  18.1 字符串的操作

  18.2 拆分和组合

PFont f;

String typing = "";
String saved = "";

void setup() {
  size(300,200);
  f = createFont("Arial",16);
}

void draw() {
  background(255);
  int indent = 25;
  
  textFont(f);
  fill(0);
  
  text("Click in this sketch and type. \nHit return to save what you typed.",indent,40);
  text(typing,indent,90);
  text(saved,indent,130);
}

void keyPressed() {
  if(key == '\n') {
    saved = typing;
    typing = "";
  } else {
    typing = typing + key; 
  }
}
View Code

  18.3 处理数据

  18.4 处理文本文件

  18.5 表格数据

  18.6 非标准化格式的数据

  18.7 文本分析

  18.8 XML

 

  18.9 使用Processing的XML类

  18.10 JSON

  18.11 JSONObject 和 JSONArray

  18.12 线程

  18.13 API

第19章 数据流

  19.1 网络通信

  19.2 创建服务器

  19.3 创建客户端

  19.4 广播

  19.5 多用户通信,第1部分:服务器

  19.6 多用户通信,第2部分:客户端

  19.7 多用户通信,第3部分:组合

  19.8 串行通信

  19.9 使用信号交换的串行通信

  19.10 使用字符串的串行通信

第20章 声音

  20.1 基础的声音波房

  20.2 关于声音的播放的更多内容

  20.3 声音合成

  20.4 声音分析

  20.5 声音阈值

  20.6 频谱分析

第21章 导出

  21.1 导出至Web

  21.2 独立的应用程序

  21.3 高分辨PDF文件

  21.4 图像和saveFrame()

  2.15 录制视频

第22章 高级的面向对象编程

  22.1 封装

  22.2 继承

  22.3 一个继承的示例:图形

  22.4 多态性

  22.5 重载

第23章 Java

  23.1 揭开Processing魔法

  23.2 如果不使用Processing,代码看上去会是什么样子

  23.3 探索Java API

  23.4 其他有用的Java类:ArrayList

  23.5 其他有用的Java类:Rectangle

  23.6 异常(错误)处理

  23.7 Processing之外的Java

转载于:https://www.cnblogs.com/revoid/p/9764535.html

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值