简体   繁体   English

带计时器的Javascript游戏

[英]Javascript game with timer

I'm modifying a Javascript game and need to add a countdown timer (from 3:00 minutes to 0 seconds) at the top of the game board. 我正在修改Javascript游戏,需要在游戏面板顶部添加一个倒数计时器(从3:00分钟到0秒)。 I have both the game and timer written, the timer will start when the user clicks the "start" button for the game. 我同时编写了游戏和计时器,当用户单击游戏的“开始”按钮时,计时器将启动。 (ie the game is timed to end after 3 minutes) (即游戏定时在3分钟后结束)

My issue is that, since JavaScript is not multi-threaded, my game countdown timer will not be allowed to run (tick) while a user is concurrently playing my game. 我的问题是,由于JavaScript不是多线程的,所以当用户同时玩我的游戏时,我的游戏倒数计时器将不允许运行(滴答)。 Is that correct? 那是对的吗?

It just seemed to me that there would be some way to get this to work, outside of using the new multi-threading JavaScript libraries. 在我看来,除了使用新的多线程JavaScript库之外,还有某种方法可以使它起作用。

Here's my timer: 这是我的计时器:

<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>

Here's the portion of my game that kicks everything off: 这是我游戏的开始一切的部分:

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

How do I have the game.start method run as well as the countdown() method from my timer? 我如何运行game.start方法以及计时器中的countdown()方法? Everytime I try to run both of the methods when "start" is clicked, the JavaScript doesn't run at all. 每次单击“开始”时,我尝试同时运行这两种方法时,JavaScript根本不会运行。 Nothing works and it freezes up, I assume from two methods trying to run at once? 我认为有两种方法尝试一次运行,但没有任何效果,并且冻结了?

Unless your game uses some sort of a busy loop, ie, something like this: 除非您的游戏使用某种繁忙循环,即像这样的事情:

while (1) {
    // process next event
}

… then you shouldn't need to worry about it. ……那么您不必担心。 Your JavaScript engine will automatically interleave user events with timer events, so the timer shouldn't get starved. 您的JavaScript引擎会自动将用户事件与计时器事件交织在一起,因此计时器不会饿死。

You should just use setTimeout , then it won't block 您应该只使用setTimeout ,否则它不会阻塞

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

Just don't use a busy loop 只是不要使用繁忙的循环

one way: 单程:

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's way using setTimeout and no Jquery: @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();

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

when I should have been using setTimeout(Decrement,1000); 当我应该一直使用setTimeout(Decrement,1000);

Removing the single quotes and parenthesis after "Decrement" solved my problem. 在“减量”之后删除单引号和括号解决了我的问题。

All of these answers seem way too complex for me. 所有这些答案对我来说似乎太复杂了。

Why not simply get a timestamp in seconds upon first starting the timer using 为什么不首先使用以下方法启动计时器就以秒为单位获取时间戳

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

Then make your end 然后结束

var endTimestamp = beginTimestamp + (3*60)

Then on update, get the number of seconds remaining with 然后在更新时,获得剩余的秒数

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

and finally 最后

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

To format, just do 要格式化,只需

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

This approach isn't affected by any funkiness that setTimeout might be prone to. 此方法不受setTimeout可能容易出现的任何干扰的影响。 It's also much smaller, and requires basically no math. 它也小得多,并且基本上不需要数学。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM