摘要
绘画的元素中,采用码绘对绘画材料与交互方式进行改进十分方便,比如可以加上动态效果,有规律的形状,绘画的基本元素不再使用基本像素等
设计思路
参考老师的案例,采用圆形面板来当绘制的panel,矩形面板的功能我也实现了一个自己的版本。采用上一次说的面向对象的方法,能够方便地改变每个元素的坐标,颜色等信息。
tips:
由于想象力有限,所以只能做出仅有的几个功能。
首先是定义一个绘制圆形的类:
它包括以下几个属性:
- 创建时的坐标
- 当前坐标
- 半径
- 旋转角度
- 旋转角度增加量
- 是否旋转
- 是否平移
- 是否被画笔画过
如果被画过,那么它的颜色就由笔刷面板来控制,代码:
function drawFcn(x,y,theta,angle,radius,rot,trans,painted)
{
//坐标
this.x=x;
this.y=y;
//初始坐标
this.initx=x;
this.inity=y;
//旋转角度
this.theta=theta;
//旋转角度增加量
this.angle=angle;
//半径
this.radius=radius;
//是否旋转
this.rotate=rot;
//是否平移
this.trans=trans;
//是否被画过
this.painted=painted;
this.draw_roundness=function()
{
if(!this.painted)//如果没有
{
fill(p_RGB_R, p_RGB_G, p_RGB_B, opacity);//使用本身颜色
}
else if(this.painted)
{
fill(b_RGB_R, b_RGB_G, b_RGB_B,opacity);//使用笔刷颜色
}
push();
rotate(this.theta);
if(this.trans)//是否移动
{
if(this.x<=this.initx+200&&this.x>=0)
{
if(!is_contrary)
{
this.x-=c_tran_speed;
}
else
{
this.x+=c_tran_speed;
}
}
}
if(this.rotate)//是否旋转
{
this.theta+=this.angle;
}
strokeWeight(c_stroke);
ellipse(this.x,this.y,this.radius,this.radius);
pop();
}
}
定义数组来保存对象并且随着Gui面板变量更新而更新(zoom是整体圆形的半径,radius是单个圆形的半径):
//更新、初始化圆形
function InitRoundnessList()
{
var r = radius * zoom;//半径
if(RoundList.length>seeds)
{
RoundList.length=seeds;
}
else if(RoundList.length<seeds)
{
for(var i = RoundList.length-1; i <seeds ; i++)
{
RoundList[i]=new drawFcn(sqrt(i + 0.5) * zoom,0,0,0,r,false,false,false);
}
}
if(RoundList[0].initx!=sqrt(0.5) * zoom)
{
for(var i = 0; i <RoundList.length ; i++)
{
RoundList[i].x=sqrt(i+0.5) * zoom;
}
}
if(RoundList[0].radius!=r)
{
for(var i = 0; i <RoundList.length ; i++)
{
RoundList[i].radius=r;
}
}
}
绘制圆形:(每个圆形绘制前都旋转一定的角度,平移指定距离,角度可以由面板控制)
push();
for(var i = 0; i < RoundList.length; i++) {
push();
translate(center_x, center_y);
rotate(i*angle);
RoundList[i].draw_roundness();
pop();
}
pop();
这样就绘制出基础的panel:
定义笔刷:
//brush
var brush_type=['color','rotate','translate','eraser','rotate_down','translate_down'];
var brush_radius=30;//笔刷半径
var brush_radiusMax=50;
var b_RGB_R=255;
var b_RGB_G=255;
var b_RGB_B=255;
var BrRotatePower=1;旋转笔刷的旋转速度
var BrRotatePowerMax=3;
var BrRotatePowerStep=0.1;
这里定义了Gui中几种笔刷的类型和笔刷的颜色。
给panel上色,实际上就是把鼠标划过的圆形对应的painted设为true:
if('roundness'==panel_type)
{
ellipse(mouseX-center_x,mouseY-center_y,brush_radius,brush_radius);
for(var i=0;i<seeds;i++)
{
var pos=createVector(center_x+cos((i)*angle+RoundList[i].theta)*(RoundList[i].x),center_y+sin((i)*angle+RoundList[i].theta)*(RoundList[i].x));
var position=createVector(mouseX,mouseY);
var su=p5.Vector.sub(pos,position);
var length=su.mag();
if(length<=brush_radius)
{
RoundList[i].painted=true;
}
}
}
绘制过的地方就可以用brush_gui来控制颜色
然后由roundness_gui控制参数可以达到其他效果:
让基础圆形向着远离圆心或者是向着圆心平移
因为旋转已经在类中定义好,所以代码和上色差不多:
if('roundness'==panel_type)
{
ellipse(mouseX-center_x,mouseY-center_y,brush_radius,brush_radius);
for(var i=0;i<seeds;i++)
{
var pos=createVector(center_x+cos((i)*angle+RoundList[i].theta)*(RoundList[i].x),center_y+sin((i)*angle+RoundList[i].theta)*(RoundList[i].x));
var position=createVector(mouseX,mouseY);
var su=p5.Vector.sub(pos,position);
var length=su.mag();
if(length<=brush_radius)
{
RoundList[i].trans=true;
}
}
}
效果:
围绕中心旋转:
这些基本上就是圆形面板的效果。
接下来是矩形面板:
同样的,定义一个绘制矩形的类:
function squaresFcn(x,y,xsize,ysize)
{
//方块坐标
this.x=x;
this.y=y;
//初始中心坐标
this.initx=x;
this.inity=y;
//方块长宽
this.xsize=xsize;
this.ysize=ysize;
//旋转角度
this.theta=0;
//旋转角度增加量
this.angle=0;
this.stroker = 0;
this.strokeg = 0;
this.strokeb = 0;
this.stroke=1;
//颜色
this.r = random() * 255;
this.g = random() * 255;
this.b = random() * 255;
//确定是否旋转
this.rot=false;
//是否被上色
this.painted=false;
//是否平移
this.trans=false;
//画普通的方块
this.draw_square=function()
{
push();
if(!this.painted)
{
fill(this.r, this.g, this.b,opacity);
}
else if(this.painted)
{
fill(b_RGB_R, b_RGB_G, b_RGB_B,opacity);
}
if(this.trans)
{
if(s_is_tran_x)
{
if(this.x<=this.initx+s_tran_x&&this.x>=this.initx-s_tran_x)
{
if(s_is_contrary)
{
this.x-=tran_speed;
}
else
{
this.x+=tran_speed;
}
}
}
if(s_is_tran_y)
{
if(this.y<=this.inity+s_tran_y&&this.y>=this.inity-s_tran_y)
{
if(s_is_contrary)
{
this.y-=tran_speed;
}
else
{
this.y+=tran_speed;
}
}
}
}
translate(s_center_x,s_center_y);
rotate(s_angle);
strokeWeight(stroke_weight);
stroke(stroke_r,stroke_g,stroke_b);
rect(this.x,this.y,this.xsize,this.ysize);
pop();
}
//画旋转的方块
this.draw_rotate=function()
{
if(this.trans){
if(s_is_tran_x)
{
if(this.x<=this.initx+s_tran_x&&this.x>=this.initx-s_tran_x)
{
if(s_is_contrary)
{
this.x-=tran_speed;
}
else
{
this.x+=tran_speed;
}
}
}
if(s_is_tran_y)
{
if(this.y<=this.inity+s_tran_y&&this.y>=this.inity-s_tran_y)
{ if(s_is_contrary)
{
this.y-=tran_speed;
}
else
{
this.y+=tran_speed;
}
}
}
}
push();
translate(s_center_x,s_center_y);
translate(this.x,this.y);
rotate(this.theta);
this.theta+=BrRotatePower;
fill(s_RGB_R, s_RGB_G, s_RGB_B,opacity);
if(!this.painted)
{
fill(this.r,this.g,this.b,opacity);
}
strokeWeight(stroke_weight);
stroke(stroke_r,stroke_g,stroke_b);
rect(0,0,this.xsize,this.ysize);
pop();
}
}
基础颜色设置成随机色,当单个矩形被画过时,同样的会被bursh面板操控颜色:
如果再被旋转笔刷刷过,就可以通过square面板控制颜色:
对应的,同样有平移的笔刷:
总结
这两种面板基本上是以一种类似像素画风的方法来绘制图片,不同的面板可以根据不同角度画出不一样的效果,采用不同的绘图元素,用动态的效果展示。
载体
采用的绘画材料和普通的护花方式不一样,可以自由控制动态效果等。
技法和理念
绘画,目的的是让看到的人获得一定的感受,这个绘画系统设计的就是基于有规律的基本面板形状,来表现出一种特别的感觉。
而手绘等传统的绘画方式是创作者基于自身的能力,随意发挥,而这个绘画系统目的就是让人能简单表现出一种想要的效果。
局限性
只能基于给定的基本形状进行扩展,不能像传统的基本像素组成的图案随意组合。
参考链接
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