Skip to content

SetInterval does not work well after some actions

When I press Start button it runs

function startGame() {
        invaderId = setInterval(moveInvaders, 1000);
    }

In my game it moves blocks from top to bottom each second. Also I have a laser which shoots and destroy blocks. When you press space key it use another

laserId = setInterval(moveLaser, 100)

Before you press space key blocks move well each second, but after using lazer blocks move faster then 1 sec. If I set invaderId = setInterval(moveInvaders, 1000) outside StartGame function everythink is good. But I need to start game only after press button Start.

Maybe it easier to see this in action. So, I leave full code here and someone can explain why it happens

const resultDisplay = document.querySelector('#result');
let width = 15;
let BOARD_SIZE = width * width 
let currentShooterIndex = 202;
let currentInvaderIndex = 0;
let alienInvadersTakenDown = [];
let result = 0;
let direction = 1;
let invaderId

const $board = document.querySelector('.grid')
for(let i = 0; i < BOARD_SIZE; i++) {
    $board.appendChild(document.createElement('div'))
}
const squares = document.querySelectorAll('.grid div');
//define alien invaders
const alienInvaders = [0,1,2,3,4,5,6];

//=======draw the aliens invaders========
alienInvaders.forEach(invader => squares[currentInvaderIndex + invader].classList.add('invader'));

//=======draw the shooter================
squares[currentShooterIndex].classList.add('shooter');

//==========move shooter along the line=========
function moveShooter (e) {
    squares[currentShooterIndex].classList.remove('shooter');
    switch (e.keyCode) {
        case 37:
            if(currentShooterIndex % width !== 0) {
                currentShooterIndex -=1;
                break;
            }
        case 39:
            if(currentShooterIndex % width < width -1) {
                currentShooterIndex +=1;
                break;
            }
    }
    squares[currentShooterIndex].classList.add('shooter');
}

//=============move the alien invaders===============
function moveInvaders() {
    const leftEdge = alienInvaders[0] % width === 0;
    const rightEdge = alienInvaders[alienInvaders.length - 1] % width === width - 1;

    //=====decide next direction for aliens invaders=======
    if ((leftEdge && direction === -1) || (rightEdge && direction === 1)) {
        direction = width;
    } else if (direction === width) {
        if (leftEdge) direction = 1;
        else  direction = -1;
    }

    //=====remove invaders from previous position===========
    for (let i = 0; i <= alienInvaders.length - 1; i++) {
        squares[alienInvaders[i]].classList.remove('invader');
    }

    //===========change invaders position due to direction======
    for (let i = 0; i <= alienInvaders.length - 1; i++) {
        alienInvaders[i] += direction;
    }

    //============show current invaders===========
    for (let i = 0; i <= alienInvaders.length - 1; i++) {
        if (!alienInvadersTakenDown.includes(i)) {
            squares[alienInvaders[i]].classList.add('invader');
        }
    }

    //==========decide a game over=============
    if (squares[currentShooterIndex].classList.contains('invader', 'shooter')) {
        resultDisplay.textContent = "Game Over";
        squares[currentShooterIndex].classList.add('boom');
        clearInterval(invaderId);
        document.removeEventListener('keydown', moveShooter);
        document.removeEventListener('keyup', shoot);
    }
    for (let i = 0; i <= alienInvaders.length - 1; i++) {
        if (alienInvaders[i] > (squares.length - (width - 1))) {
            resultDisplay.textContent = "Game Over";
            clearInterval(invaderId);
        }
    }

    //==========decide a win===========
    if (alienInvadersTakenDown.length === alienInvaders.length) {
        resultDisplay.textContent = "You Win!";
        clearInterval(invaderId);
    }
}//moveInvaders



