手绘和码绘的对比(2)——动态比较

本文探讨了码绘与手绘两种创作方式的特点及差异,通过实例展示如何使用p5.js实现动态画面,强调了构思与技术的重要性,分享了创作体验及呈现效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

码绘

手绘

代码实现过程

var numBalls = 30;
var spring = 0.05;
var gravity = 0.01;
var friction = -0.9;
var balls = [];
var dancingWords = [];
var angle1=0;
var angle2=90;
var scalar = 80;

function setup() {
    
  //colorMode(HSB, 360, 100, 100);
    
  createCanvas(600, 500);
     
        
  rectMode(CENTER);

   
    
    for (var i = 0; i < numBalls; i++) {
      
    balls[i] = new Ball(
      random(width),
      random(height),
      random(40, 80),
      i,
      balls
      
          );
       
  }
  noStroke();
    
    
    createP('Lets dance together.Lets dance together.Lets dance together.Lets dance together.').addClass('text');

 
  var texts = selectAll('.text');

  for (var i=0; i<texts.length; i++) {
    var paragraph = texts[i].html();
    var words = paragraph.split(' ');
    for (var j=0; j<words.length; j++) {   
      var spannedWord = createSpan(words[j]);
      var dw = new DanceSpan(spannedWord, random(500), random(60));
      dancingWords.push(dw);
    }
  }
    
}

function draw() {
    
  background(0);
  balls.forEach(ball => {
    ball.collide();
    ball.move();
    ball.display();
  });
     for (var i=0; i<dancingWords.length; i++) {
    dancingWords[i].brownian();
  }
      
     //画小丑
    fill(255,215,0);
    quad(204,181,271,210,270,227,196,194);
    quad(386,176,319,211,324,231,393,189);
       
     fill(255,248,220);
    rect(272,353,17, 40);
    rect(323,353,17, 40);
    
   fill(72,118,255);
     ellipse(274,300,55,55);
     ellipse(320,300,55,55);
    quad(265,323,280,323,287,336,254,336);
    quad(317,323,332,323,339,336,306,336);
  fill(106,90,205);
  quad(270,200,325,200,345,290,250,290);
        
    fill(0,139,69);
    ellipse(250,170,50,30);
    ellipse(253,145,50,30);
    ellipse(260,120,50,30);
    ellipse(350,170,50,30);
    ellipse(344,145,50,30);
    ellipse(335,120,50,30);
    fill(255,235,205)
    ellipse(300,160,100,100);//tou
    fill(0,139,69);
    ellipse(300,115,35,55);
    ellipse(275,124,35,55);
    ellipse(325,124,35,55);
    fill(255);
     ellipse(275,164,25,25);
     ellipse(325,164,25,25);
    fill(0);
    quad(275,144,277,164,275,184,273,164);
    quad(325,144,327,164,325,184,323,164);
    quad(255,164,275,167,295,164,275,161);
    quad(305,164,325,167,345,164,325,161);
    fill(255,248,220);
    ellipse(196,183,27,27);
     ellipse(393,179,27,27);
     fill(255,0,0);
     rect(272,373,17, 40);
    rect(323,373,17, 40);
    arc(251,400, 60, 60, radians(180), radians(0));
    arc(344,400, 60, 60, radians(180), radians(0));
     strokeWeight(1);
    beginShape();
 vertex(267, 184);
 vertex(275, 183);
 vertex(282, 189);
 vertex(291, 194);
 vertex(301, 196);
 vertex(316, 191);
 vertex(324, 184);
 vertex(333,187);
    vertex(329,196);
    vertex(315,204);
    vertex(301,206);
    vertex(300,207);
    vertex(289,206);
    vertex(275,200);
    vertex(267,193);
     endShape(CLOSE);
 var ang1 = radians(angle1);
  var ang2 = radians(angle2);
  var x1 = width/2+ (scalar * cos(ang1));
  var x2 = width/2 + (scalar * cos(ang2));
    var y1 = height/3 + (scalar * sin(ang1));
  var y2 = height/3 + (scalar * sin(ang2));
    fill(25 ,25 ,112);
  rect(x1, y1, 50, 50);
  rect(x2, y2, 50, 50);
    fill(255, 255, 0);
  rect(x2, y1, 50, 50);
  rect(x1, y2, 50, 50);
  angle1 += 3;
  angle2 += 2;
      
}
function Ball(xin, yin, din, idin, oin) {
    
  this.x = xin;
  this.y = yin;
  var vx = 0;
  var vy = 0;
  this.diameter = din;
  this.id = idin;
  this.others = oin;

  this.collide = function() {
    for (var i = this.id + 1; i < numBalls; i++) {
      // console.log(others[i]);
      var dx = this.others[i].x - this.x;
      var dy = this.others[i].y - this.y;
      var distance = sqrt(dx * dx + dy * dy);
      var minDist = this.others[i].diameter / 2 + this.diameter / 2;
      //   console.log(distance);
      //console.log(minDist);
      if (distance < minDist) {
        //console.log("2");
        var angle = atan2(dy, dx);
        var targetX = this.x + cos(angle) * minDist;
        var targetY = this.y + sin(angle) * minDist;
        var ax = (targetX - this.others[i].x) * spring;
        var ay = (targetY - this.others[i].y) * spring;
        vx -= ax;
        vy -= ay;
        this.others[i].vx += ax;
        this.others[i].vy += ay;
      }
    }
  };

  this.move = function() {
    vy += gravity;
    this.x += vx;
    this.y += vy;
    if (this.x + this.diameter / 2 > width) {
      this.x = width - this.diameter / 2;
      vx *= friction;
    } else if (this.x - this.diameter / 2 < 0) {
      this.x = this.diameter / 2;
      vx *= friction;
    }
    if (this.y + this.diameter / 2 > height) {
      this.y = height - this.diameter / 2;
      vy *= friction;
    } else if (this.y - this.diameter / 2 < 0) {
      this.y = this.diameter / 2;
      vy *= friction;
    }
  };

  this.display = function() {
      var h = random(100, 255);
        fill(0, h, h,200);
    ellipse(this.x, this.y, this.diameter, this.diameter);
  };
}


