请注意,这是我之前的一个后续问题:“How to memorize user's progress through the application?”。
在答案之后,我明白错误是使用Javascript来确定用户是否赢得了比赛。所以我将逻辑移到我的控制器中:当用户启动关卡时,我将UNIX时间戳保存到会话中,并在用户结束时计算差异。如果用户完成关卡的时间不超过X秒,我允许他/她访问下一个,依此类推。
一切正常,直到我决定引入用Javascript制作的客户端计时器。计时器显然不像PHP那样准确,因为它依赖于用户的CPU而不是服务器的CPU。因此,两个定时器不同步。当时间范围很大时(例如,用户必须完成4到10秒之间的水平),游戏仍然有效,但是当时间范围较小(1或2秒)时,它不能按预期工作。即使用户在获胜时间框架内点击,PHP也会告诉他他没有获胜。
我做了一些尝试,这是我的结果:
|===========================|
| # | PHP | JS | Ratio |
|===========================|
| 1 | 6.20 | 5.29 | 1.17 |
| 2 | 7.32 | 6.27 | 1.16 |
| 3 | 2.89 | 2.24 | 1.29 |
| 4 | 22.56 | 20.13 | 1.12 |
| 5 | 50.15 | 45.24 | 1.10 |
|===========================|
(是的,我知道,这是有史以来最糟糕的ASCII表。)
这是我使用jQuery制作的计时器(我没有用这种语言练习过,所以它可能也是有史以来最糟糕的Javascript计时器):
$(document).ready(function() {
window['time'] = {
'cseconds': 0,
'dseconds': 0,
'seconds': 0,
'minutes': 0,
'hours': 0
};
$("#timer").everyTime(10, function() {
window['time']['cseconds'] += 1;
if (window['time']['cseconds'] > 9) {
window['time']['cseconds'] = 0;
window['time']['dseconds'] += 1;
}
if (window['time']['dseconds'] > 9) {
window['time']['dseconds'] = 0;
window['time']['seconds'] += 1;
}
if (window['time']['seconds'] > 60) {
window['time']['seconds'] = 0;
window['time']['minutes'] += 1;
}
if (window['time']['minutes'] > 60) {
window['time']['minutes'] = 0;
window['time']['hours'] += 1;
}
cseconds = window['time']['cseconds'].toString();
dseconds = window['time']['dseconds'].toString();
seconds = window['time']['seconds'].toString();
minutes = window['time']['minutes'].toString();
hours = window['time']['hours'].toString();
if (seconds.length < 2) {
seconds = "0" + seconds;
}
if (minutes.length < 2) {
minutes = "0" + minutes;
}
if (hours.length < 2) {
hours = "0" + hours;
}
$("#timer").text(hours + ":" + minutes + ":" + seconds + "." + dseconds + cseconds);
});
});
我尝试过不同的解决方案,比如AJAX:首先,计时器仅依赖于AJAX请求(导致数千个HTTP请求),但仍然不精确。然后我修改它以每隔X秒与PHP同步,但它也不起作用。
有没有人有任何提示?
答案 0 :(得分:3)
如果您通过在事件的开始和结束时执行new Date()
计时事件并比较它们之间的经过时间差异,您将使用javascript获得非常准确的计时。现代浏览器中定时器的精度通常为几毫秒,而旧版浏览器的定时器精度不低于15毫秒。
您的代码看起来像是在尝试使用间隔计时器并计算间隔。这不会很准确。因为javascript是单线程的,所以javascript计时器触发的确切时间不是非常精确,因此不应该依赖于事件的准确计时。换句话说,测量已用系统时间而不是计算已触发的计时器间隔要准确得多。
答案 1 :(得分:1)
为什么AJAX解决方案不起作用?这是我心中的第二个解决方案。它必须工作,因为时间来自服务器......
第一个解决方案非常简单,我认为最准确。而不是依赖于Javascript定期执行功能,尝试依赖系统日期时间。使用Javascript周期性功能更新屏幕上的时间,但使用系统日期/时间而不是简单的seconds += 1
来获取时间!一些伪代码:
var startTime = new Date();
// Every 1/2 second or less...
var elapsedTimeInMs = new Date().getTime() - startTime.getTime();
但我建议您阅读Date
个对象的文档。
答案 2 :(得分:0)
你将不得不使用AJAX,但只有在用户完成游戏的情况下,才能获得服务器上的时间......