I want to resume the game after pausing it, and it freezes the game, but after resuming, the game only gives you one key and the score is glitching between 0 and whatever score you actually have.
I tried using the clearTimeout() function to stop the function, store the timer, lives, score, and current key, however it seems to stuck on the one key I gave it.
This is the pause function:
function pause() {
window.addEventListener("keydown", (event) => {
if (event.key == 'Tab') {
if (!isPaused) {
isPaused = true;
gameIsPlaying = false;
window.currentKey = item
window.currentScore = score
window.currentTime = seconds
window.currentLives = lives
console.log(currentKey, currentScore, currentTime)
clearTimeout(timerId);
clearTimeout(updateLives);
clearTimeout(ScoreUpdate);
bars.forEach((bar) => {
bar.style.animationPlayState = 'paused';
})
AudioElement.pause();
} else {
isPaused = false;
item = currentKey
score = currentScore
seconds = currentTime
lives = currentLives
game(item, seconds, lives, score);
bars.forEach((bar) => {
bar.style.animationPlayState = 'running';
})
AudioElement.play();
}
}
})
}
JSFiddle: https://jsfiddle.net/b30osaLp/ (Tab to Pause game)
Edit: I tried @code's solution in the comments.
window.addEventListener("keydown", (event) => {
if (event.key == 'Tab') {
pause();
}
})
function pause() {
if (!isPaused) {
isPaused = true;
gameIsPlaying = false;
clearTimeout(timerId);
clearTimeout(updateLives);
clearTimeout(ScoreUpdate);
bars.forEach((bar) => {
bar.style.animationPlayState = 'paused';
})
AudioElement.pause();
} else {
isPaused = false;
game();
bars.forEach((bar) => {
bar.style.animationPlayState = 'running';
})
AudioElement.play();
}
}
But it still is producing the same issue.
2 Answers 2
I have managed to get your code to work, although I have re-written most of it.
I have removed all the extraneous features, such as AudioElement and the animated timer. I have simplified both your HTML and CSS.
You had 3 setIntervals, I have removed the Score and Lives intervals and replaced them by updating the relevant information when it is required do so.
I have collated all your event handlers into one per event type.
And I have used some functions, namely bindElement and styleElement, to tidy the code.
So now you can pause and restart the game! (Use Q - TAB has other uses and interferes with other code on the page).
window.focus();
var paused, timerId;
var item, pickTime;
var seconds, lives, score;
const keys = ["W", "A", "S", "D", "Q", "ENTER"];
function bindElement(ref) {
return document.getElementById(ref);
}
function styleElement(ref, clr, txt) {
ref.style.backgroundColor = clr;
ref.innerHTML = txt;
}
const LetterGUI = bindElement("Letter");
const TimerGUI = bindElement("Timer");
const LivesGUI = bindElement("Lives");
const ScoreGUI = bindElement("Score");
const W = bindElement("W");
const A = bindElement("A");
const S = bindElement("S");
const D = bindElement("D");
const PA = bindElement("playAgain");
document.onkeydown = function(e) {
var key = e.key.toUpperCase();
if (!keys.includes(key)) return;
if (key == 'Q') {
if (!paused) {
paused = true;
clearTimeout(timerId);
} else {
paused = false;
timerId = setTimeout(countdown, 0);
}
return;
}
if (key == "ENTER" && PA.style.visibility == "visible") {
game();
return;
}
if (key != item) {
lives--;
score -= 50;
if (lives < 1) {
gameOver();
return;
}
} else {
var elapsed = Math.floor(Date.now() / 1000) - pickTime;
if (elapsed < 1.5) score += 500;
else if (elapsed < 3) score += 350;
else if (elapsed < 5) score += 150;
}
ScoreGUI.innerHTML = "Score: " + score;
LivesGUI.innerHTML = "Lives: " + lives;
if (key == "W")
if (key == item) styleElement(W, 'lime', '');
else styleElement(W, 'red', '');
if (key == "A")
if (key == item) styleElement(A, 'lime', '');
else styleElement(A, 'red', '');
if (key == "S")
if (key == item) styleElement(S, 'lime', '');
else styleElement(S, 'red', '');
if (key == "D")
if (key == item) styleElement(D, 'lime', '');
else styleElement(D, 'red', '');
letter();
}
document.onkeyup = function(e) {
var key = e.key.toUpperCase();
if (key == "W") styleElement(W, 'white', 'W');
if (key == "A") styleElement(A, 'white', 'A');
if (key == "S") styleElement(S, 'white', 'S');
if (key == "D") styleElement(D, 'white', 'D');
}
function letter() {
item = keys[Math.floor(Math.random() * 4)];
LetterGUI.innerHTML = "Letter: " + item;
pickTime = Math.floor(Date.now() / 1000);
}
game();
function game() {
paused = false;
styleElement(W, 'white', 'W');
styleElement(A, 'white', 'A');
styleElement(S, 'white', 'S');
styleElement(D, 'white', 'D')
TimerGUI.style.color = "white";
PA.style.visibility = "hidden";
seconds = 20;
lives = 3;
score = 0;
letter();
ScoreGUI.innerHTML = "Score: " + score;
LivesGUI.innerHTML = "Lives: " + lives;
timerId = setTimeout(countdown, 0);
}
function countdown() {
seconds--;
if (seconds < 0) {
gameOver();
return;
}
if (seconds <= 5) TimerGUI.style.color = "red";
if (seconds > 9) TimerGUI.innerHTML = "Time: " + seconds;
else TimerGUI.innerHTML = "Time: 0" + seconds;
timerId = setTimeout(countdown, 1000);
}
function gameOver() {
clearTimeout(timerId);
styleElement(W, 'red', '');
styleElement(A, 'red', '');
styleElement(S, 'red', '');
styleElement(D, 'red', '')
LetterGUI.innerHTML = "";
TimerGUI.innerHTML = "";
ScoreGUI.innerHTML = "Score: " + score;
LivesGUI.innerHTML = "Lives: " + lives;
PA.style.visibility = "visible";
}
body {
background-color: #abcdef
}
.info {
color: white;
font-size: 18px
}
.letter {
height: 50px;
width: 50px;
text-align: center
}
.center {
display: flex;
justify-content: center;
align-items: center;
position: absolute;
top: 0;
bottom: 100px;
left: 0;
right: 0
}
.footer {
position: fixed;
text-align: center;
bottom: 0px;
width: 100%;
font-size: 22px;
color: green;
font-family: "Courier New"
}
<div id="Letter" class="info"></div>
<div id="Lives" class="info"></div>
<div id="Score" class="info"></div>
<div id="Timer" class="info"></div>
<table class="center">
<tr>
<td></td>
<td id="W" class="letter"></td>
<td></td>
</tr>
<tr>
<td id="A" class="letter"></td>
<td id="S" class="letter"></td>
<td id="D" class="letter"></td>
</tr>
</table>
<span id="playAgain" class="footer">Press [Enter] to restart</span>
1 Comment
Are you sure you intended to start the game with setInterval(resetGame, 0)?
That would repeatedly reset the game, every 0 ms.
Perhaps you meant to start it after a 0 ms timeout, i.e. once the interpreter became next free:
setTimeout(resetGame, 0);
When I change it in your fiddle, it seems to work as expected.
isPaused, accessible in scope both bypause()and your event listener handler, then have your event listener handler check whether it's paused each time it's fired to decide whether to execute.letter(), two new event listeners are added. Every timegame()is called, an event listener for pause is created. You need to refactor these from thegame()method.