Вторая проблема, связанная с настройками повтора символов в системе — это задержка перед началом повтора. То есть, когда я нажимаю кнопку, сначала генерируется только одно событие keydown, потом следует пауза (заданная в настройках системы), и только после паузы события начинают генерироваться быстро.
Так же это будет нечестно по отношению к некоторым пользователям. Если у пользователя низкая скорость повтора символов или большая задержка перед повтором, он может просто не успеть быстро переместить фигуру, напирмер, к краю поля. Будет обидно, наверное.
Переделаем наш код следующим образом. При нажатии на кнопку «Вниз», мы будем увеличивать скорость падения фигур, а не вызывать самостоятельно метод tick. А когда пользователь отпустит кнопку — будем возвращать значение скорости на прежний уровень.
var Tetris = {
config: {
// ...
speed: 500
}
},
init: function() {
// ...
window.onkeydown = function (event) {
var direction = '';
if (event.keyCode == 39) {
direction = 'right';
} else if(event.keyCode == 37) {
direction = 'left';
}
if (direction) {
Tetris.figure.sideStep(direction);
} else if(event.keyCode == 40) {
// Увеличиваем скорость до 30
Tetris.setSpeed(30);
}
}
// А когда пользователь отпустил клавишу
window.onkeyup = function (event) {
// Возвращаем значение скорости по умолчанию
if(event.keyCode == 40) {
Tetris.setSpeed();
}
}
},
tick: function() {
console.log('tick');
Tetris.figure.go();
Tetris.draw();
if (Tetris.tickHandler === undefined) {
// Чтобы суметь изменять скорость, придется вынести функционал
// в отдельный метод
Tetris.setSpeed();
}
},
currentSpeed: 0, // Чтобы всегда знать, какая скорость сейчас
setSpeed: function(speed) {
// Если скорость не указана, ставим значение из конфига
if (!speed) var speed = Tetris.config.speed;
// Если текущая скорость не равна требуемой
if (speed != this.currentSpeed) {
// Проверяем - не начало ли это игры
if (Tetris.tickHandler !== undefined) {
// Если нет, надо сначала очистить текущий setInterval
clearInterval(Tetris.tickHandler);
}
// Ну и назначаем интервал
Tetris.tickHandler = setInterval(function(){
Tetris.tick();
}, speed);
// Записываем текущую скорость
this.currentSpeed = speed;
}
}
};
Tetris.init();
Провернём то же самое и с кнопками «Влево»/«Вправо»//...
figure: {
// ...
rollback: false,
sideStepSpeed: 0, // Текущая скорость перемещения вбок
sideStepStart: function(direction) {
// Если мы и так уже перемещаемся, не будем ничего делать
if (!this.sideStepSpeed) {
// Устанавливаем скорость движения влево или вправо
this.sideStepSpeed = 50;
// Указываем интервал для совершения шага
this.sideStepHandler = setInterval(function(){
Tetris.figure.sideStep(direction);
}, this.sideStepSpeed);
}
},
// Когда пользователь отпустит клавишу, движение вбок надо остановить
sideStepStop: function() {
if (this.sideStepHandler != undefined || !this.sideStepHandler) {
this.sideStepSpeed = 0;
clearInterval(this.sideStepHandler);
}
},
// ...
},
init: function() {
// ...
window.onkeydown = function (event) {
var direction = '';
if (event.keyCode == 39) {
direction = 'right';
} else if(event.keyCode == 37) {
direction = 'left';
}
if (direction) {
// Запускаем движение в нужную сторону
Tetris.figure.sideStepStart(direction);
} else if(event.keyCode == 40) {
Tetris.setSpeed(30);
}
}
window.onkeyup = function (event) {
var direction = '';
if (event.keyCode == 39) {
direction = 'right';
} else if(event.keyCode == 37) {
direction = 'left';
}
if (direction) {
// Останавливаем движение
Tetris.figure.sideStepStop();
} else if(event.keyCode == 40) {
Tetris.setSpeed();
}
}
},
// ...Ну вот, теперь наш код, хоть и тормозит, но зато не глючит: http://jsfiddle.net/ilyautkin/aavju3jd/19/ — браузер отрисовывает каждый шаг, и уже нет никаких «телепортаций» фигур.
Объектная
2. Влево и право понятно, но как вертеть фигуры?
3. Когда произошло «game over», где кнопка «повторить заново» или «start»?
4. joxi.ru/D2PBg1pCRjQvr3
5. «game over» после некоторого времени снова выскакивает.