绘画系统

实现作品

实现了雨和雪,通过不同的交互方式,产生相关的一些效果。

创作思路

这次作业的要求是编写一个“绘画系统”,提供一系列绘画材料(例如画笔/颜料/滤镜)给用户操作,以创作出动态/交互的绘画作品。这个绘画系统是对“绘画”的概念的扩展,但仍然体现出与传统绘画系统的相似性。
什么是绘画?在文章《什么是绘画?——以抽象思维理解绘画》中把绘画的一些要素抽象出来,给了一个比较宽泛的定义,绘画:****作画者 以特定的 交互方式 操作一系列 材料,制造出 作品以呈现给观赏者,传达一定的思想和情感。
这篇文章给我的最大的启示是一种思想,把一个复杂的系统用数学抽象思维的方式,提取出其中的要素,以一种数学的思想去理解它。
互动媒体的作业是“绘画系统”,而这学期学的数字图像处理的大作业有一项是做一款类似Photoshop的“图像处理系统”,我当时隐约感觉到两者是有很大不同的,但具体是什么我又没有想明白。
先说回这次的作业,当律老师最开始提到做一个“绘画系统”时,我当时想到的是看过的一篇博文《canvas实现漂亮的下雨效果》,于是想基于下雨做些拓展,并且交互也比较好想。后来想了一下,这个可以勉强往场模型上面靠,但实际做的过程中感觉有点不妥。与场模型做下对比,下雨效果可以改变的东西太少,我绞尽脑汁也只能想到在速度,风向,雨滴碰撞,云,闪电等方面,所以最终的系统变化很少。而场模型则不是这样,场模型的像素阵列的变化更加多,最终呈现的效果也是多种多样。
为什么会这样呢?简单来说,雨落已经是一幅画了,而我提供的一些效果,只是在原画的基础上进行修改,而场模型虽然也有基础的框架,但这个框架对最终作品的约束并不大。或者可以用熵的理论来解释,从像素到一幅画是一个从无序到有序的过程,一个已经有序的画可以改变的程度比较低,而熵比较低的场模型更改的幅度更大。
从呈现效果上来说,我感觉场模型乃至另外两种主要表现的是局部,当然也可以画出整体的效果,但局部的变化是始终不能忽视的,而我的雨和雪体现的是整体,局部的变化始终是为整幅画服务的,仅仅切出一小部分是没有意义的。
第一印象往往影响很大,我因为一开始就想到了下雨,中间虽然感觉有些问题,但也只能一条路走到黑了。
说回上面提到的互动媒体的“绘画系统”和数字图像处理的“图像处理系统”,我后来想想图像处理系统,这个进行修改应当也是能够转化成绘画系统,photoshop与常规的绘画实际上已经有很大的不同了。我最开始想到的两者不同,是把图形处理系统想成了板绘,这点与常规绘画差别很小,但PS用在板绘上的功能是只是很小的一部分,还有大量的图像处理相关的操作,而这部分是可以规划到抽象后的比较宽泛的绘画定义中的。
做完后发现了我的一些问题,我在创意和创新上能力很弱。这学期刚开始有艺术方面的课程,限于个人艺术素养较差,感觉理解起来很慢,学起来也比较吃力。互动媒体是把技术和艺术相结合,教授一些思想,更好入手一些,而UI设计和动画就让我很痛苦了。前一段时间做UI大作业,当时是把UI结合到了游戏大作业中,一连几个星期被老师提出各种意见反复修改。在做游戏方面的作业时,老师更关注的是实现的技术,美工方面的资源能够自己做更好,不行就使用商店资源,而做UI时,所有都要原创。
在过去写代码时,需要实现什么功能,第一步都是查资料,找到相关的资料,基于前人的工作进行修改。而现在也越来越推崇开源思想,计算机很多前沿的知识都可以通过网络获取。但艺术方面则很注重原创,对抄袭的界定也比较严格。而我过往的经验也限制了我的创意和创新,我更习惯去修改,而从头开始创作的能力就比较差。所以当时直接想到了基于下雨去修改,而不是像其他模型一样能够根据想象力画出不同效果的画。

效果展示

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码介绍

代码的实现比我想象中的难,一开始想用p5.js做,结果发现类都不会写,还是换回了processing,对java还算熟悉点,但还是遇到不少问题,一些操作的资料也不好找,中间废了很多无用功。功能主要通过一些类和粒子系统来实现。

这是processing主要绘画相关函数,这里把雨雪放到了一个里面,通过对ui的控制调用不同的界面,一开始用controlP5做ui界面,本来以为可以把雨和雪放到不同的画布上,结果发现在鼠标交互等方面效果不好,只能使用自带的ui控件通过条件来控制画不同的界面。

void setup() {
  size(1000, 900);

  buttonInitial();

  rainInitial();

  snowInitial();

  introInitial();
}

void draw() {
  background(0);

  if (rainOver) {
    rainDisplay();
  } else if (snowOver) {
    snowDisplay();
  } else if (introOver)
  {
    introDisplay();
  }

  buttonDisplay();
}

按钮控制
在这里插入图片描述

