作业汇报:融入动画技术的交互应用

一、要求

主题:自拟

技术:
参考《代码本色》教程,运用不少于3个章节的动画技术,实现一个交互应用,将动画技术充分运用于交互过程中;
最好能充分融入其他课程的知识。

报告:
撰写一篇博文/推文,介绍该应用的背景、创意、功能、用法、技术等各个方面,并可自行选定特殊主体做深入讨论,尽可能从多种角度、关联多学科的方式来探讨;

开发工具:p5.js, processing, openframeworks, unity, 若涉及其他工具或语言,要提前找老师讨论并征求意见

二、实践

1、作品预览

粒子效果

其他动态

2、开发工具
Windows10&processing3(Java)

3、功能及关键代码
(1)、GUI界面设计

GUI界面

页面中一共有六个控制按钮,还有四个滑块控制。六个控制按钮分别为:功能操作介绍、雨、雪、暴风雪、其他功能介绍。
GUI功能的部分代码:

birdButton birdButton;
scrollBar hs;
Handle[] handles;
helpButton helpButton;
rainButton rainButton;
snowButton snowButton;
blizzardButton blizzardButton;
otherButton otherButton;
..............
void GUI() {
    birdButton.draw();
    helpButton.draw();
    rainButton.draw();
    snowButton.draw();
    blizzardButton.draw();
    otherButton.draw();
    hs.display();
    
      for (int i = 0; i < handles.length; i++) {
     
    handles[i].update();
    handles[i].display(i);
  }

(2)、三种粒子动态
下雨:
雨和暴雪数组是相似的,唯一的区别是:(1)暴雪类使用rotation()函数使其看起来像是在大风中行进的雪;(2)使用ellipse() 创建雪的形状;(3)雪的大小没有随机性;(4)使用push和pop矩阵防止随机旋转受到影响。以及使generateBlizzard()函数中的屏幕变白,使其看起来更自然。

下雨
class Rain {
  
  float xpos, ypos, z, len, yspeed;
  
  
  Rain() {
    xpos = random(width);
    ypos = random(-1000, -500);
    z = random(0, 10);
    len = map(z, 0, 1, 1, 2);
    yspeed = map(z, 0, 20, 4, 10);
  }
  
  void fall() {
   
      ypos = ypos + yspeed;
      float gravity = map(z, 0, 20, 0, 0.2);
      yspeed = yspeed + gravity;
      
      if (ypos > height) {
         ypos = random(-1000, -500);
         yspeed = map(z, 0, 20, 10, 30);
      }
      
  }
  
  void display() {
     float thickness = map(z, 0, 20, 1, 2);
     fill(0, 0, 225, 90);
     rect(xpos, ypos, thickness, (ypos+len)/10);
  }
}

下雪:
snow类使用一个数组,该数组在一个名为getsnow()的函数中初始化和填充。我参考了一个关于数组的处理教程,它演示了如何在屏幕上制作点。因为它是一个简单的例子,并且与缺乏随机性保持一致,所以除了值(例如雪的数量和Y轴位置使雪看起来更自然)、变量名和封装之外,我没有对代码做太多的更改。


下雪
class Snow {
  
   float x, y;
   float diameter;
   float speed;
   float r;  
  float g;  
   float b;  
   int direction = 1;
   
   Snow(float xpos, float ypos, float dia, float sp) {
    
       x = xpos;
       y = ypos;
       diameter = dia;
       speed = sp;
   }
  
    void move() {
        if (y > height) {
         y = -50; 
        }
       y += (speed * direction);
    }
    
    void display() {
         
      //r = x/4;     
      //g= y/4;    
      //b = (x+y)/8;
      // fill(r,g,b);
       ellipse(x, y, diameter, diameter);
    }
}

暴风雪:


暴风雪

class Blizzard {
  
  float xposBlizzard, yposBlizzard, z, len, yspeed;
  
  
  Blizzard() {
    xposBlizzard = random(width);
    yposBlizzard = random(-1000, -500);
    z = random(20, 100);
    len = map(z, 0, 20, 10, 20);
    yspeed = map(z, 0, 20, 1, 20);
  }
  
  void fall() {
   
      yposBlizzard = yposBlizzard + yspeed;
      float gravity = map(z, 0, 20, 0, 0.02);
      yspeed = yspeed + gravity;
      
      if (yposBlizzard > height) {
         yposBlizzard = random(-1000, -500);
         yspeed = map(z, 0, 20, 1, 20);
      }
      
  }
  
  void display() {
    pushMatrix();
    rotate(radians(z));
    fill(255);
    ellipse(xposBlizzard, yposBlizzard, 5, 5);
  popMatrix();
  }
}

(3)、鼠标和键盘交互
例如:按“2”键会在鼠标光标所在位置种一棵随机大小的小树。
首先,声明arraylist并为tree类打开了一个新标签。使用add()函数添加树,该函数根据光标的X轴和Y轴传递值。这允许在用户选择的位置创建树,以及树的高度。与其他对象(如human)相比,使用forloop和get()函数(位于draw()函数内部)访问tree类。它将获取索引并将其传递给get()函数,然后获取并调用display()函数,该函数将绘制树。display()函数包括使用rect()函数绘制树的木材,使用triangle()函数作为基础绘制树叶,然后使用更多的triangle()函数在其顶部添加forloop和更改的值。


种树
void Weather() {
    if (key == '3') {
       snowFlag = true;
    }
    
    if (key == '2') {
      treeFlag = true;
      trees.add(new Tree(mouseX, mouseY)); 
      keyReleased();
    }
    
    if (key == '4') {
       rainFlag = true;
    }
    
    if (key == '5') {
       blizzardFlag = true; 
    }
    
    if (key == '1') {
       birdFlag = true; 
    }

    else if (key == '6') {  //remove weather functions
       snowFlag = false;
       treeFlag = false;
       rainFlag = false;
       blizzardFlag = false;
       birdFlag = false;
    }
    
 }
......
void checkFlags() {
     if (snowFlag == true) {
    generateSnow();
  }
  
  if (rainFlag == true) {
     generateRain(); 
  }

  if (blizzardFlag == true) {
     generateBlizzard();
  }
  
  if (birdFlag == true) {
    generateBird();  
  }
 }

(4)、图片动画


动画
class Bird {

  PImage[] images;
  int imageCount;
  int frame;
 
 float xposBird;
 float yposBird = height * 0.25;

  Bird(String imagePrefix, int count) {
     imageCount = count;
     images = new PImage[imageCount];
     
     for (int i = 0; i < imageCount; i++) {
        String filename = imagePrefix + i + ".png";
        images[i] = loadImage(filename);
     }
  }

  
  void display(float xpos, float ypos) {
    frame = (frame+1) % imageCount;
    image(images[frame], xpos, ypos);
    image(images[frame], xpos, ypos);
  }
  
  void draw() {
     float drag = 30.0;
     float dx = mouseX - xposBird;
     xposBird += dx/drag;
     float dy = mouseY - yposBird;
     yposBird += dy/drag; 
     bird_1.display(xposBird-bird_1.getWidth()/2, yposBird-bird_1.getHeight()/2);  
  }

  
  int getWidth() {
     return images[0].width; 
  }
  
  int getHeight() {
     return images[0].height; 
  }
}

(5)、操作说明
键盘交互:
“a”向左走
“d”向右走
“1”召唤一只鸟
“2”种一棵树
“3”下雪
“4”下雨
“5”暴风雪
“6”删除所有内容
鼠标交互:
-鼠标点击狗来改变它摇摆尾巴的速度。
-鸟跟着光标移动。
-生成的树由光标位置决定,包括放置树的位置(光标的X轴)和树的高度(光标的Y轴)。

功能简介
 if (mousePressed) {
           fill(255, 255, 255, 50);
           rect(imageX, imageY, 1000, 500);
           fill(0);
           
           textSize(18);
           textFont(myFont);
           text("功能简介", imageX + 20, imageY + 20);
           textSize(12);
           text("“a”和“d”键移动人的向左向右。或者,使用上面的灰色滑块移动人。", imageX + 20, imageY + 40);
           text("按'1'键召唤小鸟跟随光标。或者,单击bird图标来调用它。它会跟随你的光标。", imageX + 20, imageY + 60);
           text("按“2”键种植一棵树。根据光标的x轴创建树;树的高度取决于光标的y轴;树干的宽度是随机的;叶的高度、宽度和层数是随机的。", imageX + 20, imageY + 80);
           text("按‘3’键下雪。或者,点击“Snow”按钮。可以使用滑块来改变雪的直径。", imageX + 20, imageY + 100);
           text("按“4”键使天下雨。或者,点击“Rain”按钮。可以使用滑块来改变水滴的大小。", imageX + 20, imageY + 120);
           text("按‘5’键制造暴风雪。或者,点击“暴雪”按钮。使用黑色的“暴雪”滑块来改变速度。", imageX + 20, imageY + 140);
           text("按'6'键删除所有内容。", imageX + 20, imageY + 160);
           text("鼠标点击狗来改变它摇尾巴的速度。", imageX + 20, imageY + 180);
      }
        
     }
     ......
 if (mousePressed) {
           fill(255, 255, 255, 50);
           rect(imageX, imageY, 1000, 180);
           fill(0);
           textSize(18);
           text("树、删除和狗的说明", imageX + 20, imageY + 20);
           textSize(12);
           text("对于树,按'2'键种植一棵树。根据光标的x轴创建树;\n \t树的高度取决于光标的y轴;树干的宽度是随机的;叶的高度、宽度和层数是随机的。", imageX + 20, imageY + 40);
           text("按'6'键删除所有内容。", imageX + 20, imageY + 80);
           text("鼠标点击狗来改变它摇尾巴的速度.", imageX + 20, imageY + 100);
           text("在‘介绍’按钮中列出的更多功能。.", imageX + 20, imageY + 120);
        
      }

4、知识涉及
1)、ArrayList
构造函数:
ArrayList<Type>()
ArrayList<Type>(initialCapacity)
参数:
类型类名:要放置在ArrayList中的对象的数据类型。
initialCapacity int:定义列表的初始容量;默认为空。
ArrayList存储的对象数量可变。这类似于创建对象数组,但使用arraylist,可以轻松地添加和删除arraylist中的项,并动态调整其大小。这可能非常方便,但比在使用许多元素时创建对象数组要慢。请注意,对于整数、浮点数和字符串的可调整大小的列表,可以使用处理类intlist、floatlist和stringlist。
ArrayList是Java列表接口的可调整数组实现。它有许多方法用于控制和搜索其内容。例如,arraylist的长度由其size()方法返回,该方法是列表中元素总数的整数值。元素用add()方法添加到arraylist,用remove()方法删除。get()方法返回列表中指定位置的元素。
2)、中文字体的设置与使用
a、首先,使用PFont类的静态函数list,可以列出当前系统可用字体,返回一个String[]数组。使用printArray显示。
b、要在Processing中绘制文字,必须创建PFont字体类型。
如图,根据系统字体创建,最简单的用法为:
PFont字体变量=createFont("字体名",字体大小);

设置字体

c、在默认渲染模式下,对于矢量字体,createFont函数中指定的字体大小无关紧要。但是在P2D模式和P3D模式下,createFont是创建纹理图片。
函数使用说明:
PFont -> 创建字体类型对象
loadFont("字体类型") //在工具中创建字体文件 (.vlw 类型的文件)
textFont(类型对象) //引用新创建的字体类型对象
textSize(x) //修改字体的大小
text("文本文件", x, y) //x,y 设定水平和垂直的位置, 这个位置是想对于文字的基线而言的
text("文本文件", 26, 30, width, height) //同上, width, height 表示绘制文字的区间高低宽度,

