文章目录
主题
- 得到一件编程创意作品,必须实现动态效果或交互效果
- 作品可以是具象化地描绘自己的形象,也可以是任何形式表现自己的兴趣、追求、特色、经历等
- 作品录制一段一分钟内的视频
编程语言:p5.js
编程工具:Sublime Text、p5.js在线编辑器
效果展示
画像简介
内容
- 显然这是脸
- 不知道你有没有注意到它分成左右两半
- 两边的脸是不同情绪的,左边开心,右边不快,遮挡着看可能会更明显一些
- 本意是表达两面或者不同情绪,但是可能对比不太明显
动态与交互
-
鼠标的位置上始终有一个小心形一样的东西标志鼠标的实时位置,形象如下——
-
鼠标移动时会有三个变化——
两半的背景颜色分别变化,但始终右边的暗沉一些
人物的眼睛高光部分会跟随鼠标的移动而移动,像是在看向鼠标
人物的嘴角会变化,左半边在是否上扬间变化,右半边在是否下撇间变化 -
鼠标点击时会有两个变化——
人物的眼睛会闭起来,而且闭上的状态也因表达心情的不同而不同
左右两边会出现不同的简陋特效,左边是闪烁的亮黄心心,右边是闪烁的愤怒标志,也是与心情相对应的
实现过程
实现流程
其中所有的五官都是分左右两半分别编写的。
几个关键函数
贝塞尔函数
p5.js中的函数释义
线性贝塞尔曲线
给定点 P0、P1,线性贝塞尔曲线只是一条两点之间的直线。这条线由下式给出:
二次方贝塞尔曲线
路径由给定点 P0、P1、P2 的函数 B(t) 追踪
三次方贝塞尔曲线
P0、P1、P2、P3 四个点在平面或在三维空间中定义了三次方贝塞尔曲线。曲线起始于 P0 走向 P1,并从 P2 的方向来到 P3。一般不会经过 P1 或 P2;这两个点只是在那里提供方向资讯。 P0 和 P1 之间的间距,决定了曲线在转而趋进 P3 之前,走向 P2 方向的“长度有多长”
在p5.js函数中,bezier前两个参数指定曲线第一个点,后两个参数指定另一个点。中间的参数指定了定义曲线形状的控制点,编写时通过不断调节控制点的位置画出想要的效果。
curve函数
p5.js中的函数释义
简单地说
curve(控制点1,起点,终点,控制点2)
其中每个点都由两个参数x,y表示。控制点1控制起点,控制点2控制终点。具体绘制时先确定起点和终点的位置,再通过调节控制点改变曲线的形状。
arc函数
p5.js中的函数释义
后两个参数表示的是起点和终点,编写时通过调节起点与终点实现不同圆弧的绘制。
线宽函数
p5.js中的函数释义
这个函数很简单,使用方法和作用一目了然,但是有一点要注意——在这一次设置了线宽后,如果后面没有再设置,线宽将保持不变!所以如果你只是想改变一小部分绘画的线宽,在画完之后一点更要记得重新设置回来呀!
代码实现
布置背景
//背景布置
noStroke();
if(mouseX<=400&&mouseX>=0) dx=mouseX/10;
if(mouseY<=400&&mouseY>=0) dy=mouseY/10;
fill(244,121+dx,131+dy);//粉色
rect(0,0,200,400);
fill(128+dx,128+dy,128);//浅灰色
rect(200,0,400,400);
画头发、脸、耳朵
//头发
strokeWeight(4);
noFill();
stroke(160,82,45);//黄土赭色
fill(210,105,30);//巧克力色
bezier(80, 380, -60, -100, 460, -100, 320, 380);
//齐刘海
strokeWeight(4);
stroke(160,82,45);//黄土赭色
line(110,180,130,180);
line(140,180,200,180);
line(210,180,230,180);
line(245,180,290,180);
//刘海隙
noStroke();
fill(255,245,215);//肉色
triangle(130,180,135,140,140,180);
triangle(200,180,205,110,210,180);
triangle(230,180,238,135,245,180);
stroke(160,82,45);//黄土赭色
line(130,180,135,140);
line(135,140,140,180);
line(200,180,205,110);
line(205,110,210,180);
line(230,180,238,135);
line(238,135,245,180);
//脸
strokeWeight(2);
stroke(160,82,45);
fill(255,245,215);//肉色
bezier(110, 180, 100, 350, 300, 350, 290, 180);
//耳朵
stroke(160,82,45);
fill(255,245,215);//肉色
//bezier(60, 20, 30, 0, 15, 50, 50, 60);
bezier(108, 200, 80, 180, 65, 230, 115, 240);
bezier(292, 200, 320, 180, 335, 230, 285, 240);//关于x=200对称
画眉毛
由此处开始出现左右不对称的情况了,因为要用无关来表现人物(应该就是我)的心情了!
//左眉毛
strokeWeight(4);
stroke(160,82,45);
noFill();
//curve(5, 70, 4, 10, 44, 10, 40, 70);
curve(145, 260, 145, 200, 185, 200, 190, 260);
//右眉毛
stroke(160,82,45);
noFill();
line(215,195,255,188);
画眼睛嘴巴
这里进入了整个自画像有关交互和动态变化的关键点!
在这里会涉及到——
- 鼠标点击的判断
mouseIsPressed 系统变量将会在滑鼠键被按下时为真(true),而没按下时为假(false)。
我们将写眼睛嘴巴的两个状态或变化,分别放在点击与不点击中,实现鼠标点击使表情变化。
-
鼠标移动的变化
这其中包括鼠标移动眼睛跟随
鼠标移动两侧嘴角不同的变化
(背景的变化写在了背景部分中)
所以就是 m o u s e X mouseX mouseX 和 m o u s e Y mouseY mouseY 的运用
mouseX 系统变量将会储存当时的鼠标相对于画布 (0, 0) 位置的的横向位置。如果使用的是触动而不是滑鼠的话,mouseX将会储存上一个触动点的 x 值。
mouseY 系统变量将会储存当时的鼠标相对于画布 (0, 0) 位置的的直向位置。如果使用的是触动而不是滑鼠的话,mouseY将会储存上一个触动点的 y 值
接下来展出代码(好长,做好准备)
if(mouseIsPressed)//鼠标按下
{
drawAngry(340,50);
drawAngry(250,100);
drawAngry(380,200);
drawAngry(270,300);
drawAngry(370,380);
drawSun(50,80);
drawSun(100,300);
drawSun(150,30);
drawSun(30,210);
drawSun(10,380);
//左眼
strokeWeight(4);
stroke(160,82,45);//黄土赭色
line(145,210,185,225);
line(145,240,185,225);
//左侧嘴巴
noFill();
arc(200,240,100,80,HALF_PI,-PI-0.3);
//右眼
strokeWeight(4);
stroke(160,82,45);//黄土赭色
line(215,220,220,225);
line(220,225,255,220);
//右侧嘴巴
line(200,280,220,285);
}
else
{
//控制眼睛移动
if(mouseX<=400)
{
x=mouseX/400*10;
}
else
{
x=10;
}
if(mouseY<=400&&mouseY>=0)
{
y=mouseY/400*14;
}
else if(mouseY>400)
{
y=14;
}
line(160+x,215+y,160+x,225+y);
//左眼
strokeWeight(2);
stroke(160,82,45);//黄土赭色
line(145,210,185,210);
fill(160,82,45);
rect(155,210,20,30,5);
strokeWeight(6);
stroke(255);
line(160+x,215+y,160+x,225+y);
//右眼
strokeWeight(2);
stroke(160,82,45);//黄土赭色
line(215,205,220,210);
line(220,210,255,205);
fill(160,82,45);
rect(225,210,20,30,5);
strokeWeight(6);
stroke(255);
line(230+x,215+y,230+x,225+y);
//左侧嘴巴
strokeWeight(2);
stroke(160,82,45);//黄土赭色
noFill();
if(mouseX>=200&&mouseX<=400)
{
xml=(mouseX-200)/300;
}
else if(mouseX<200&&mouseX>=0)
{
xml=0;
}
arc(200,240,100,80,HALF_PI,-PI-0.3-xml);
//右侧嘴巴
strokeWeight(2);
stroke(160,82,45);//黄土赭色
if(mouseX<=200&&mouseX>=0)
{
xmr1=mouseX/10;
xmr2=mouseX/40;
}
else
{
xmr1=20;
xmr2=5;
}
line(200,280,210+xmr1,282.5+xmr2);
}
( d r a w S u n drawSun drawSun 和 d r a w A n g r y drawAngry drawAngry 是我自定义的两个简陋特效函数)
画中轴线、鼠标标志、简陋特效
这几个就都是简单的绘制图形了
但有一点!之所以把中轴线和鼠标标志放在
d
r
a
w
draw
draw函数的最后编写,是为了让中轴线和鼠标的小标志能在所有的图像之上,不会被覆盖~
//中轴线
strokeWeight(5);
stroke(255);//白色
line(200,0,200,400);
mouseShape(mouseX,mouseY);
function drawAngry(x,y)
{
r=random(5,20);
d=2*r;
noFill();
stroke(220,20,60);
strokeWeight(4);
arc(x-r,y-r,r,r,0,HALF_PI);
arc(x+r,y+r,r,r,0,HALF_PI);
arc(x+r,y-r,r,r,0,HALF_PI);
arc(x-r,y+r,r,r,0,HALF_PI);
}
function drawSun(x,y)
{
r=random(5,15);
d=2*r;
stroke(255,241,67);
strokeWeight(2);
fill(255,241,67);
ellipse(x,y,d,d);
ellipse(x+10,y,d,d);
ellipse(x+5,y+5,d,d);
}
function mouseShape(x,y)
{
stroke(234,205,118);
fill(234,205,118);
ellipse(x,y,5,5);
ellipse(x+10,y,5,5);
ellipse(x+5,y+5,5,5);
}
这些代码是按照我的绘画过程粘贴的,把他们拼接起来就是完整的全部代码啦!
最后
这次的自画像任务很开放,完完全全由自己一手创作,想画什么就画什么,所以在完成作业的过程中也收获了很多创作的快乐。每当有新想法蹦出来时,一点一点地寻找实现方法,这个摸索过程十分让人沉浸。
但是绕来绕去我会的还是不多,所以只能做成这样一个简单的作品了,之后再继续加油吧!