Processing之运动

运动

一.帧

1.1定义

      为了创建流畅的动画,Processing尝试以每秒60帧的速率在draw()函数中运行代码。一帧即draw()函数运行一次,帧频率是每秒钟运行了多少帧。因此,一个程序每秒运行60帧意味着每秒钟draw()函数中的全部代码运行了60次。

1.2观察帧频率

      为了确认帧频率,运行这个程序并查看控制台输出的值(frameRate变量持续跟踪程序的速率)。代码如下:

void  draw(){

println(frameRate);

}

1.3设置帧频率

      frameRate()函数改变程序运行的频率。代码如下:

void setup(){

frameRate(30);//每秒30帧

}

void  draw(){

println(frameRate);

}

      注意:Processing一般以每秒60帧的速度运行代码,如果运行一个draw()方法的时间超过1/60秒,那么帧频率就会降低。frameRate()函数指定的只是最大帧帧频率。

二.速度和方向

      为了创建流畅运动的先例,我们使用一种叫做浮点型的数据类型,这种变量存储带小数点的数,这为运动提供了更强大的表现能力。

2.1移动图形

      案例代码如图1

                                           图1

      保存运行如图2

                        图2

      注意:运行代码时,我们可以发现图形从左边往右边运动,当x的值比窗口宽度大时,图形从右侧缓慢消失。x的值会持续增加,但看不见了图形。

1.4循环

      案例代码如图3

                                         图3

      保存并运行如图4

                      图4

      注意:图3中代码比图1多了一个判断。在draw()函数每次运行的时候,代码都检测x的值是否已经超出屏幕的宽度(加上图形半径)。如果超过,我们设置x的值为负,这样他就可以继续增加,从屏幕左侧出现,实现一个循环,而不是像图2运行只出现一次。

1.5折返

      当图形撞击到边缘时让它反向,而不是穿过边界重新从左侧出现。为了实现这种效果,我们添加一个新的变量来存储图形的方向。方向值为1的时候图形向右运动,当图形为-1时图形向左运动。案例代码如下:

int radius=40;
float x=110;
float speed=0.5;
int direction=1;
void setup(){
  size(240,120);
  ellipseMode(RADIUS);
}
void draw(){
  background(0);
  x+=speed*direction;
  if((x>width-radius)||(x<radius)){
    direction=-direction; //反转方向
  }
  if(direction==1){
    arc(x,60,radius,radius,0.52,5.76);//面向右边

}
    else{
      arc(x,60,radius,radius,3.67,8.9);//面向左边
    }
}

      保存并运行如图5

                        图5

      当图形接触到边缘时,代码通过改变dircetion变量的符号来改变图形方向。比如说当图形接触到一个边缘时,如果direction是正的,代码会将它变成负的。

二.补间动画

      有时候我们想让一个图形从屏幕的某处移动到另一个位置。用几行代码可以设置运动的起点和终点,每帧计算两点间的位置。

2.1计算补间位置

      为了实现补间动画,我们在顶部创建了一组变量。多运行几次这段代码,然后改变它们的值来看看代码如何用不同的速度从一个点移到另外一个点。改变step变量改变速度。案例代码如下:

int startX=20;    //计算x的起始坐标
int stopX=160; //计算x的终止坐标
int startY=30; //计算y的起始坐标
int stopY=80; //计算y的终止坐标
float x=startX;//当前x坐标
float y=startY;//当前y坐标
float step=0.005; //每一步的尺寸(0.0到1.0)
float pct=0.0;//运行过的百分比(0.0到1.0)
void setup(){
  size(240,120);
}
void draw(){
  background(0);
  if(pct<1.0){
    x=startX+((stopX-startX)*pct);
    y=startY+((stopY-startY)*pct);
    pct +=step;
  }
  ellipse(x,y,20,20);
}
       保存并运行如图6

 

                         图6

三.随机

3.1生成随机数

       我们可以用随机数模拟现实世界中不确定的特征。random()函数计算这样的数值,我们可以在程序中设置一个范围来调整这些随机数。

       案例代码如下:

void draw(){

float r=random(0.mouseX);

println(r);

}

       上面这个案例可在控制台输出随机数,由鼠标控制它生成的范围。random()函数通常返回一个浮点数的值,因此要保证赋值符号左边的变量也是float类型。

3.2随机绘制

       案例代码如图7

                                              图7

