简体   繁体   中英

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

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.

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

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 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. It's also much smaller, and requires basically no math.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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