码绘:使用p5.js创作简单的货车运动动画

使用工具
Visual Studio Code+p5.js
下载地址
Visual Studio Code:https://code.visualstudio.com/Download
p5.js:https://p5js.org/zh-Hans/download/
目标
在网页上画出一辆货车,通过运用循环、条件分支、函数等流程控制方法来达到动态的效果。
具体流程
首先我们建立一个index.html文件(主页)和一个car.js文件(码绘实现文件),并把car.js和p5.js链接到index.html上。
在这里插入图片描述
在car.js中我们创建setup()和draw()两个函数,用于画布的初始化和作图。

// car.js
function setup() {
  createCanvas(1440, 750);
}

function draw() {
  background(0);
}

然后加上地面和两个车轮。
在这里插入图片描述

// car.js
function setup() {
  createCanvas(1440, 750);
}

function draw() {
  background(0);
  stroke(255);
  line(0,600,1440,600);
  push();

  translate(400,500);
  tyre();

  pop();

  translate(900,500);
  tyre();
}

function tyre(){
  //轮胎
fill(255);
ellipse(0,0,200,200);
fill(0);
ellipse(0,0,160,160);

fill(255);
ellipse(0,0,40,40);


//钢圈十字
fill(255);
ellipse(0,-50,40,80);
fill(255);
ellipse(0,50,40,80);

fill(255);
ellipse(-50,0,80,40);
fill(255);
ellipse(50,0,80,40);

//轴
fill(0);
ellipse(0,0,30,30);
fill(255);
ellipse(0,0,20,20);
}

注意这里使用的pop()和push()函数。push() 函数将储存当时的绘画样式设置及变形,而 pop() 将恢复这些设置。这两个函数需要一起使用。它们让您改变样式及变形设置然后再回到您之前的设置。由于p5.js的translate()、rotate()等函数的效果在draw()的一次调用中是累积的,不使用pop()和push()函数的话会导致移动、旋转等代码的效果的重叠。

车轮的旋转
定义两个变量step(控制旋转速度)和angle(每调用一次draw()车轮旋转的角度)用于车轮的旋转。

// car.js
var step=0.1;
var angle=0;

将draw()中代码改至如下

// car.js
function draw() {
  background(0);
  stroke(255);
  line(0,600,1440,600);
  push();

  if(angle<2*PI)
  {
    angle+=step*PI;
  }
  else
    angle=0;
  translate(400,500);
  rotate(angle);
  tyre();
  
  pop();
  push();

  translate(900,500);
  rotate(angle);
  tyre();
 
  pop();
}

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

车身部分我们直接在draw中修改

// car.js
function draw() {

  background(0);
  stroke(255);
  line(0,600,1440,600);
  //车身部分
  push();
  stroke(150);
  fill(150);
  rect(250,300,800,200,5);

  stroke(100);
  fill(100);
  rect(750,150,150,150);
  triangle(900,150,900,300,1050,300);

  stroke(160);
  fill(160);
  stroke(255);
  rect(800,200,100,100);
  triangle(900,200,900,300,1000,300);
 //车轮部分
  stroke(255);
  if(angle<2*PI)
  {
    angle+=step*PI;
  }
  else
    angle=0;
  translate(400,500);
  rotate(angle);
  tyre();
  
  pop();
  push();

  translate(900,500);
  rotate(angle);
  tyre();
 
  pop();
}

效果
在这里插入图片描述

最后我们加上一棵草作为参照物,来使得整幅图“动起来”。

// car.js
var grassstep=1440;
function draw() {

  background(0);
  stroke(255);
  line(0,600,1440,600);

  push();
  stroke(150);
  fill(150);
  rect(250,300,800,200,5);

  stroke(100);
  fill(100);
  rect(750,150,150,150);
  triangle(900,150,900,300,1050,300);

  stroke(160);
  fill(160);
  stroke(255);
  rect(800,200,100,100);
  triangle(900,200,900,300,1000,300);
 
  stroke(255);
  if(angle<2*PI)
  {
    angle+=step*PI;
  }
  else
    angle=0;
  translate(400,500);
  rotate(angle);
  tyre();
  
  pop();
  push();

  translate(900,500);
  rotate(angle);
  tyre();
 
  pop();

  push();

  if(grassstep>-20)
    grassstep-=5;     
  else
    grassstep=1440;

  translate(grassstep,0);
  weed();
  pop();
}