function DanceSpan(element, x, y) {
  element.position(x, y);
  
  this.brownian = function() {
    x += random(-6, 6);
    y += random(-6, 6);
    element.position(x, y);
  };
    

    
}

比较


技法

这次的手绘只是一副表现出了画面中的具体物件的图画,没有表现出直观的动态,因此是比较简单的,没有用到什么特别的技巧,如果要做出动态的画面需要制作多幅图片再做出动画,工作量就比较大了。

本次的码绘主要分为了三个部分,分别是作为背景的有抖动效果的文字,背景闪烁跳动的圆和前面控制小方块运动的小丑。背景产生的圆的位置和大小是随机的,互相会发生碰撞,和画布边界也会碰撞。文字抖动主要是使文字发生快速位移,产生抖动效果。小丑比较简单就是静态描绘,小丑控制的方块则是利用了方块坐标的改变,得到动态的效果。主要参考了两个案例,参考文献给出。

工具


码绘是基于p5.js实现 

手绘依旧使用纸笔作画

理念


手绘和码绘的重点始终是在“绘”上,因此首先需要的是对画面的构思,对场景里物体的摆放,但两种方法又给我提供了不同的效果选择,码绘能够更为轻松的实现规则或随机的流畅动态,手绘能更精致更准确地描述出笔者的真实感受。但无论哪一种,都是十分好的表达途径。

创作体验


因为最开始没有一个十分完备的画面构思,因此在进行码绘的时候是十分苦恼的,在每一次新的尝试中常常是不能达到想象的效果但是又有可能出现更加有趣的图像,所以其实是拥有了很多选择但是没有一个画面主题。最后还是先确定了主题手绘画出了想要的画面,再通过码绘进行了动态实现,可以说是一次手绘码绘的合作了,最后的结果还是非常满意的。

呈现效果

手绘的图片可能没有码绘的这么好看,但毕竟是先用手绘确定了基本画面,其实如果用数位板画画并且做出多张图片的话呈现的动画效果应该是和码绘旗鼓相当甚至要更好的,因为笔者可以确定到每一帧地创作修改,但是这样工作量太大了,因此这种并不需要太精细的动态效果还是码绘更高效,码绘呈现的动态效果也非常灵动。

参考文献

https://p5js.org/zh-Hans/examples/motion-bouncy-bubbles.html

