Вторая проблема, связанная с настройками повтора символов в системе — это задержка перед началом повтора. То есть, когда я нажимаю кнопку, сначала генерируется только одно событие 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» после некоторого времени снова выскакивает.