Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 01.08.2019, 23:09
Новичок на форуме
Отправить личное сообщение для Temcher Посмотреть профиль Найти все сообщения от Temcher
 
Регистрация: 13.02.2018
Сообщений: 9

Обработка нажатия двух клавиш одновременно.
Всем привет! Помогите разобраться, как изменить код, чтобы обрабатывались две нажатые клавиши одновременно. Чтобы две кнопки были независимы друг от друга.
Я так понимаю тут причина в keyCode, которая принимает только какое то одно значение. т.е при получении второго значения(скажем D) значение W удаляется. Нужен массив? пробовал по разному, не понимаю.
var mas = {
	'W':87,
	'D':68
};

window.onkeydown=function(e){
	if(e.keyCode == mas.W){
		console.log('Кнопка W нажата');
	}
	if(e.keyCode == mas.D){
		console.log('Кнопка D нажата');
	}
	window.onkeyup=function(e){
		if(e.keyCode == mas.W){
			console.log('Отжата кнопка W');
		}
		else if(e.keyCode == mas.D){
			console.log('Отжата кнопка D');
		}
	}
}


В консоле при нажатии к примеру клавиши W вижу, как она обрабатывается, но как только нажимаю D обработка W прерывается.

В дальнейшем хочу чтобы объект в canvas мог двигаться не только по вертикали и горизонтали, но и по диагонали.
Ответить с цитированием
  #2 (permalink)  
Старый 02.08.2019, 00:44
Аватар для j0hnik
Профессор
Отправить личное сообщение для j0hnik Посмотреть профиль Найти все сообщения от j0hnik
 
Регистрация: 01.12.2016
Сообщений: 3,650

у вас же есть событие keyup, очевидно ведь, что если клавиша была нажата, пока не сработало событие keyup она нажата.
Ответить с цитированием
  #3 (permalink)  
Старый 02.08.2019, 01:57
Аватар для Malleys
Профессор
Отправить личное сообщение для Malleys Посмотреть профиль Найти все сообщения от Malleys
 
Регистрация: 20.12.2009
Сообщений: 1,714

Зачем на каждом нажатии клавиши переопределяется обработчик отжимания клавиши?

Сообщение от Temcher
e.keyCode
Это не рекомендуемое к использованию свойство, используйте вместо него KeyboardEvent.prototype.key или KeyboardEvent.prototype.code

Исправленный вариант, в объекте pressedKeys хранятся нажатые клавишы...
var pressedKeys = {};

onkeydown = function(e) {
	if(pressedKeys[e.code]) return;
	pressedKeys[e.code] = true;

	if(e.code === "KeyW") {
		console.log('Кнопка W нажата');
	} else if(e.code === "KeyD") {
		console.log('Кнопка D нажата');
	}
}

onkeyup = function(e) {
	delete pressedKeys[e.code];

	if(e.code === "KeyW") {
		console.log('Отжата кнопка W');
	} else if(e.code === "KeyD") {
		console.log('Отжата кнопка D');
	}
}


Можно упростить до...
var pressedKeys = {};

onkeydown = function(e) {
	if(e.code in pressedKeys) return;
	pressedKeys[e.code] = true;
}

onkeyup = function(e) {
	delete pressedKeys[e.code];
}
В pressedKeys находятся зажатые клавиши.

Вот улучшенный вариант... Класс PressedKeysRegistry позволяет включать/выключать отслеживание нажатых клавиш, также используется метод addEventListener, чтобы вы могли добавить и другие обработчики событии keydown и keyup.
<canvas id="app" width="300" height="300" style="border: solid;"></canvas>
<script>

function PressedKeysRegistry() {
	this.handler = this.handler.bind(this);
}

PressedKeysRegistry.prototype = {
	constructor: PressedKeysRegistry,
	start: function() {
		addEventListener("keydown", this.handler);
		addEventListener("keyup", this.handler);
	},
	stop: function() {
		removeEventListener("keydown", this.handler);
		removeEventListener("keyup", this.handler);
	},
	handler: function(event) {
		if(event.type === "keydown") {
			if(this[event.code]) return;
			this[event.code] = true;
		} else if(event.type === "keyup") {
			delete this[event.code];
		}
	}
};

// пример
var pressedKeys = new PressedKeysRegistry();
pressedKeys.start();
var player = { x: 50, y: 50 };
var field = { width: 100, height: 100 };
var ctx = app.getContext("2d");

(function loop() {
	ctx.clearRect(0, 0, app.width, app.height);
	ctx.fillRect(player.x / field.width * app.width, player.y / field.height * app.height, 20, 20);
	
	if("KeyD" in pressedKeys) player.x++;
	if("KeyA" in pressedKeys) player.x--;
	if("KeyS" in pressedKeys) player.y++;
	if("KeyW" in pressedKeys) player.y--;

	setTimeout(loop, 50);
})();

</script>

Последний раз редактировалось Malleys, 02.08.2019 в 13:32.
Ответить с цитированием
  #4 (permalink)  
Старый 02.08.2019, 06:03
Аватар для j0hnik
Профессор
Отправить личное сообщение для j0hnik Посмотреть профиль Найти все сообщения от j0hnik
 
Регистрация: 01.12.2016
Сообщений: 3,650

Ставим влаги нажатым клавишам,вся соль в верхушке, остальное мишура (пример для простоты понимания, !не боевой код)
<div id="obj" style="width: 20px; height:20px; background-color:red; position:absolute; "></div>
  <script>

    var key = {
      87: 0,
      68: 0,
      83: 0,
      65: 0,
    };

    window.onkeydown = e => key[e.keyCode] = 1;
    window.onkeyup = e => key[e.keyCode] = 0;

    //остальное мишура
    var rct = obj.getBoundingClientRect();
    pos = [['top',rct.top],['left',rct.left]];
    
    (run =_=> {
      [[87,83],[65,68]].forEach((tl, x)=> tl.forEach((el, i)=> {
        if(key[el]) {
          pos[x][1] += i ? 1 : -1;
          obj.style[pos[x][0]] = pos[x][1]+'px';
        }
      }));
      setTimeout(run, 50);
    })();

  </script>
Ответить с цитированием
  #5 (permalink)  
Старый 02.08.2019, 07:50
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 31,789

Сообщение от Malleys
var field = { width: 100, height: 100 };
для чего это?
Ответить с цитированием
  #6 (permalink)  
Старый 02.08.2019, 13:52
Аватар для Malleys
Профессор
Отправить личное сообщение для Malleys Посмотреть профиль Найти все сообщения от Malleys
 
Регистрация: 20.12.2009
Сообщений: 1,714

Сообщение от j0hnik
Ставим влаги нажатым клавишам,вся соль в верхушке, остальное мишура (пример для простоты понимания, !не боевой код)
А в примере выше не тоже самое? И как 87, 68, 83, 65 может быть лёгким для понимания? У вас получается, что правый и левый shift одно и тоже! Live expression в консоли показывает {16: 1, 65: 0, 68: 0, 83: 0, 87: 0} Так какая именно клавиша нажата? Кстати у вас происходит раздувание объекта после других нажатии!

В моём примере вы можете узнать, нажат ли правый shift, или левый или оба, цифра 2 нажата на цифровой клавиатуре или нет. Если не поняли, то вот с пример с информацией о нажатых клавишах... Нажмите кнопку Посмотреть!, а затем нажмите на пустое появившееся поле, чтобы оно могло ловить нажатия клавиш!
<p id="info"></p>
<script>
var pressedKeys = {};

onkeydown = function(e) {
	if(e.code in pressedKeys) return;
	pressedKeys[e.code] = true;
};

onkeyup = function(e) {
	delete pressedKeys[e.code];
};

(function loop() {
	info.textContent = Object.keys(pressedKeys).join(", ");
	setTimeout(loop, 50);
})();
</script>


Сообщение от рони
для чего это?
Размер игрового поля.

Последний раз редактировалось Malleys, 02.08.2019 в 14:00.
Ответить с цитированием
  #7 (permalink)  
Старый 02.08.2019, 16:56
Аватар для j0hnik
Профессор
Отправить личное сообщение для j0hnik Посмотреть профиль Найти все сообщения от j0hnik
 
Регистрация: 01.12.2016
Сообщений: 3,650

Malleys,
Я в курсе всего очевидного что вы написали, про шифты тут вообще без разницы, они не участвуют.
Пример демонстрирует идею!, но раз у вас на душе не спокойно то добавьте.Object.preventExtensions(key);
Ответить с цитированием
  #8 (permalink)  
Старый 02.08.2019, 17:17
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 31,789

Сообщение от Malleys
Размер игрового поля.
ок.
Ответить с цитированием
  #9 (permalink)  
Старый 02.08.2019, 18:35
Аватар для Malleys
Профессор
Отправить личное сообщение для Malleys Посмотреть профиль Найти все сообщения от Malleys
 
Регистрация: 20.12.2009
Сообщений: 1,714

Сообщение от j0hnik
про шифты тут вообще без разницы, они не участвуют.
Если человек не указал все клавиши, которые используются/будут использоваться в игре, то это не значит, что это не важно. В играх такое различие как раз важно!

Сообщение от j0hnik
Object.preventExtensions(key);
Оно и без этого работает... Я про то, что для игр лучше использовать KeyboardEvent.prototype.key или KeyboardEvent.prototype.code, а не KeyboardEvent.prototype.keyCode
Ответить с цитированием
  #10 (permalink)  
Старый 02.08.2019, 18:48
Аватар для j0hnik
Профессор
Отправить личное сообщение для j0hnik Посмотреть профиль Найти все сообщения от j0hnik
 
Регистрация: 01.12.2016
Сообщений: 3,650

Сообщение от Malleys
Оно и без этого работает...
Это что не было эффекта
Сообщение от Malleys
происходит раздувание объекта после других нажатии!
ок, не знаю ни одной игры где шифты по разному работают, но учту ваше замечание
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
проблема перехвата нажатия клавиш управления в Файрфокс alexlead Firefox/Mozilla 0 16.10.2016 19:18
Оброботка одновременного нажатия 2-х клавиш NullNull Events/DOM/Window 3 05.11.2015 00:16
Обработка нажатия двух клавиш 12345678 Events/DOM/Window 1 15.01.2013 13:41
Обработка нажатия на элемент и его родитель klev2004 Общие вопросы Javascript 3 12.12.2012 18:07
обработка одновременно двух клавиш клавиатуры Destrifer Events/DOM/Window 8 20.12.2008 14:25