//=======shoot at aliens function========
function shoot(e) {
    let laserId;
    let currentLaserIndex = currentShooterIndex;
    //move the laser from shooter to the alien invader
    function moveLaser() {
        squares[currentLaserIndex].classList.remove('laser');
        currentLaserIndex -= width;
        squares[currentLaserIndex].classList.add('laser');
        if (squares[currentLaserIndex].classList.contains('invader')) {
            squares[currentLaserIndex].classList.remove('laser');
            squares[currentLaserIndex].classList.remove('invader');
            squares[currentLaserIndex].classList.add('boom');
            setTimeout(() => squares[currentLaserIndex].classList.remove('boom'), 250);
            clearInterval(laserId);
            //==============add to alien takedown array killed invader using currentlaser index
            const alienTakeDown = alienInvaders.indexOf(currentLaserIndex);
            alienInvadersTakenDown.push(alienTakeDown);
            result++;
            resultDisplay.textContent = result;
        }
        if (currentLaserIndex < width) {
            clearInterval(laserId);
            setTimeout(() => squares[currentLaserIndex].classList.remove('laser'), 100);
        }
    }
    //========define "space" - shoot button and run laser function=======
    switch (e.keyCode) {
        case 32:
            laserId = setInterval(moveLaser, 100);
            break;
    }
}


// invaderId = setInterval(moveInvaders, speedInterval);



// setTimeout(() => invaderId = setInterval(moveInvaders, speedInterval), 2000)



document.addEventListener('keydown', moveShooter);
document.addEventListener('keyup', shoot);

function startGame() {
    invaderId = setInterval(moveInvaders, 1000);
}
.grid {
    display: flex;
    flex-wrap: wrap;
    border: 3px solid #1b63d0;
    width: 300px;
    height: 300px;
}

.grid div {
    width: 20px;
    height: 20px;
}

.shooter {
    background-color: blue;
}

.invader {
    background-color: purple;
}

.boom {
    background-color: red;
}

.laser {
    background-color: orange;
}
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div class="container">
        <div class="wrap">
            <div class="grid"></div>
            <div class="control-block">
                <button class="start-btn" onclick="startGame()">Start</button>
                <div class="score">Score: <span id="result">0</span></div>

                <div class="control-btn">
                    <img src="left.png">
                </div>
                <div class="control-btn">
                    <img src="right.png">
                </div>
                <div class="control-btn">
                    <img src="space.png">
                </div>
                <!-- <div><img src="right.png"></div>
                <div><img src="space.png"></div> -->
            </div>
        </div>
    </div>

    <script src="script.js"></script>

</body>
</html>

Answer

Try adding event.target.blur() inside the startGame function.

Why?? its because when you hit on the start button. its actually being focused and when you hit on space, its browsers default property to click on the focused element. So you will have to remove the focus from the button.

const resultDisplay = document.querySelector('#result');
let width = 15;
let BOARD_SIZE = width * width 
let currentShooterIndex = 202;
let currentInvaderIndex = 0;
let alienInvadersTakenDown = [];
let result = 0;
let direction = 1;
let invaderId

const $board = document.querySelector('.grid')
for(let i = 0; i < BOARD_SIZE; i++) {
    $board.appendChild(document.createElement('div'))
}
const squares = document.querySelectorAll('.grid div');
//define alien invaders
const alienInvaders = [0,1,2,3,4,5,6];

//=======draw the aliens invaders========
alienInvaders.forEach(invader => squares[currentInvaderIndex + invader].classList.add('invader'));

//=======draw the shooter================
squares[currentShooterIndex].classList.add('shooter');

//==========move shooter along the line=========
function moveShooter (e) {
    squares[currentShooterIndex].classList.remove('shooter');
    switch (e.keyCode) {
        case 37:
            if(currentShooterIndex % width !== 0) {
                currentShooterIndex -=1;
                break;
            }
        case 39:
            if(currentShooterIndex % width < width -1) {
                currentShooterIndex +=1;
                break;
            }
    }
    squares[currentShooterIndex].classList.add('shooter');
}

