Chapter4 - Canvas背景动画(I)让落叶随风飘落、自然摇摆

本篇衔接上篇:https://ithelp.ithome.com.tw/articles/10272738

该如何让动画更自然?

今天来深入聊聊怎麽调节动画模式的随机性

今天由四个部分组成,来作循序渐进的思考:
让我们用 今天的演示 来感受一下
https://ithelp.ithome.com.tw/upload/images/20210929/20135197jTaxhEEYic.png

为了没看过前面19篇的朋友们简述一下步骤

  1. 点选「上传音乐」或「请选择曲名」来换一首歌
  2. 点选「Play」进行播放,点选「Pause」暂停
  3. 选择不同模式感受动画的变化

规律

如果试着用昨天的代码去跑动画,就会发现它看起来相当规律

什麽意思呢?当时的角速度预设为定值,那每个物件的简谐运动就很单纯:

this.rotateOmega = 60 / 180 * Math.PI;
this.revolveOmega = 60 / 180 * Math.PI;

那如果我单纯把60这个数字改成随机的40~80之间行不行?这个问题留给大家思考答案,并想看看为什麽,欢迎留言表达观点。

当角速度是定值时,就会发现动画的路径相当规律,可以很容易地透过观察发现,每一个物件基本相同,更可以轻松预测动画的走向,显得呆版、无聊,却可以减少使用者的负荷,更加轻松、具有一致性,很适合用在简单的关卡,当你更重视注重情节而非挑战性,规律显然是最舒适的

多样(period=1~2)

昨天我们写了一个随机数:this.period = 1 + Math.random() * 1;,但还没真正拿来用,而之所以设定period的理由,其实是希望简谐运动摇摆的幅度有大有小,假如周期不变,则幅度越大时移动速度越快,这样就会变得相当奇怪(可以想像摆福是整个萤幕的宽度,然後在3秒间来回摆动),因此在摆福增加的时候也同时让周期增加,这就是设定一个介於1~2之间的period之用意。

因此角速度除以period以後:

this.rotateOmega = 60 / this.period / 180 * Math.PI;
this.revolveOmega = 60 / this.period / 180 * Math.PI;

去把对应的摆福乘上period:

this.pointX = this.beginX + this.period * WIDTH * 0.04 * A + WIDTH * 0.02 * dT;
this.pointY = this.beginY + this.period * HEIGHT * 0.015 * C + HEIGHT * 0.08 * dT;

再顺便提醒一下,最右侧dT所负责的参数,就是动画的线性前进方向,较容易被肉眼观察!

当我们如上述代码设置,就会使画面更加生动,每一个彷佛都是独立的个体,有着自己的运动轨迹,很难将两三个物件联想在一起,不过作为整体来看,还是能稍微看出整个动画的走向,正往斜右下掉落,能够良好的表达当前的意境,彷佛真的随风飘落一般。

混乱

除了上述的作法,还可以考量到在角速度不变的情况下,增减整体的位移,设计两个随机数:

this.scaleX = 0.5 + Math.random() * 1;
this.scaleY = 0.5 + Math.random() * 1;

用来缩放XY的位移,使得有些走得更长,有些走的更短:

let x = this.scaleX * (this.period * WIDTH * 0.04 * A + WIDTH * 0.02 * dT);
let y = this.scaleY * (this.period * HEIGHT * 0.02 * C + HEIGHT * 0.06 * dT);
this.pointX = this.beginX + x;
this.pointY = this.beginY + y;

其实混乱概念上也就是远近效果,可以搭配物件大小或Z轴作为参考标准,就不会显得如此混乱

与上面的多样相比,较难感受到随风飘落的意境,更像是有更多不确定因素,是一个混乱的系统,即便还是能感受到物件来回摆动,然而物件的移动总是不如预期,似乎总会差一些、差一点,让人觉得整体不和谐,各个都在捣乱的样子,适合用於困难的关卡,增加挑战性和挫折感。

自由

这是一个很主观的定义,主要是对於掌控感下去作讨论,我认为设计游戏,无非就是思考:如何让使用者感受到他能主宰整个游戏世界,享受无边无际的自由,强调回馈感这件事,是一个很值得摸索的设计,假如我们用在落叶掉落之时,那是否使用者就主宰了这个小世界,能随着滑鼠的移动来改变动画的行进,那是否,也掌控了风神呢?

采用的就是第二章用的滑鼠跟随机制,参数设哪个没有限制,看想研究哪个就设那个,该范例设置的是旋转角速度:

function MouseAnime(){
    myMouse.NextFrame();
    animeList.forEach(obj => {
        obj.rotateOmega = myMouse.pointX * 40 / obj.period / 180 * Math.PI;
        if(mode == 'Free'){
            obj.scaleX = 1 + myMouse.pointX/2;
            obj.scaleY = 1 + myMouse.pointY/2;
        }
    })
}

不过要注意,每次滑鼠改变都会刷新,因此这种方法不能直接用於随机数,比方说若想测试period,就得把一开始的随机数存起来另外放,因此需要两个变数。


<<:  【领域展开 12 式】 安装 Soledad 主题插件,成功汇入漂亮模板到网站罗

>>:  [DAY 12] AWS RDS 之 Aurora

[Day12]C# 鸡础观念- 当我们同在一起~阵列(Array)

成绩单上有国,英,数,物理四科 分数分别70、89、72、93 这时候我们就可以用阵列将他们绑再一起...

Day7-"常数"

今天补充一些之前没提到的内容 我们在日常生活中几乎都会看见它的身影,像是圆周率、自然数、光速,这些永...

Angular Stock登入(四)(Day25)

透过昨天我们提到的路由,今天我们要实现登入後将token存入sessionStorage後转导到首页...

Day04 - Parsing Ptt

在前一篇我们已经顺利使用WebSocket连上Ptt了,接着要做的事情就是读取Server回传的内容...

Day6:今天来聊一下如何布署Microsoft Defender for Endpoints

当我们第要建立Microsoft Defender for Endpoints环境时 首先我们先到M...