非常喜欢星星,非常喜欢特别美特别棒的东西,所以我的自画像是一只一直在追逐光明的兔子。
希望自己永远好奇,永远追逐,赤诚得与在世界上的每一天相恋。
也希望可以有星星点点,在追逐的路上与我相伴。
一追再追
兔子
静态图像
兔子的身子组成部分是头、身体、左耳、右耳、前腿、后退与尾巴,每个部分都是一条bezier曲线。
本来深受平时个人用AI画图的习惯影响,准备所有的图形都用圆来绘制。这里实名感谢yc小天使安利的bezier tool,让我放弃了这个危险的想法。事实证明,当使兔子动起来时,bezier曲线只要移动对应的端点与控制点就可以了,而用圆,即便可以在静态时绘制地好,动态时还是很难控制的。(其实是因为不能像AI中修改锚点)
由于想要天真随意的手绘风格,所以采用的方法是将兔子的代码封装在一个类中,创建多个对象,同时绘制。给每个顶点与控制点都添加一个较小的噪声,就可以使四条线条比较随意地重叠交叉。
绘制方法以身体为例,首先使用bezier tool获得满意的曲线,输出顶点信息:
beginShape();
vertex(633,406);
bezierVertex(521,552,478,382,352,456);
bezierVertex(125,692,697,746,673,458);
endShape();
由于获得的顶点学习是在固定位置的,而我们希望能够动态调整兔子的绘制位置,所以添加x与y到每一个顶点位置坐标中去,实现对位置信息动态修改。
同时,因为希望每一次绘制时的线条都是不同的,而且线条比较连贯顺畅,所以使用了噪声,也添加到每个顶点的位置坐标中。
为了代码的简洁性【大雾,将噪声封装起来。
nosie()函数每次返回一个0-1之间的柏林噪声,与偏移量offset相乘,得到顶点的偏移距离。
由于每绘制一个顶点都会使 i 自增,为了防止长时间运行使浮点数 i 超出取值范围,每次判断,当 i 等于2的23次时,将i重新置零。
float change(){
if(i == 2 << 23){
i = 0;
}
return noise(i++) * offset;
}
beginShape();
float x = xR;
float y = yR;
vertex(633 + x + change(),406 + y + change());
bezierVertex(521 + x + change() + xOffset * 0.5,510 + y + change() + yOffset * 0.8,478 + x + change() + xOffset * 0.8,382 + y + change() + yOffset * 0.8,352 + x + change() + xOffset,456 + y + change() + yOffset);
bezierVertex(125 + x + change() + xOffset * 0.8,692 + y + change() + yOffset * 0.8,707 + x + change() + xOffset * 0.3,746 + y + change() + yOffset * 0.3,673 + x + change(),458 + y + change());
endShape();
像这样依次绘制可以获得兔子的静态图像。
但是这张图上耳朵并没有画上去
动态图像
那么下一步就是使兔子动起来。
由于听了yc小天使的话,使用的是bezier曲线,所以要动起来只需要动态改变顶点与控制点的坐标即可。
但是要调整到满意的效果还是非常非常非常非常令人绝望的
还是以身体为例,由于兔子在奔跑时,身体会随着奔跑动作拉伸或收缩,所以对最右边的那个点及其控制点添加一个随时间变化的偏移量。
在每次绘制兔子时,都将记录绘制次数的updateCount增加一。
每绘制10次,使其动作变化一次,将变化次数记为runCount。
updateCount++;
runCount = updateCount % 10;
我们希望每个动作的周期中动作变化10次,因此将runCount乘上36,每增加10次,回到起点。
float xOffset = 50 - cos(PI - radians(36 * runCount)) * 50;
float yOffset = sin(PI - radians(36 * runCount)) * 10 - 10;
将偏移量乘上相对的值,添加在身体后的点及其控制点上。
更新后代码如下:
void drawBody(){
beginShape();
float x =