保存并运行如图8

                              图8

       当鼠标向左时变化很小,当鼠标向右时变化很大,random()函数生成的值变大,运动会变得更加剧烈。因为random()函数在for循环中,执行时每条线都会有一个新的计算值。

3.3随机移动图形

       当移动屏幕中图形时,随机值可以让图形出现的更加自然。

       案例代码如图9

                                    图9

       保存并运行如图10

                     图10

       图10中我们可以发现之前运行过的轨迹都存在,这是因为没有使用background()函数,如果使用我们可以发现只有一个圆在中。盯着这个案例运行久点可以发现圆形移出来屏幕又运动回来。这是偶然的,我们可以添加一些if结构或者使用constrain()函数来保证圆形不离开屏幕外。constrain()函数可以将一个值限定在一个范围内,这样可以将x和y保持在运行窗口之内。替换draw()函数里面的代码如下:

void draw(){

x+=random(-speed,speed);

y+=random(-speed,speed);

x=constrain(x,0,width);

y=constrain(y,0,height);

ellipse(x,y,diameter,diameter);

}

四.计时器

       每一个Processing程序都会计算运行时间。它用以毫秒为单位来计算(1/1000秒)。因此,经过1s后它会记为1000,一分钟以后会记为60000.我们可以用这个计时器在特定的时间点触发动画。millis()函数用来返回计数器的值。

4.1经过时间

       查看经过时间代码如下:

void setup(){

size(240,120);

}

void draw(){

int timer=millis();

println(timer);

}

4.2触发时间事件

       当与if结合时,从millis()函数中返回的值可以被用于程序中的序列动画和事件。案例代码如图11

                                    图11

保存并运行如图12

              图12

       当2s过去后,if块中的代码可以触发一个变化。在图11中,变量timer1和timer2决定了什么时候去改变x变量的值。

五.圆周

5.1正弦波形的值

      案例代码如下:

float angle=0.0;

void setup(){

size(240,120);

}

void draw(){

float sinval=sin(angle);

println(sinval);

float gray=map(sinval,-1,1,0,255);

background(gray);

angle+=0.1;

}

      案例代码中sin()函数的值在角度增加的过程中是从-1~1循环的。使用map()函数后,sinval变量的范围被转变为0~255.这个新的值被用来设置窗口背景的颜色。当代码运行时候我们可以发现颜色不断变化。

5.2正弦波运动

      案例代码如图13

                                        图13

保存并运行如图14

                        图14

5.3圆周运动

      当sin()和cos()函数一起使用时,它们可以生成圆周运动。cos()函数的值提供了x坐标,sin()函数的值提供了y坐标。两个值都乘以scalar的变量来改变运动的半径,并使用offset值来设置圆周的中心。

      案例代码如图15

     

                                        图15

      保存并运行如图16

                        图16

5.4螺旋

      当在每一帧稍微增加scalar的值会产生螺旋形而不是圆形。案例代码如图17

                                        图17

      保存并运行如图18

                  图18

六.运动案例

      机器人代码如下:

float x=180;//x坐标

float y=400;//y坐标

float bodyHeight=153;//身体高度

float neckHeight=56;//脖子高度

float radius=45;//头的半径

float angle=0.0;//运动的角度

void setup(){

size(360,480);

ellipseMode(RADIUS);

background(0,153,204);//蓝色的背景

}

void draw(){

//通过一个小的随机值造成位置的变化

x+=random(-4,4);

y+=random(-1,1);

//改变脖子的高度

neckHeight=80+sin(angle)*30;

angle+=0.05;

//调整头的高度

float ny=y-bodyHeight-neckHeight-radius;

//脖子

stroke(255);

line(x+2,y-bodyHeight,x+2,ny);

line(x+12,y-bodyHeight,x+12,ny);

line(x+22,y-bodyHeight,x+22,ny);

//天线

line(x+12,ny,x-18,ny-43);

line(x+12,ny,x+42,ny-99);

line(x+12,ny,x+78,ny+15);

//身体

noStroke();

fill(255,204,0);

ellipse(x,y-33,33,33);

fill(0);

rect(x-45,y-bodyHeight,90,bodyHeight-33);

fill(255,204,0);

rect(x-45,y-bodyHeight+17,90,6);

//头部

fill(0);

ellipse(x+12,ny,radius,radius);

fill(255);

ellipse(x+24,ny-6,14,14);
fill(0);

ellipse(x+24,ny-6,3,3);

}

      保存运行如图19

                              图19

  • 21
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梦之妹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值