https://p5js.org/zh-Hans/examples/dom-modifying-the-dom.html


 

基于数据挖掘的音乐推荐系统设计与实现 需要一个代说明,不需要论文 采用python语言,django框架,mysql数据库开发 编程环境:pycharm,mysql8.0 系统分为前台+后台模式开发 网站前台: 用户注册, 登录 搜索音乐,音乐欣赏(可以在线进行播放) 用户登陆时选择相关感兴趣的音乐风格 音乐收藏 音乐推荐算法:(重点) 本课题需要大量用户行为(如播放记录、收藏列表)、音乐特征(如音频特征、歌曲元数据)等数据 (1)根据用户之间相似性或关联性,给一个用户推荐与其相似或有关联的其他用户所感兴趣的音乐; (2)根据音乐之间的相似性或关联性,给一个用户推荐与其感兴趣的音乐相似或有关联的其他音乐。 基于用户的推荐基于物品的推荐 其中基于用户的推荐是基于用户的相似度找出相似相似用户,然后向目标用户推荐其相似用户喜欢的东西(你类似的人也喜欢**东西); 而基于物品的推荐是基于物品的相似度找出相似的物品做推荐(喜欢该音乐的人还喜欢了**音乐); 管理员 管理员信息管理 注册用户管理,审核 音乐爬虫(爬虫方式爬取网站音乐数据) 音乐信息管理(上传歌曲MP3,以便前台播放) 音乐收藏管理 用户 用户资料修改 我的音乐收藏 完整前后端源,部署后可正常运行! 环境说明 开发语言:python后端 python版本:3.7 数据库:mysql 5.7+ 数据库工具:Navicat11+ 开发软件:pycharm
MPU6050是一款广泛应用在无人机、机器人运动设备中的六轴姿态传感器,它集成了三轴陀螺仪三轴加速度计。这款传感器能够实时监测并提供设备的角速度线性加速度数据,对于理解物体的动态运动状态至关重要。在Arduino平台上,通过特定的库文件可以方便地与MPU6050进行通信,获取并解析传感器数据。 `MPU6050.cpp``MPU6050.h`是Arduino库的关键组成部分。`MPU6050.h`是头文件,包含了定义传感器接口函数声明。它定义了类`MPU6050`,该类包含了初始化传感器、读取数据等方法。例如,`begin()`函数用于设置传感器的工作模式I2C地址,`getAcceleration()``getGyroscope()`则分别用于获取加速度角速度数据。 在Arduino项目中,首先需要包含`MPU6050.h`头文件,然后创建`MPU6050`对象,并调用`begin()`函数初始化传感器。之后,可以通过循环调用`getAcceleration()``getGyroscope()`来不断更新传感器读数。为了处理这些原始数据,通常还需要进行校准滤波,以消除噪声漂移。 I2C通信协议是MPU6050与Arduino交互的基础,它是一种低引脚数的串行通信协议,允许多个设备共享一对数据线。Arduino板上的Wire库提供了I2C通信的底层支持,使得用户无需深入了解通信细节,就能方便地与MPU6050交互。 MPU6050传感器的数据包括加速度(X、Y、Z轴)角速度(同样为X、Y、Z轴)。加速度数据可以用来计算物体的静态位置动态运动,而角速度数据则能反映物体转动的速度。结合这两个数据,可以进一步计算出物体的姿态(如角度角速度变化)。 在嵌入式开发领域,特别是使用STM32微控制器时,也可以找到类似的库来驱动MPU6050。STM32通常具有更强大的处理能力更多的GPIO口,可以实现更复杂的控制算法。然而,基本的传感器操作流程数据处理原理与Arduino平台相似。 在实际应用中,除了基本的传感器读取,还可能涉及到温度补偿、低功耗模式设置、DMP(数字运动处理器)功能的利用等高级特性。DMP可以帮助处理传感器数据,实现更高级的运动估计,减轻主控制器的计算负担。 MPU6050是一个强大的六轴传感器,广泛应用于各种需要实时运动追踪的项目中。通过 Arduino 或 STM32 的库文件,开发者可以轻松地与传感器交互,获取并处理数据,实现各种创新应用。博客其他开源资源是学习解决问题的重要途径,通过这些资源,开发者可以获得关于MPU6050的详细信息实践指南
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值