function weed(){
  stroke(160);
  fill(160);
  stroke(255);
  triangle(20,600,40,600,0,580);
  triangle(20,600,40,600,28,560);
  triangle(20,600,40,600,43,585);
}

效果在这里插入图片描述
到此为止,一个简单的货车运动作画已经完成。

我们可以将官方的雪花特效加进去,使画面更加丰满。
效果图
在这里插入图片描述
附上源码

// car.js
var step=0.1;
var angle=0;
var grassstep=1440;
let snowflakes = []; 
function setup() {
  createCanvas(1440, 750);
  

}

function draw() {
  background(0);
  stroke(255);
  line(0,600,1440,600);
  
  push();
  stroke(150);
  fill(150);
  rect(250,300,800,200,5);

  stroke(100);
  fill(100);
  rect(750,150,150,150);
  triangle(900,150,900,300,1050,300);

  stroke(160);
  fill(160);
  stroke(255);
  rect(800,200,100,100);
  triangle(900,200,900,300,1000,300);
 
  stroke(255);
  if(angle<2*PI)
  {
    angle+=step*PI;
  }
  else
    angle=0;
  translate(400,500);
  rotate(angle);
  tyre();
  
  pop();
  push();

  translate(900,500);
  rotate(angle);
  tyre();
 
  pop();
  push();

  if(grassstep>-20)
    grassstep-=5;     
  else
    grassstep=1440;

  translate(grassstep,0);
  weed();
  pop();

  let t = frameCount / 60; // update time

  // create a random number of snowflakes each frame
  for (var i = 0; i < random(5); i++) {
    snowflakes.push(new snowflake()); // append snowflake object
  }

  // loop through snowflakes with a for..of loop
  for (let flake of snowflakes) {
    flake.update(t); // update snowflake position
    flake.display(); // draw snowflake
  }

  
}


function tyre(){
     //轮胎
  fill(255);
  ellipse(0,0,200,200);
  fill(0);
  ellipse(0,0,160,160);

  fill(255);
  ellipse(0,0,40,40);
  

  //钢圈十字
  fill(255);
  ellipse(0,-50,40,80);
  fill(255);
  ellipse(0,50,40,80);

  fill(255);
  ellipse(-50,0,80,40);
  fill(255);
  ellipse(50,0,80,40);

  //轴
  fill(0);
  ellipse(0,0,30,30);
  fill(255);
  ellipse(0,0,20,20);
}

function weed(){
  stroke(160);
  fill(160);
  stroke(255);
  triangle(20,600,40,600,0,580);
  triangle(20,600,40,600,28,560);
  triangle(20,600,40,600,43,585);
}

function snowflake() {
  // initialize coordinates
  this.posX = 0;
  this.posY = random(-50, 0);
  this.initialangle = random(0, 2 * PI);
  this.size = random(2, 5);

  // radius of snowflake spiral
  // chosen so the snowflakes are uniformly spread out in area
  this.radius = sqrt(random(pow(width / 2, 2)));

  this.update = function(time) {
    // x position follows a circle
    let w = 0.6; // angular speed
    let angle = w * time + this.initialangle;
    this.posX = width / 2 + this.radius * sin(angle);

    // different size snowflakes fall at slightly different y speeds
    this.posY += pow(this.size, 0.5);

    // delete snowflake if past end of screen
    if (this.posY > height) {
      let index = snowflakes.indexOf(this);
      snowflakes.splice(index, 1);
    }
  };

  this.display = function() {
    ellipse(this.posX, this.posY, this.size);
  };
}

码绘与手绘相比
在这里插入图片描述
手绘由于是静态的,来表现车的运动效果主要有速度线、车轮线、烟雾以及物体高速变形,通过这些静态的线条来还原物体运动的效果。而码绘则是通过参数的改变实现每一帧图像的变化来达到动态的效果,比起手绘更直观地体现了“动感”这个词。在细节方面,手绘明显更胜一筹,可以方便地勾勒出车的细节,而码绘由于参数、循环等一系列问题(可能动一个参数就要改一大片,以及坐标问题),在绘画体验上明显不行。整体比较下来,手绘给人的感觉更具艺术气息,能够感受到一股人情味,码绘虽然更容易产生动感的效果,线条更加精准,但是总感觉少了一份绘画原有的感觉,更像是另一种艺术创作形式,而不是在绘画。

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值