前言:
在creator 开发中,我们经常要去获取时间, 如果仅仅只是用时间戳做一些客户端标记,用JavaScript 中的Date对象,完全可以满足需要,但是,如果牵扯到时间的显示,或者判断某些与时间有关的变量的时候, 仅仅使用Date 对象是不够的. 因为客户端本地的时间是可以调节的,用户调节了本地时间后,Date对象就会和服务器的时间不同步,会产生错误,那么这时候,我们就要获取服务器时间
方案:
1. 发送协议,获取服务器时间
2. 利用连线后的心跳协议(用来确认用户在线),来更新服务器的时间
3. 登录时获取服务器时间,客户端做定时器,自己维护这个时间
4. 登录时获取服务器时间,客户端记录当前游戏运行的时间. 服务器时间 = 初次获取的时间 + 游戏运行的时间差
很明显,方案4 是最好的.
游戏中有很多获取时间然后计算的地方,每次都从服务器获取,游戏的逻辑就没法完成了,所以方案1 不可行.
如果用方案二, 那么心跳的频率设置多少呢,频率高了,影响其他协议,低了时间又不同步,而且再两次心跳之间,需要使用时间时,会发现时间是一样的.方案2 不可行.
方案3,看似很不错,实际上也有瑕疵,如果游戏暂停,计时器就会停止运作,这时就会存在时间差
实现方法:
要获取运行时间就要用到 Performance 对象了, 我们不妨写成一个函数:
function getTickCount() {
if(window && window.performance){
return window.performance.now();
}
return (new Date()).getTime();
}
代码实例:
//一个服务器时间简单实现
function getTickCount() {
if(window && window.performance){
return window.performance.now();
}
return (new Date()).getTime();
}
export class ServerTime {
private _t: number;
private _lastSetTime: number;
private _timer: number;
constructor(t) {
let self = this;
self._t = t || (new Date()).getTime(); // 时间戳
self._lastSetTime = getTickCount(); // 最后一次setTime时, 本地时间点
//实现一个计时器,每隔一段时间和服务器同步一下时间
//self._timer = ...
}
public setTime(t): void {
// 链接服务器后,调用这个方法同步服务器时间
let self = this;
self._t = t; //
self._lastSetTime = getTickCount();
}
//--获取当前的服务器时间戳
public getTime(): number {
let self = this;
let elapsed = getTickCount - self._lastSetTime;
return self._t + elapsed;
}
}
上面的代码,连接服务器后,收到服务器时间后调用setTime
可以不要定时器.