最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

multithreading - Javascript game with timer - Stack Overflow

programmeradmin1浏览0评论

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

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

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? Everytime I try to run both of the methods when "start" is clicked, the JavaScript doesn't run at all. Nothing works and it freezes up, I assume from two methods trying to run at once?

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

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

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? Everytime I try to run both of the methods when "start" is clicked, the JavaScript doesn't run at all. Nothing works and it freezes up, I assume from two methods trying to run at once?

Share Improve this question edited Feb 28, 2013 at 21:25 CODe asked Feb 28, 2013 at 21:12 CODeCODe 2,3016 gold badges36 silver badges66 bronze badges 4
  • No, that is not correct. Timers still run regardless. – Diodeus - James MacFarlane Commented Feb 28, 2013 at 21:16
  • How are we suppose to help without your code? Are you using a for loop for the countdown instead of setTimeout? – Ruan Mendes Commented Feb 28, 2013 at 21:17
  • "Playing the game" is not a synchronous, browser-freezing 3-minute-lasting script execution, is it? The timer will have a chance to fire during the event loop. – Bergi Commented Feb 28, 2013 at 21:26
  • @Bergi It's an interactive game, it constantly changes images (once every 2 seconds) and requires the user to press keyboard buttons. – CODe Commented Feb 28, 2013 at 21:29
Add a ment  | 

5 Answers 5

Reset to default 2

You should just use setTimeout, then it won't block

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

Unless your game uses some sort of a busy loop, i.e., 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.

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:

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

when I should have been using setTimeout(Decrement,1000);

Removing the single quotes and parenthesis after "Decrement" solved my problem.

All of these answers seem way too plex 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. It's also much smaller, and requires basically no math.

发布评论

评论列表(0)

  1. 暂无评论