5、参考资料
1)、《代码本色:用编程模拟自然系统》
2)、Processing 入门教程(三十七)图层动画:https://blog.csdn.net/qq_39097425/article/details/85110281
3)、Processing 入门教程(十九) 图片动画:http://www.pianshen.com/article/1148135405/
4)、Processing大神教程:The Nature of Code -- 粒子系统:https://www.bilibili.com/video/av4044431/
5)、Processing 教程3--Arry和For Loop :http://www.sohu.com/a/205366456_654105

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,026评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,655评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,726评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,204评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,558评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,731评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,944评论 2 314
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,698评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,438评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,633评论 2 247
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,125评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,444评论 3 255
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,137评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,103评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,888评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,772评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,669评论 2 271

推荐阅读更多精彩内容

  • 0. 前言 新的手游项目使用Unity引擎,动画部分要使用重定向技术来实现动画复用。之前在大公司工作的时候对这块了...
    董夕阅读 11,691评论 21 44
  • 最近常听朋友对我说一句话:你怎么越来越具有猫的特征啦。对此评价我不置可否,猫就猫啦,又温柔、又漂亮、还可爱,没什么...
    醋娘子阅读 142评论 0 0
  • 值传递:基本数据类型的变量之间的数据传递 全局变量static和extern 1)static修饰的全局变量作用范...
    游某人阅读 807评论 0 0
  • 虽然越来越多的人觉得读书有用,但是仍有人没有想明白读书有什么用。 看一下下图,健美的身材,喜欢么?臃肿的肥肉,厌弃...
    LvJack阅读 276评论 0 0
  • 酱香型白酒作为中国白酒的一个主流品类,在市场上已不鲜见。但是,我估计绝大多数的消费者,并不清楚其实酱香型白酒还分为...
    品创者阅读 290评论 0 2