Keydown дает неожиданный результат. HTML5-игра

Итак, я нахожусь на самом начальном этапе создания своей первой платформенной игры на html5. Пока я реализовал только движение влево и вправо, и в игре нет «гравитации» или обнаружения столкновений.

Однако я уже столкнулся с проблемой.

Если вы идете влево или вправо в течение короткого периода времени, «персонаж» действует так, как задумано (я использую термин «персонаж» вольно, поскольку на самом деле движется карта). Однако, если вы удерживаете клавишу нажатой, карта перемещается слишком быстро.

Я полагаю, проблема в том, что прослушиватель событий keydown все время прослушивает, там для перемещения карта перемещается перед каждым тиком или кадром игры.

Итак, мой вопрос: как я могу заставить нажатие клавиши увеличивать смещение карты только на каждом тике игры (20 миллисекунд).

Вот мой JSFiddle: НАЖМИТЕ ЗДЕСЬ

document.addEventListener('keydown',function(event){
    var dir = event.which;

    if(dir == directions.LEFT){
        mapOffsetX += mapOffsetDistanceX;
        event.preventDefault();
    };

    if(dir == directions.RIGHT){
        mapOffsetX -= mapOffsetDistanceX;
        event.preventDefault();
    };
});

document.addEventListener('keyup',function(event){
    var dir = event.which;

    if(dir == directions.LEFT){
        mapOffsetX -= mapOffsetDistanceX;
    };

    if(dir == directions.RIGHT){
        mapOffsetX += mapOffsetDistanceX;
    };
});

initFloorObject(100,c.height/2,300,20,0,0,0,1);

var myInt = setInterval(function(){

clearScreen();

for(var i=0;i<floorObject.length;i++){
    floorObject[i][0] = parseInt(floorObject[i][0])+mapOffsetX;
};

drawChar();
drawFloorObjects();

},20);

person Dominic Sore    schedule 03.12.2013    source источник


Ответы (2)


Устанавливайте переменную в false каждый раз, когда вы keydown, и возвращайте ее в true каждые 20 миллисекунд.

var isKeydownAvailable = true;
document.addEventListener('keydown', function (event) {
    var dir = event.which;
    if(isKeydownAvailable){
        if (dir == directions.LEFT) {
            mapOffsetX += mapOffsetDistanceX;
            event.preventDefault();
        };

        if (dir == directions.RIGHT) {
            mapOffsetX -= mapOffsetDistanceX;
            event.preventDefault();
        };
        isKeydownAvailable = false;
    };
});

В промежутке сбросьте isKeydownAvailable на true.

var myInt = setInterval(function () {

    clearScreen();

    for (var i = 0; i < floorObject.length; i++) {
        floorObject[i][0] = parseInt(floorObject[i][0]) + mapOffsetX;
    };

    drawChar();
    drawFloorObjects();
    isKeydownAvailable = true;

}, 20);
person sPaz    schedule 03.12.2013
comment
Разве я не использовал intervalTime в качестве второго аргумента при установке myInt в прослушивателе событий? - person Dominic Sore; 03.12.2013
comment
Ааа да вы бы. Я считаю, что неправильно прочитал вопрос. Как я могу заставить нажатие клавиши увеличивать смещение карты только на каждом тике игры (20 миллисекунд), вы имеете в виду вызывать прослушиватель событий каждые 20 миллисекунд, когда игрок удерживает клавишу? - person sPaz; 03.12.2013
comment
Да, именно то, что я имею в виду. Будет ли применимо ваше решение? - person Dominic Sore; 04.12.2013
comment
Я отредактировал ответ. Это должно быть применимо. Вот JSFiddle: jsfiddle.net/aU7ta/5. Я изменил интервал на 1 секунду, чтобы было лучше видно изменение. - person sPaz; 04.12.2013

Используйте логические значения для действий и проверяйте их внутри интервала.
При нажатии клавиши вы устанавливаете логическое значение isMovingLeft в значение true, а затем добавляете смещение в функцию интервала только if(isMovingLeft). Сделайте это для других действий, и все готово.

person SparK    schedule 03.12.2013