要求
主题:用编程方式创作一幅介绍自己的作品
作品: 一件编程创意作品,必须实现动态效果或交互效果;作品录制一段一分钟内的视频;作品可以是具象化地描绘自己的形象,也可以是任何形式表现自己的兴趣、追求、特色、经历等;
自画像创作
想了好久自己的自画像是什么样子,最后决定画一个JOJO的奇妙冒险里的迪奥。不是因为自己长得像,大概是我也不想做人了吧。因为是要码绘,所以过于复杂的图案代码敲起来太浪费时间,就设计了一个Q版的造型。最终图如下:
最终成果图:
坐标的计算
由于dio爷那飘逸的发型,图像中大部分需要运用曲线。查了查p5的参考https://p5js.org/zh-Hans/reference,p5中的曲线用的是贝塞尔曲线算法。
那么问题就出现了,如何才能准确的找到自己在纸上画的图案的控制点与锚点坐标呢?
看到贝塞尔曲线,突然想到之前做过的图形学作业,制作一个简单的画图系统。其中的曲线就用到了贝塞尔曲线算法,可以通过移动鼠标在屏幕获取鼠标坐标,就能看到锚点与控制点坐标了。于是就翻了翻之前的作业,虽然简陋了点,但刚好能解决这个问题。不管白猫黑猫,逮到耗子就是好猫。剩下的只是繁重的坐标的记录。
颜色填充
用bezier曲线画好图形后,用fill()函数填充。发现并不能达到我们想要的效果。
虽然已经形成封闭的形状,但fill()函数并没有完美的填充,大概是顶点的遍历问题。解救办法是改用bezierVertex()函数。
动态背景与交互功能的添加
背景动态图
因为人物来自动漫,并且是dio爷标志性”扣no迪奥哒“动作,所以背景希望添加上漫画的网线效果。具体代码参考了网上的生成光芒线的代码https://wow.techbrood.com/fiddle/32556
var angle = 0;
var offset = 30;
var offset2 = 20000;
var scalar = 90;
var speed = 1;
function setup() {
createCanvas(500, 500);
background(200);
stroke(255, 0, 0)
strokeWeight(.1);
}
function draw() {
var y1 = offset + sin(angle) * scalar;
var y2 = offset2 + sin(angle + 0.4) * scalar;
for (var i = 0; i < 1; i++) {
translate(width / 2, height / 2)
rotate(angle)
push()
y1 = offset + sin(angle) * scalar;
rotate(angle)
line(0, 10 + angle / 9, 1000, y2);
angle += speed;
pop()
}
}
添加声音与图片
通过P5.js官网的在线编辑器,很容易在项目中添加声音与图像资源,具体操作参考https://www.php.cn/js-tutorial-395952.html。但将项目下载并在网页打开就无法加载音频图片资源,还不知道怎么解决。添加好资源后加上鼠标交互就能达到很好打效果。
//点击右键加载不做人了的图片与音频
//点击右键加载咋瓦鲁多的图片与音频
function loading() {
if (mouseIsPressed) {
if (mouseButton === RIGHT) {
mySound.setVolume(1);
mySound.play();
imageMode(CENTER);
//绘制图片
image(img, 200, 200);
tint(0, 153, 204, 126); //渲染
}
if (mouseButton === LEFT) {
mySound.setVolume(1);
mySound1.play();
imageMode(CENTER);
//绘制图片
image(img2, 200, 200);
imageMode(CENTER);
//绘制图片
image(img1, 200, 200);
tint(0, 153, 204, 126); //渲染
}
}
}
时间停止效果
迪奥在动漫中喊出“the world !”会产生时停。所以想着在右上角添加一个时钟,点击左键会加载图片和音频并让始终停止。
下面是时钟代码,艺术字体参考网上:https://mlln.cn/2018/06/06/p5.js%E6%95%99%E7%A8%8B06-%E6%98%BE%E7%A4%BA%E6%96%87%E5%AD%97/
var showEllipse = false;
let value = 0;
function preload() {
let style = document.createElement('link')
style.rel = "stylesheet"
style.href = 'https://fonts.googleapis.com/css?family=Gaegu'
document.getElementsByTagName('head')[0].appendChild(style)
}
function setup() {
createCanvas(800, 800);
textFont("Gaegu");
// 设置填充颜色
fill(123, 0, 0)
// 设置框线
stroke(255)
}
function draw() {
background(220);
time();
//if (mouseIsPressed) {
//sleep(3000);
//}
}
function mouseClicked() {
if (mouseButton === CENTER) {
showEllipse = !showEllipse;
if (value === 0) {
noLoop();
value = 255;
} else {
loop();
value = 0;
}
}
}
function time() {
let y = year();
let m = month();
let d = day();
let h = hour();
let mi = minute();
let s = second();
let millisecond = millis();
// 设置字体大小
textSize(26);
text('current time: ' + y + '-' + m + '-' + d + ' ' + h + ':' + mi + ':' + s + ':' + millisecond, 25, 60);
if (showEllipse) {
ellipse(200, height / 2, 50, 50);
//sleep(3000);
//setTimeout("time()", 3000);
}
}
function sleep(milliseconds) {
setTimeout(function() {
var start = new Date().getTime();
while ((new Date().getTime() - start) < milliseconds) {
// Do nothing
}
}, 0);
}