//=============move the alien invaders===============
function moveInvaders() {
    const leftEdge = alienInvaders[0] % width === 0;
    const rightEdge = alienInvaders[alienInvaders.length - 1] % width === width - 1;

    //=====decide next direction for aliens invaders=======
    if ((leftEdge && direction === -1) || (rightEdge && direction === 1)) {
        direction = width;
    } else if (direction === width) {
        if (leftEdge) direction = 1;
        else  direction = -1;
    }

    //=====remove invaders from previous position===========
    for (let i = 0; i <= alienInvaders.length - 1; i++) {
        squares[alienInvaders[i]].classList.remove('invader');
    }

    //===========change invaders position due to direction======
    for (let i = 0; i <= alienInvaders.length - 1; i++) {
        alienInvaders[i] += direction;
    }

    //============show current invaders===========
    for (let i = 0; i <= alienInvaders.length - 1; i++) {
        if (!alienInvadersTakenDown.includes(i)) {
            squares[alienInvaders[i]].classList.add('invader');
        }
    }

    //==========decide a game over=============
    if (squares[currentShooterIndex].classList.contains('invader', 'shooter')) {
        resultDisplay.textContent = "Game Over";
        squares[currentShooterIndex].classList.add('boom');
        clearInterval(invaderId);
        document.removeEventListener('keydown', moveShooter);
        document.removeEventListener('keyup', shoot);
    }
    for (let i = 0; i <= alienInvaders.length - 1; i++) {
        if (alienInvaders[i] > (squares.length - (width - 1))) {
            resultDisplay.textContent = "Game Over";
            clearInterval(invaderId);
        }
    }

    //==========decide a win===========
    if (alienInvadersTakenDown.length === alienInvaders.length) {
        resultDisplay.textContent = "You Win!";
        clearInterval(invaderId);
    }
}//moveInvaders



//=======shoot at aliens function========
function shoot(e) {
    let laserId;
    let currentLaserIndex = currentShooterIndex;
    //move the laser from shooter to the alien invader
    function moveLaser() {
        squares[currentLaserIndex].classList.remove('laser');
        currentLaserIndex -= width;
        squares[currentLaserIndex].classList.add('laser');
        if (squares[currentLaserIndex].classList.contains('invader')) {
            squares[currentLaserIndex].classList.remove('laser');
            squares[currentLaserIndex].classList.remove('invader');
            squares[currentLaserIndex].classList.add('boom');
            setTimeout(() => squares[currentLaserIndex].classList.remove('boom'), 250);
            clearInterval(laserId);
            //==============add to alien takedown array killed invader using currentlaser index
            const alienTakeDown = alienInvaders.indexOf(currentLaserIndex);
            alienInvadersTakenDown.push(alienTakeDown);
            result++;
            resultDisplay.textContent = result;
        }
        if (currentLaserIndex < width) {
            clearInterval(laserId);
            setTimeout(() => squares[currentLaserIndex].classList.remove('laser'), 100);
        }
    }
    //========define "space" - shoot button and run laser function=======
    switch (e.keyCode) {
        case 32:
            laserId = setInterval(moveLaser, 100);
            break;
    }
}


// invaderId = setInterval(moveInvaders, speedInterval);



// setTimeout(() => invaderId = setInterval(moveInvaders, speedInterval), 2000)



document.addEventListener('keydown', moveShooter);
document.addEventListener('keyup', shoot);

function startGame() {
    event.target.blur();
    invaderId = setInterval(moveInvaders, 1000);
}
.grid {
    display: flex;
    flex-wrap: wrap;
    border: 3px solid #1b63d0;
    width: 300px;
    height: 300px;
}

.grid div {
    width: 20px;
    height: 20px;
}

.shooter {
    background-color: blue;
}

.invader {
    background-color: purple;
}

.boom {
    background-color: red;
}

.laser {
    background-color: orange;
}
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div class="container">
        <div class="wrap">
            <div class="grid"></div>
            <div class="control-block">
                <button class="start-btn" onclick="startGame()">Start</button>
                <div class="score">Score: <span id="result">0</span></div>

                <div class="control-btn">
                    <img src="left.png">
                </div>
                <div class="control-btn">
                    <img src="right.png">
                </div>
                <div class="control-btn">
                    <img src="space.png">
                </div>
                <!-- <div><img src="right.png"></div>
                <div><img src="space.png"></div> -->
            </div>
        </div>
    </div>

    <script src="script.js"></script>

</body>
</html>