码绘VS手绘|processing“运动”主题创作——如何让一只沙雕鸟起飞

目录

一、代码逻辑

二、理论对比

三、参考资料


最终作品效果可以看上传在B站的视频:https://www.bilibili.com/video/av36523799

第一次码绘VS手绘指路:https://blog.csdn.net/qq_37787956/article/details/84200103

一、代码逻辑

在第一次尝试中,绘制了一个十分简单的小人,它不会动,也不能和用户进行交互。

对于艺术创意编程来说,实在是一个无趣的作品,如何让静止的作品动起来,是这次尝试主要要实现的目标。

首先,准备一幅静态的作品:

这只小鸟激发了我创作的热情[○・`Д´・ ○],贴出我的手绘作品。

 

然后 ,你需要把你的创作对象放在坐标轴里肢解,规划好各个部分的排列顺序,因为上一次实践中并没有尝试任意曲线的绘制,这次尝试一下。

设计好了之后,就可以创建一张画布开始绘制了。

 

真正绘制起来就很随心随性了,你会发现既不像你找的图,也不像你画的图,这就是创作的乐趣所在,永远有你想不到的惊喜emmm 

接下来,我们要怎么让它动起来,应该实际来说有两种可行的解决方法,一是让小鸟自己动,二是让背景动起来。

在这里我尝试的是第二种方法,如果我想让这只小鸟飞翔在群山之上,只需要让后面的群山动就好了。

这时候就要用到一个非常实用的函数了!

 noise(x):返回指定坐标处的Perlin噪声值,结果值始终在0.0到1.0之间。

 Perlin噪声是随机序列发生器,产生比标准random()函数更自然,谐波序列的数字。它是由Ken Perlin在20世纪80年代开发的,并已用于图形应用程序,以生成程序纹理,形状,地形和其他看似有机的形式。(引用)

总之生成的噪声图案十分的层次分明,就很美。

我们要做的就是不断的按照一定的速度向前更新x的坐标值,每次刷新画布的时候就会产生不断运动的感觉。

类似于:

但是现在是不是发现鸟飞的很尴尬,像吊在半空中一样,我们怎么来做的更像呢?

现实中鸟飞的时候翅膀都会动,显然,我们这只并不,好,我们来解决一下翅膀这个问题。绕一个点上下摆动,啊,我们有一个现成的模型可以套用,单摆运动,

 

我们确定了上下摆动的范围,具体的x值我们带到sin函数中算就好了。

一个有趣的交互,当鼠标靠近小鸟的时候,小鸟就躲开,狡猾的小别致。很简单,检测到鼠标位置时,移动坐标轴就好了,当然不要移动太大,小鸟就飞没了。

 

看是不是十分的和谐。

进入完善阶段,为了丰富一下我的画面,加了一个模拟雪花的“假粒子系统”。

很通俗的来讲,我准备了200半径随机个小白球,一开始在随机位置生成,不断改变y值,落到最下面的时候,回到固定位置重新开始新一轮的降落循环。

 

为了更鬼畜一点,加了一个跟着音乐跳动的太阳。

只是进行了一下简单的尝试,最最简单的音乐可视化,加载了minim库,加载进音乐来,用player.left.get(i)获取它左声道的值,这个值是介于(-1,1)之间的一个值‘’只需要乘一个系数放大这种变化,传递给画圆函数,就收获到一个闪烁着的太阳效果。这里友情提示一下,一开始我选择的是sound这个库,怎么弄也不出声,后来我一百度,原来这个库不支持processing 3这个版本,果断换了minim。

最终效果,可以点击下面链接看录屏效果。

https://www.bilibili.com/video/av36523799

附上代码:

import ddf.minim.* ;
Minim minim;
AudioPlayer player;

float theta=0.0;
float angle=PI/2;
int count=200;
float[] x=new float[count];
float[] y=new float[count];
float[] r=new float[count];
float[] s=new float[count];

float step,theta1;
int num=5, frames = 1200;  
Layer[] layers = new Layer[num];  

float value=0;
void setup() {
  size(800, 600);
  surface.setResizable(true);
  
  minim =new Minim(this);
  player=minim.loadFile("1.mp3");
  
  smooth(); 
  step = (height-120)/num;  
  for (int i=0; i<num; i++) {  
    layers[i] = new Layer(-20+i*step, random(1000), i+1);
  }
  
  for (int i=0; i<count; i++)
  {
    x[i]=random(0, width);
    y[i]=random(0, height);
    r[i]=random(3, 7);
    s[i]=random(1, 2);
  }
}


void draw() {
  background(255);
  
  for(int i=0;i<player.bufferSize()-1;i++)
  {
    value=abs(player.left.get(i));
   
  }
   sunoutside(value);
    suninside(value);
  
  
  for (int i=0; i<layers.length; i++) {  
    color col = lerpColor(#00C322,0, 0.8-0.8/num*i);  
    fill(col);  
    layers[i].display();
  }  
  theta1 += TWO_PI/frames;  
  
  //snow
  fill(255);
  for (int i=0; i<count; i++) {
    if (y[i]>height) {
      y[i]=-5;
    }
    if (dist(mouseX, mouseY, x[i], y[i])<20) {
      y[i]=-5;
      x[i]=random(0, width);
    }
    y[i]+=s[i];
    ellipse(x[i], y[i], r[i], r[i]);
  }
  
  translate(width/2, height/2);
  
  float x= -(mouseX-150)/7;
  float y= -(mouseY-150)/7;
  translate(x,y);
  bird();

  translate(-40, 40);//arm
  rotate(theta);
  beginShape();
  vertex(0, 0);
  bezierVertex(0, 0, -50, 0, -50, -30);
  bezierVertex(-50, -30, -90, 0, 0, 0);
  endShape();
  theta+=sin(angle)*0.05;
  angle+=0.05;
  
}
void bird()
{
  fill(126);//tail
  noStroke();
  ellipse(-80, 0, 20, 10);
  rotate(PI/40);
  ellipse(-80, 0, 20, 10);
  rotate(-PI/20);
  ellipse(-80, 0, 20, 10);
  rotate(PI/40);

  rotate(PI/4);//mouth
  rect(0, -50, 30, 30);
  rotate(-PI/4);

  fill(200);
  beginShape();//body
  vertex(-80, 0);
  bezierVertex(-80, 0, 0, -60, 30, -50);
  bezierVertex(30, -50, 70, -30, 30, 40);
  bezierVertex(30, 40, 0, 60, -80, 0);
  endShape();

  fill(126);//eye
  translate(40, -40);
  ellipse(-5, 5, 30, 30);

  fill(0);
  ellipse(0, 0, 10, 10);
}
void suninside(float value)
{
  float wid=40;
  wid=wid+value*100;
  if(wid>60)
  wid=40;
  fill(255,0,0,200);
  ellipse(150,100,wid,wid);
  
  fill(255,0,0,100);
  ellipse(150,100,60,60);
}
void sunoutside(float value)
{
  float wid=70;
  wid=wid+value*100;
  if(wid>100)
  wid=70;
  fill(255,255,0,200);
  ellipse(150,100,wid,wid);
}
class Layer {  

  float start, noize, speed;  
  float yOff, yOff2;  

  Layer(float _start, float _noize, float _speed) {  
    start = _start;  
    noize = _noize;  
    speed = _speed;
  }  

  void display() {  
    yOff = yOff2;  
    noStroke();  
    for (int x=0; x<width; x+=1) {  
      float y = start + noise(noize+sin(yOff)*3)*step*3.5;  
      rect(x, height, 1, -height+y);  
      yOff+=TWO_PI/(width);
    }  
    yOff2=theta1*speed;
  }
}
void mousePressed()
{
  if(player.isPlaying())
  {
    player.pause();
  }
  else
  player.play();
}

二、理论对比

下面是心得体会时间。

手绘VS码绘,动态表现手法到底有哪些不同。

(一)手绘

这种变现手法,在漫画中很常见,风是一个很抽象的概念,看不见也摸不着,但是这个名词带给我们的感觉就是流动的,画面就是动起来的,绘画中对于风的表现也有多种,粗细分明的线条,或者是明暗分明的光影。

  1. 材质

不同的材质在人们认知中是不同的,铁是硬的,棉花是软的,在画画中作者表现好这种材质的感觉,飘起的衣服,头发,往往给人一种代入感,让人下意识的就在脑海中浮现出动态的画面。

     

 

  1. 体态的表现

人体的动作的表现在漫画创作中,是每一个漫画技师需要磨练的技术,怎么画的像,评判“像”的标准又是什么呢?当然是和现实中我们日常见到的各种动作相像,当表现好了这种方式的时候,就是给看的人一种潜意识的联想,也就是自己已经脑补出画面了。

         

说到底,从我的理解角度来看,手绘之所以能够变现出动态的效果,实际上是在用画面刺激我们的大脑去联想,见到风我们就联想到吹过的树叶,见到水流,我们就会想到被拍打的石头。

画面是静止的,但是我们的联想会越来越具有代入感的把你拉进,所有这些静态画面构建的虚拟动态世界中去。

(二)码绘

反过来看码绘,其实更接近与我们经常看的电影,一帧一帧排列在一起,按照时序,一秒多少帧,放出来,我们看起来就是动起来的,但是和真正的制作动画片的流程不一样的,我们不需要亲自一帧一帧的制作,我们只需要负责一个画面的绘制,然后,告诉计算机,这一帧和后面的关系,计算机就会不知疲倦的帮你把所有都画出来。

这么说来,其实码绘也算是艺术创作的一种,你绘制出来的东西是随机的,当在经历了许多的迭代之后,你赋予计算机的链接关系,带来的结果更是具有惊喜的感觉。

好了,就写到这里吧。

三、参考资料

1.《用代码画画》:

0.1 用代码画画——搞艺术的学编程有啥用?

https://blog.csdn.net/magicbrushlv/article/details/77922119

1.1 开始第一幅“码绘”——以编程作画的基本方法

https://blog.csdn.net/magicbrushlv/article/details/77840565

2. 以编程的思想来理解绘画—— (一)用”一笔画“表现“过程美”

https://blog.csdn.net/magicbrushlv/article/details/82634189

3.http://iprocessing.cn/2017/10/22/%e7%ac%ac%e5%85%ab%e6%9c%9f%ef%bc%9aprocessing%e5%88%b6%e4%bd%9c%e5%8a%a8%e6%80%81%e5%b1%b1%e6%b0%b4%e8%83%8c%e6%99%af/

4.噪声noise()

http://iprocessing.cn/2017/07/09/noise-%e5%99%aa%e9%9f%b3/

  • 15
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值