微信号:FrontDev

介绍:分享 Web 前端相关的技术文章、工具资源、精选课程、热点资讯

时光倒流程序设计-AlloyTicker

2016-08-03 19:56 伯乐专栏\/欲休

(点击上方公众号,可快速关注)

来源:AlloyTeam

链接:www.alloyteam.com/2016/07/clock-programming-alloyticker/


熵与负熵


熵遵循熵增原理,即无序非热能与热能之间的转换具有方向性。薛定谔说过:生命本质在于负熵。熵代表的是无序,负熵就是熵的对立,而负熵表示的则是有序。汲取负熵(米饭、面包、牛奶、鸡蛋),可以简单的理解为从外界吸收了物质或者能量之后,转化成负熵流,使系统的熵降低,人体变得更加有序。


那么一直吃饭为何还衰老?一日吃6餐行不行?答案是肯定不行。

负熵流和熵增伴从出生到死亡一直在对抗,随着时间流逝,负熵流慢慢对抗不过熵增,人体组织体系结构越来越无序。越无序就越难以抵抗疾病,所以通常死亡不是熵增到无序而老死,而是熵值较大时,难以抵抗其他疾病而死亡。最终归于尘土、洒向大海(更加无序了)。

所以:熵增加的方向就是时间的方向,时间不可逆,回到过去是不可能的,才有了AlloyTicker-让时光倒流成为可能….


Github: https://github.com/AlloyTeam/AlloyTicker

Demo: http://alloyteam.github.io/AlloyTicker/


传统的动画和运动


涉及到动画和运动才能和时间关联起来。这里做下分类:

1.精灵图动画:如利用精灵图实现人物跑、走等

2.积分运动:如粒子系统、子弹飞行等

3.缓动:如骨骼动画、弹出层特效、金币拾取等其他拥有起点、终点、时间和缓动函数的运动


精灵图动画



如上面的精灵图动画,当需要求出当前播放哪一帧的时候,通常按照下面这种方式计算:


 var index = Math.floor(dt / interval) % length;


其中index为当前求出的结果。

dt为过去了多长时间

interval每一帧的间隔时间

length为总共的帧数


精灵图动画可逆设计


要实现精灵图动画可逆,必须对dt进行动态计算。dt怎么计算?

dt = 当前时间 – 开始时间

即:


var dt = currentTime - startTime;

var index = Math.floor(dt / interval) % length;


只需要把currentTime和startTime保存好方便sprite对象使用即可实现可逆。

当然这里要做边界处理,即dt小于0,代表播放时间还未开始,index是没有对应的值。


积分运动



传统的做法:


this.vx += this.ax * dt;

this.vy += this.ay * dt;

this.x += this.vx* dt;

this.y += this.vy * dt;


即:

速度是加速度在时间上的累加

位移是速度在时间上的累加


积分运动可逆设计


问题建模:根据起点位置(startX startY)、起始速度(vx vy)、加速度(ax ay)、开始时间(startTime)、当前时间(currentTime)求当前位置(x y)。


var dt = this.currentTime - this.startTime;

var h_sqDt = dt * dt/2;

this.x = this.startX + this.vx * dt + this.ax * h_sqDt;

this.y = this.startY + this.vy * dt + this.ay * h_sqDt;


公式:



缓动



this.dv = this.endValue - this.startVaule ;

var result = this.startVaule + this.dv * this.ease(dt / this.time);


其中result为当前求出的结果。

endValue为最终要运动到的结果

startVaule为开始运动的状态

ease为缓动函数

time为总时间


缓动可逆设计


缓动天生就是支持可逆设计。只需计算好dt便可。


var dt = currentTime - startTime;


当然还要处理一下边界情况,因为时间的流动性,dt是可能大于0或者dt大于传入的总时间this.time。

当dt小于0,即result等于this.startVaule

当dt大于总时间,即result等于this.endVaule


精灵图动画+积分运动



如上面的超级玛丽,不仅需要播放精灵图动画,还需要向右的积分运动。所以需要同时顾及两种状态:


var dt = this.currentTime - this.startTime;

//计算关键帧索引的结果

if (dt < 0) {

    this.index = -1;

} else {

    this.index = Math.floor(dt / this.interval) % this.length;

}

//计算积分运动的结果

this.x = this.startX + this.vx * dt;

this.y = this.startY + this.vy * dt;


AlloyTicker


是时候抽象出一个时间机器的-AlloyTicker。


var AlloyTicker = function(){

    this.interval= null;

    this.intervalTime= 16;

    this.tickIntervalTime = 16;

    this.currentTime = 0;

    this.clockwise = true;

    this.ticks=[];

    this.isPause = false;

    this.isStop = false;

}

AlloyTicker.prototype = {

    //时间开始

    start: function () {

        this.interval = setInterval(function () {

            if(!this.isPause){

                this.currentTime += (this.clockwise ? this.intervalTime : -1 * this.intervalTime);

                if(this.currentTime<0)this.currentTime=0;

                this.tick();

            }

        }.bind(this), this.tickIntervalTime);

    },

    tick: function () {},

    //时光倒流

    back: function () {

        this.clockwise = false;

    },

    forward: function () {},

    goto: function(time){},

    pause:function(){},

    play :function(){},

    stop:function() {},

    scale:function(value){}

}


因为:

1.从逻辑层面上currentTime不属于动画或运动对象的属性,都属于AlloyTicker时间机器的属性。

2.统一时间管理(倒流(back)、暂停(pause)、加速减速(scale)、时间跳转(goto)…)

3.所有对象的动画和运动都跟AlloyTicker挂钩,AlloyTicker时间状态的变更会影响到所有挂钩的对象


Github: https://github.com/AlloyTeam/AlloyTicker

Demo: http://alloyteam.github.io/AlloyTicker/


【今日微信公号推荐↓】

更多推荐请看值得关注的技术和设计公众号


其中推荐了包括技术设计极客 和 IT相亲相关的热门公众号。技术涵盖:Python、Web前端、Java、安卓、iOS、PHP、C/C++、.NET、Linux、数据库、运维、大数据、算法、IT职场等。点击《值得关注的技术和设计公众号》,发现精彩!


 
前端大全 更多文章 看懂此文,不再困惑于 JS 中的事件设计 工作五年,后面四年重复着第一年的活儿? js从0开始构思表情插件 FineReport第二届平台主题开发大赛,参与奖2000元,你会JS\/CSS吗? 从零开始,DIY一个jQuery(1)
猜您喜欢 不适合当一名开发人员的10种迹象 给大一师弟师妹的一些建议 MBH俱乐部论坛搭建完毕 【ReactNative For Android】框架启动核心路径剖析 PHP通过CRUL上传文件