javascript - SetInterval 在某些操作后效果不佳

标签 javascript setinterval clearinterval

当我按下开始按钮时它运行

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

在我的游戏中,它每秒从上到下移动方 block 。我还有一个可以发射和摧毁方 block 的激光。当您按空格键时,它会使用另一个

laserId = setInterval(moveLaser, 100)

在你按下空格键之前,方 block 每秒移动得很好,但在使用 lazer 方 block 之后,移动速度比 1 秒快。 如果我在 StartGame 函数之外设置 invaderId = setInterval(moveInvaders, 1000) 一切都很好。但是我只需要在按下开始按钮后才开始游戏。

也许在实际操作中更容易看到这一点。所以,我在这里留下完整的代码,有人可以解释为什么会这样

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>

最佳答案

尝试在 startGame 函数中添加 event.target.blur()

为什么?这是因为当您点击开始按钮时。它实际上是被聚焦的,当你点击空格时,它的浏览器默认属性是点击聚焦的元素。因此,您必须从按钮上移除焦点。

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>

关于javascript - SetInterval 在某些操作后效果不佳,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66603405/

相关文章:

javascript - 如何获取多维数组中最长的单词?

java - 有没有办法在 javascript 中验证表单以停止 onSubmit() java 方法触发?

javascript - 如何使用 css3 rotate 和 setinterval 旋转图像?

javascript - 单击时显示下一个 div

javascript - 声音和图像

javascript - SetInterval mySQL 每秒查询一次

javascript - 随机报价生成器 - 如何在每次页面加载或页面刷新后设置 setInterval?

javascript - 在 setInterval 中为匿名函数提供多个参数

javascript - 使用 slider 上的按钮停止 setInterval

javascript - React 类中的清除间隔