熵與負熵
熵遵循熵增原理,即無序非熱能與熱能之間的轉換具有方向性。薛定諤說過:生命本質在於負熵。熵代表的是無序,負熵就是熵的對立,而負熵表示的則是有序。汲取負熵(米飯、面包、牛奶、雞蛋),可以簡單的理解為從外界吸收了物質或者能量之后,轉化成負熵流,使系統的熵降低,人體變得更加有序。
那么一直吃飯為何還衰老?一日吃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/