1

我正在修改一个 Javascript 游戏,需要在游戏板顶部添加一个倒数计时器(从 3:00 分钟到 0 秒)。我已经编写了游戏和计时器,当用户单击游戏的“开始”按钮时,计时器将启动。(即游戏定时在3分钟后结束)

我的问题是,由于 JavaScript 不是多线程的,所以当用户同时玩我的游戏时,我的游戏倒数计时器将不允许运行(滴答)。那是对的吗?

在我看来,除了使用新的多线程 JavaScript 库之外,还有一些方法可以让它工作。

这是我的计时器:

<script type="text/javascript">
// set minutes
var mins = 3;
// calculate the seconds (don't change this! unless time progresses at a different speed for you...)
var secs = mins * 60;

function countdown() {
    setTimeout('Decrement()',1000);
}

function Decrement() {
    if (document.getElementById) {
        minutes = document.getElementById("minutes");
        seconds = document.getElementById("seconds");
        // if less than a minute remaining
        if (seconds < 59) {
            seconds.value = secs;
        } else {
            minutes.value = getminutes();
            seconds.value = getseconds();
        }
        secs--;
        setTimeout('Decrement()',1000);
    }
}

function getminutes() {
    // minutes is seconds divided by 60, rounded down
    mins = Math.floor(secs / 60);
    return mins;
}

function getseconds() {
    // take mins remaining (as seconds) away from total seconds remaining
    return secs-Math.round(mins *60);
}
</script>

<script>
countdown();
</script>


<div id="timer">
    <input id="minutes" value="3" type="text" style="width: 14px; border: none; background-color:none; font-size: 16px; font-weight: bold;">:<input id="seconds" value="00" type="text" style="width: 26px; border: none; background-color:none; font-size: 16px; font-weight: bold;"> remaining
</div>

这是我的游戏中启动一切的部分:

<script>
$(function(){
    $("#button-start").click(game.start);
});
</script>

如何game.start运行该countdown()方法以及我的计时器中的方法?每次单击“开始”时我尝试运行这两种方法时,JavaScript 都不会运行。没有任何效果并且它冻结了,我假设有两种方法试图同时运行?

4

5 回答 5

2

你应该只使用setTimeout,然后它不会阻塞

var initialTime = new Date();
function updateTimer() {
    if (new Date() - initialTime > (1000 * 1000 * 60 * 3) ) {
         document.getElementById('clock').innerHTML = formatTime();
         setTimeout(updateTimer, 1000);    
    }
}
updateTimer();

只是不要使用繁忙的循环

于 2013-02-28T21:20:38.340 回答
1

除非您的游戏使用某种繁忙的循环,例如,像这样:

while (1) {
    // process next event
}

......那么你不应该担心它。您的 JavaScript 引擎会自动将用户事件与计时器事件交错,因此计时器不应该被饿死。

于 2013-02-28T21:17:35.610 回答
1

单程:

var S_LEFT = 180;
function myTicker(){
  console.log('tick');
  S_LEFT -= 1;
  if(S_LEFT === 0) doSomething();
  $('#seconds').html(S_LEFT);
};

$('#start').on('click', function(){
  window.setInterval(myTicker, 1000);
});

@Juan Mendes 使用 setTimeout 而没有 Jquery 的方式:

var S_LEFT = 180;
function tick(){
  console.log('tick');
  S_LEFT -= 1;
  if(S_LEFT === 0){ 
    alert('Boom');
  } else {
    document.body.innerHTML = S_LEFT;
    window.setTimeout(tick, 1000);
  }
};
//document.addEventListener('DOMContentLoaded',tick,false);
tick();
于 2013-02-28T21:28:04.113 回答
0

我正在使用setTimeout('Decrement()',1000);

当我应该使用setTimeout(Decrement,1000);

在“减量”之后删除单引号和括号解决了我的问题。

于 2013-03-05T17:46:29.647 回答
0

所有这些答案对我来说似乎都太复杂了。

为什么不简单地在第一次使用启动计时器时以秒为单位获得时间戳

var beginTimestamp = Math.floor(Date.now() / 1000)

然后做你的结束

var endTimestamp = beginTimestamp + (3*60)

然后在更新时,获取剩余的秒数

var numSecondsRemaining = endTimestamp - Math.floor(Date.now()/1000)

最后

if(numSecondsRemaining <= 0) { /* end game */ }

要格式化,只需执行

var date = new Date(numSecondsRemaining*1000);
var minutes = "0" + date.getMinutes();
var seconds = "0" + date.getSeconds();
var formattedTime = minutes.substr(-2) + ':' + seconds.substr(-2);

这种方法不受 setTimeout 可能容易出现的任何问题的影响。它也小得多,基本上不需要数学。

于 2015-09-17T22:47:38.303 回答