SetInterval вызывается более одного раза - PullRequest
0 голосов
/ 04 апреля 2019

Я играю в тетрис.

Вот ссылка на jsfiddle. https://jsfiddle.net/e9q1mykt/1/

Проблема / ошибка в том, что при игре в игру setInterval(move_tetris_part,interval_time); вызывается более одного раза, поэтому скорость понижения выше, чем обычно.

Я не могу найти почему.

Проблема в функции keydown и keyup. У меня есть переменная с именем job_completed, которая имеет значение true в начале каждой нажатой кнопки, а затем будет иметь значение false. Только если эта переменная ложна, код выполняется.

document.onkeydown = function(event){
        can_move_left = true;
        can_move_right = true;
        can_rotate = true;

    switch(event.keyCode){
        case 37:
            //left;
            if(game_mode=="started" && job_completed){
            job_completed = false;
            //code there
            job_completed = true;
            }
    }
        case 39:
            //left;
            if(game_mode=="started" && job_completed){
            job_completed = false;
            //code there
            job_completed = true;
            }
case 40:
            //left;
            if(game_mode=="started" && job_completed){
            job_completed = false;
            //code there
            job_completed = true;
            }

       case 38:
            //left;
            if(game_mode=="started" && job_completed){
            job_completed = false;
            //code there
            job_completed = true;
            }

}

document.onkeyup = function(event){
    if(game_mode=="started"){
        switch(event.keyCode){
            case 37:
                //left
                if(job_completed){
                    game_mode = "started";
                    game_interval = setInterval(move_tetris_part,interval_time);
                    console.log("Set interval after pressing left arrow");
                }
                break;
            case 38:
                //up
                if(job_completed){
                    game_mode = "started";
                    part_can_move();
                    if(part_can_go_down){       
                        game_interval = setInterval(move_tetris_part,interval_time);
                        console.log("Set interval after pressing up arrow");
                    }else{
                        new_part();
                    }
                }
                break;
            case 39:
                //right
                if(job_completed){
                    game_mode = "started";
                    game_interval = setInterval(move_tetris_part,interval_time);
                    console.log("Set interval after pressing right arrow");
                }
                //right
                break;
            case 40:
                //down
                if(job_completed){
                    if(game_mode == "started"){
                        if(interval_time==interval_time_speed){
                            clearInterval(game_interval);
                            console.log("Clear interval while pressing down arrow");
                            interval_time = interval_time_normal;
                            document.getElementById("interval_time").innerHTML = interval_time+" ms";
                            game_interval = setInterval(move_tetris_part,interval_time);
                            console.log("Set interval after pressing down arrow");
                        }
                    }
                }
                break;
            case 32:
                //space
                if(game_mode=="started" && job_completed){
                    job_completed = false;
                    console.log(job_completed);
                    clearInterval(game_interval);
                    console.log("Clear interval while pressing space arrow");
                    static_current_y = current_y;
                    for(var i=static_current_y;i<squares_y;i++){
                        current_y = i;
                        part_can_move();
                        if(part_can_go_down==false){
                            current_y = static_current_y;
                            delete_tetris_part();
                            current_y = i;
                            make_tetris_part(false);
                            clear_completed_lines();
                            score = score+((squares_y-static_current_y)*10);
                            document.getElementById("score").innerHTML = score;
                            new_part();
                            job_completed = true;
                            console.log(job_completed);
                            return 1;
                        }
                    }
                    job_completed = true;
                    console.log(job_completed);
                }
                break;
        }
    }
};

Пожалуйста, проверьте журналы (консоль).

Заранее спасибо, Крис Паппас.

1 Ответ

0 голосов
/ 04 апреля 2019

Каждому game_interval = setInterval(//... должен предшествовать clearInterval, я думаю, что в обработчике document.onkeyup вокруг строки 1680 вы пренебрегали этим.

И вот почему: интервал будет продолжать отсчитываться до тех пор, пока он не будет очищен (или пользователь закроет окно, или мир закончится - так или иначе, принудительная остановка). Когда вы набираете один setInterval, не снимая галочку с уже отмеченного, старый продолжает работать, а новый запускается. Таким образом, один раз каждые x миллисекунд будет срабатывать первая, и независимо один раз каждые x миллисекунд будет работать и вторая. Что делает два тика каждые х миллисекунд. Добавьте еще, и это 3 галочки, и так далее, и так далее.

Кстати, этот скрипт огромен, и поэтому его трудно прочитать. Концентрируясь на том, чтобы держать его более сухим, вы сможете найти ошибки.

...