1.概念介绍
2.参考案例
3.个人作品
一、概念介绍
- Processing中的向量
向量实则时两点之间的差异,也就是从一个点到另一个点的移动。向量实际上描述的时路径的一个路线过程,但是它与路径不同的是,它带有方向。由起点指向终点。
- 位置向量和速度向量
- 向量的加法
我所理解的向量的加法,就是使得所有需要相加向量首尾相连,最后只要连接最首端以及最末端,由最首端指向最末端得向量实则为它们相加后所得的向量
- 向量的减法
三角形定则解决向量加法的方法:将各个向量依次首尾顺次相接,结果为第一个向量的起点指向最后一个向量的终点
二、参考案例
1.案例一:
-
案例介绍:向量的运动——速度。利用向量对运动进行编程模拟,制作一个弹球程序。在这个例子中,屏幕中的对象有自己的位置(任意给定时刻的位置)和速度(物体在下一秒该如何运动),位置加上当前速度可以得到一个新的位置
-
步骤
(1)当前位置加上速度得到一个新的位置
(2)在新的位置上绘制对象 -
类的设计
将设计一个类,进行面向对象的编程。
类的变量有:
1.移动的物体的位置
2.移动的物体的速度
类的方法有:
1.构造函数(初始化位置和速度)
2.更新函数(更新当前物体在屏幕上的位置)
3.显示函数(显示更新后的物体的位置,将其绘制出来)
4.判断边界函数(当物体运动到窗口的边界时,重置位置,假设此时已经运动到了最左端,则改变它的横坐标到最右端,即到了边界改变位置为边界的另一边)
-
代码展示
这里对于原始的代码进行了小小的修改,增加了游走的对象,以及改变了每个对象的颜色,方便区分
//参考案例1:速度的练习
Mover[] mover=new Mover[10];
void setup() {
size(400, 200);
smooth();
//新建10个游走对象
for (int i=0; i<10; i++) {
mover[i]=new Mover();
}
}
void draw() {
background(217, 127, 127);
for (int i=0; i<10; i++) {
mover[i].update();
mover[i].checkEdges();
mover[i].display();
}
}
class Mover {
private PVector location;//位置
private PVector velocity;//速度
//构造函数
public Mover() {
//初始化位置和速度,使用随机数生成
location=new PVector(random(width), random(height));
velocity=new PVector(random(-2, 2), random(-2, 2));
}
//更新位置
public void update() {
//当前位置加上速度,得到一个新的位置
location.add(velocity);
}
//绘制游走的球
public void display() {
stroke(0);
fill(random(125, 255), random(0, 255), random(125, 255));
ellipse(location.x, location.y, 16, 16);
}
//判断是否到达了边界
public void checkEdges() {
if (location.x>width) {
location.x=0;
} else if (location.x<0) {
location.x=width;
}
if (location.y>height) {
location.y=0;
} else if (location.y<0) {
location.y=height;
}
}
}
- 效果展示
2.案例二:
-
案例简介:
向量的运动:加速度+交互。为了使得运行效果更加有趣,这里加入了加速度。这里所指的加速度的严格定义是:速度的变化率。从本质上说,这是一种“涓滴”效应。加速度影响速度。继而影响位置。
这里采用的加速度算法是:朝着鼠标所在的方向的加速度 -
初步实现:小球的加速运动
1.设置小球的初始速度为0
2.每次累加随机的加速度,这里体现的是一个累加效应,因此每次的加速度的值不要设置得很大 -
小球的加速运动代码展示
//习作二:参考案例二
Mover[] mover=new Mover[10];
void setup() {
size(400, 200);
smooth();
//新建10个游走对象
for (int i=0; i<10; i++) {
mover[i]=new Mover();
}
}
void draw() {
background(217, 127, 127);
for (int i=0; i<10; i++) {
mover[i].update();
mover[i].checkEdges();
mover[i].display();
}
}
class Mover {
private PVector location;//位置
private PVector velocity;//速度
private PVector acceleration;//新的加速度向量
private float topspeed;
//构造函数
public Mover() {
//初始化位置和速度,首先将物体放置于屏幕的中间,初始化速度为0
//即初始的时候物体是禁止不动的
location=new PVector(random(width), random(height/2));
velocity=new PVector(0, 0);
//加速度
acceleration=new PVector(-0.001, 0.01);
//速度的限制
topspeed=10;
}
//更新位置
public void update() {
//给速度加上加速度,这里会有一个累加效应
velocity.add(acceleration);
//限制速度的大小
velocity.limit(10);
//当前位置加上速度,得到一个新的位置
location.add(velocity);
}
//绘制游走的球
public void display() {
stroke(0);
fill(random(125, 255), random(0, 255), random(125, 255));
ellipse(location.x, location.y, 16, 16);
}
//判断是否到达了边界
public void checkEdges() {
if (location.x>width) {
location.x=0;
} else if (location.x<0) {
location.x=width;
}
if (location.y>height) {
location.y=0;
} else if (location.y<0) {
location.y=height;
}
}
}
-
小球的加速运动效果展示
-
加速度的交互
添加鼠标与加速度之间的交互,使得物体有着朝着鼠标方向的加速度。我们所要得到的向量是物体所在位置指向鼠标所在位置的一条向量。我们需要计算这条向量,需要根据两个点的位置进行减法运算。
dy=mouseY-y
dx=mouseX-x
在PVector类中,可以使用sub函数实现该功能。
注意:为了设置加速度的大小,必须单位话方向向量。只要能将方向向量缩短到1,就能够得到一个只代表方向的单位向量,可以将它的值设置为任意值
-
加速度交互的实现
(1)计算由物体指向鼠标的向量
(2)单位化该向量
(3)改变以上单位向量的长度(乘以某个合适的值)
(4)将步骤(3)中得到的向量赋予给加速度
三、个人作品
作品一:数学公式的结合
1.基本想法
之前案例中实现过小球跟随鼠标运动,即把鼠标所在位置作为引力中心。而小球的位置是随机分布的。这里想到使用最浪漫的一个数学公式,将小球的分布位置控制,即:笛卡尔心形公式。小球的颜色和大小由鼠标的上移和下移键盘控制。
2.原理简介
3.效果展示
4.代码展示
//习作二:参考案例二
float ballSize=3;
color c=color(255,255,255);
Mover[] mover=new Mover[1000];
void setup() {
size(400, 400);
smooth();
//新建10个游走对象
for (int i=0; i<1000; i++) {
mover[i]=new Mover();
}
}
void mouseWheel(MouseEvent event) {
float e = event.getCount();
if(e<0){
ballSize++;
}
else if(e>0&&ballSize>=2){
ballSize--;
}
if(ballSize<2){
ballSize=2;
}
c=color(random(125,255),random(200,255),random(180,250));
}
void draw() {
background(0);
for (int i=0; i<1000; i++) {
mover[i].update();
mover[i].checkEdges();
mover[i].display();
}
}
class Mover {
private PVector location;//位置
private PVector velocity;//速度
private PVector acceleration;//新的加速度向量
private float topspeed;
private float t;//心形曲线控制的参数
//构造函数
public Mover() {
//初始化位置和速度,首先将物体放置于屏幕的中间,初始化速度为0
//即初始的时候物体是禁止不动的
t=random(0,2*PI);
float a=100;
float x= a*(2*cos(t)-cos(2*t));
float y=a*(2*sin(t)-sin(2*t));
location=new PVector(random(x), random(y));
velocity=new PVector(0, 0);
//加速度
//速度的限制
topspeed=10;
}
//更新位置
public void update() {
PVector mouse=new PVector(mouseX,mouseY);
PVector dir=PVector.sub(mouse,location);
//单位化
dir.normalize();
dir.mult(0.5);
acceleration=dir;
//给速度加上加速度,这里会有一个累加效应
velocity.add(acceleration);
//限制速度的大小
velocity.limit(10);
//当前位置加上速度,得到一个新的位置
location.add(velocity);
}
//绘制游走的球
public void display() {
//stroke(0);
noStroke();
fill(c);
ellipse(location.x, location.y, ballSize,ballSize);
}
//判断是否到达了边界
public void checkEdges() {
if (location.x>width) {
location.x=0;
} else if (location.x<0) {
location.x=width;
}
if (location.y>height) {
location.y=0;
} else if (location.y<0) {
location.y=height;
}
}
}
作品二:引力三角形
1.基本想法
基于前面的两个案例。本着本章是关于向量的运用,以及添加一些交互的原则,目的是实现一个三角形中心跟随鼠标旋转的系统。以三角形到鼠标的向量与三角形原来的垂直距离之间的夹角为旋转角进行旋转,将会实现鼠标到达何处,所有的三角形都会指向鼠标所在位置。
2.原理简介
主要是利用三角形中心到鼠标指向鼠标的向量与三角形与垂直方向上的距离的夹角作为旋转角。需要通过判断鼠标此时所在位置,三角形所在位置,以及两者之间所形成的夹角实现。同时还需要对四个象限做不同的处理,因为在数学中求夹角的公式夹角的范围限定在0-PI/2中
相关的计算公式如下:
3.代码分析
1.构造小三角形类
其中包括一些基础的变量,三角形需要旋转的角度,三角形的中心坐标,三角形的大小比例。
(1)首先在初始化时,就应该指定三角形的大小、三角形的中心坐标
(2)其次设置函数计算三角形需要旋转的度数
(3)最后在图像上绘制三角形
2.增加交互
通过鼠标点击可以对三角形的颜色进行修改
4.代码展示
smallPiece[] small=new smallPiece[100];
float t=0;
//三角形是否闪动的标志
boolean lightFlag=false;
void setup() {
size(500, 500);
for (int i=0; i<100; i++) {
small[i]=new smallPiece((int)random(0, width), (int)random(0, height),random(0.1,1));
}
}
void draw() {
background(0);
// rectDraw();
for (int i=0; i<100; i++) {
small[i].calDegree();
small[i].drawSelf();
}
}
void mouseClicked()
{
if(lightFlag){
lightFlag=false;
}else{
lightFlag=true;
}
}
void rectDraw()
{
translate(100, 100);
rotate(t);
rect(-26, -26, 52, 52);
//translate(-100,-100);
}
//关于小三角形的类
class smallPiece {
//小三角形的中心坐标
private int x;
private int y;
//小三角形需要旋转的角度
private float theta;
//三角形的大小
private float scale;
//构造函数1
public smallPiece() {
super();
}
//构造函数2
public smallPiece(int x, int y,float scale) {
this.x=x;
this.y=y;
theta=0;
this.scale=scale;
fill(random(125,255), random(125,255), random(125,255));
}
//计算需要旋转的角度
public void calDegree() {
if(lightFlag)fill(random(125,255), random(125,255), random(125,255));
float value=abs(mouseY-y)/(pow(mouseX-x, 2)+pow(mouseY-y, 2));
//计算该物体与鼠标的夹角
//第三象限
if (mouseX<x&&mouseY>y)theta=degrees(acos(value));
//第一象限
else if (mouseX>x&&mouseY<y)theta=degrees(acos(value)+180);
//第二象限
else if (mouseX<=x&&mouseY<y)theta=degrees(-(acos(value)+180));
//第四象限
else if (mouseX>=x&&mouseY>y)theta=degrees(-(acos(value)-270));
//print(theta);
//if(mouseY>y)theta=degrees(acos(value)+90);
}
//绘制三角形
public void drawSelf() {
pushMatrix();
//根据夹角,旋转度数
translate(x, y);
rotate(theta);
triangle(-20*scale, 0, 20*scale, 0, 0, 25*scale);
translate(-x, -y);
popMatrix();
}
}