//draw 按钮
void buttonDisplay()
{
  //雨按钮颜色
  if (rainOver) {
    fill(rainHighlight);
  } else
  {
    fill(rainColor);
  }
  //  stroke(255);
  noStroke();
  rect(rainX, rainY, rainSizeX, rainSizeY);

  //雪按钮颜色
  if (snowOver) {
    fill(snowHighlight);
  } else {
    fill(snowColor);
  }
  //  stroke(0);
  noStroke();
  rect(snowX, snowY, snowSizeX, snowSizeY);

  //说明按钮颜色
  if (introOver)
  {
    fill(introHighlight);
  } else
  {
    fill(introColor);
  };
  //  stroke(0);
  noStroke();
  rect(introX, introY, introSizeX, introSizeY);

  fill(0);
  textSize(20);
  text("说明", 20, 35);

  text("雨", 135, 35);

  text("雪", 235, 35);
}

在这里插入图片描述

//draw 说明
void introDisplay()
{
  fill(255);

  textSize(40);
  text("操作说明:", 100, 150);
  textSize(30);
  text("点击标签切换界面", 200, 200);
  text("雨:", 200, 300);
  text(text1, 250, 270, 600, 200);
  text(text2, 250, 370, 600, 200);

  text("雪:", 200, 550);
  text(text3, 250, 520, 600, 200);
}

雨点类
雪类与这个相似

/*雨点类
雨的生成消失
判断碰撞
*/
class RainDrop
{
  float x; //雨点位置
  float y;
  float lineLength=5; //雨点长度
  float lineWeight=2;  //宽度

  float yspeed=8; //雨点速度
  float xspeed=5;
  float gravity=1;

  //雨点消失位置
  float endLine=900-150*random(0.3, 1);

  RainDrop(float tempx, float tempy)
  {
    x=tempx;
    y=tempy;
    //    lineLength=templineLength;
  }

  void run()
  {
    RainMoveDown();
    DrawLineDrop();
  }

  void RainMoveDown()
  {//雨点下降
    x=x+xspeed;
    y+=yspeed;
    if (y>endLine)
    {
      y=random(-200, 0);
      x=random(-500, 1500);
    }
  }

  void DrawLineDrop()
  {//画雨点
    float x1=x;
    float y1=y;
    float x2=x-xspeed*lineLength;
    //    lineLength
    //float y2=y+lineLength*random(0.5,1);
    //float y2=y1+lineLength;
    float y2=y1-yspeed*lineLength;
    smooth();
    stroke(250);
    strokeWeight(lineWeight);
    if (x2>0&&x2<1000&&y2<900&&y2>0)
    {
      line(x1, y1, x2, y2);
    }
  }

  void initial()
  {//雨点位置初始化
    y=random(-200, 0);
    x=random(-300, 1300);
  }

  //雨点碰撞判断
  boolean collision(float x1, float y1, float x2, float y2) {
    float disX = x1 - x2;
    float disY = y1 - y2;
    if (sqrt(sq(disX/60) + sq(disY/35)) < 1 ) {
      return true;
    } else {
      return false;
    }
  }
}

水滴类
这是一个粒子系统,其余的水环等代码也类似

/*水滴类
 雨滴碰撞后生成小水滴
 */
class WaterDrop
{
  float x;
  float y;

  float gravity=0.5;
  float radius=10;

  float yspeed=random(-8, -3);
  float xspeed=random(-3, 3);

  float life=50;

  WaterDrop(float tempx, float tempy)
  {
    x=tempx;
    y=tempy;
    //   lineLength=templineLength;
  }

  WaterDrop(float tempx, float tempy, float tempradius)
  {
    x=tempx;
    y=tempy;
    radius=tempradius;
  }

  void run()
  {
    update();
    display();
  }

  void update()
  {
    x=x+xspeed;
    yspeed+=gravity;
    y=y+yspeed;
    life-=1;
  }

  void display()
  {
    //noStroke();
    //fill(100);
    noFill();
    stroke(200);
    arc(x, y, life/5, life/5*0.5, 0.2*PI * 2, PI*2);
  }

  boolean isDead()
  {
    if (life<0)
    {
      return true;
    } else
    {
      return false;
    }
  }
}

交互方式
对雨雪和按钮等一些交互的控制

//鼠标拖动控制
void mouseDragged()
{
  if (rainOver)
  {
    rainDragged();
  }
}

//鼠标点击控制
void mouseClicked()
{
  buttonClicked();

  if (rainOver)
  {
    rainClicked();
  }
}

//键盘控制
void keyPressed() {
  if (snowOver)
  {
    snowKey();
  }
}

总结

最后一堂课老师说他没有去教具体的技术,而是教一些思想。记得最开始上互动媒体这门课的时候,上了几节仍然没有懂这门课在教什么,当时只感觉教的很杂,什么都讲,但又没感觉有个清晰的主线。到第一次作业时,我才开始动脑筋去思考老师想要教授的思想。到这门课结束,我最大的收获,不是这些具体的内容,而是那些思考的方式,这对我更重要。技术和艺术的结合,直观感觉就是很厉害,我的艺术素养比较差,仍然能够学到相关的知识。特别是第三次的作业,当时把那些相关的博文都看了一遍,感觉非常有趣。我一向感觉艺术是很难理解的东西,然后发现艺术也是可以从一种编程的思想去理解,还有这次的数学抽象思维,感觉都可以用技术的思想去理解艺术。一开始的实验感觉是从艺术去看技术,后面的实验则是从技术的思想去看艺术,不知道这些有没有提升我的能力,至少拓展了我的思维。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值