Estou tentando desenvolver um mecanismo de jogo JavaScript e me deparei com este problema:
- Quando eu pressiono SPACE o personagem pula.
- Quando pressiono, →o personagem se move para a direita.
O problema é que, quando estou pressionando a direita e pressionando espaço, o personagem pula e para de se mover.
Eu uso a keydown
função para pressionar a tecla. Como posso verificar se há várias teclas pressionadas ao mesmo tempo?
javascript
keydown
XCS
fonte
fonte
Respostas:
Nota: keyCode agora está obsoleto.
A detecção de várias teclas é fácil se você entender o conceito
O jeito que eu faço é assim:
Esse código é muito simples: como o computador passa apenas um pressionamento de tecla de cada vez, é criada uma matriz para controlar várias chaves. A matriz pode ser usada para verificar uma ou mais chaves ao mesmo tempo.
Apenas para explicar, digamos que você pressione Ae B, cada um dispara um
keydown
evento que definemap[e.keyCode]
o valor dee.type == keydown
, que é avaliado como verdadeiro ou falso . Agora ambosmap[65]
emap[66]
estão definidos comotrue
. Quando você soltaA
, okeyup
evento é acionado, causando a mesma lógica para determinar o resultado oposto paramap[65]
(A), que agora é falso , mas comomap[66]
(B) ainda está "inativo" (não disparou um evento de keyup), permanece verdadeiro .A
map
matriz, através dos dois eventos, fica assim:Há duas coisas que você pode fazer agora:
A) Um registrador de chaves ( exemplo ) pode ser criado como referência para mais tarde, quando você quiser descobrir rapidamente um ou mais códigos de chave. Supondo que você tenha definido um elemento html e apontou para ele com a variável
element
.Nota: Você pode facilmente pegar um elemento por seu
id
atributo.Isso cria um elemento html que pode ser facilmente referenciado em javascript com
element
Você nem precisa usar
document.getElementById()
ou$()
agarrar. Mas, por uma questão de compatibilidade, o uso de jQuery$()
é mais amplamente recomendado.Apenas verifique se a tag do script vem após o corpo do HTML. Dica de otimização : a maioria dos sites de grandes nomes coloca a tag de script após a tag body para otimização. Isso ocorre porque a tag de script impede que outros elementos sejam carregados até o término do download do script. Colocá-lo à frente do conteúdo permite que o conteúdo seja carregado com antecedência.
B (onde é o seu interesse) Você pode procurar uma ou mais chaves por vez, onde
/*insert conditional here*/
está, veja este exemplo:Editar : esse não é o trecho mais legível. A legibilidade é importante, então você pode tentar algo assim para facilitar a visão:
Uso:
Isso é melhor?
(fim da edição)
Este exemplo verifica para CtrlShiftA, CtrlShiftBeCtrlShiftC
É tão simples assim :)
Notas
Acompanhamento dos códigos-chave
Como regra geral, é uma boa prática documentar código, especialmente coisas como códigos-chave (como
// CTRL+ENTER
), para que você possa se lembrar do que eram.Você também deve colocar os códigos de chave na mesma ordem que a documentação (
CTRL+ENTER => map[17] && map[13]
, NÃOmap[13] && map[17]
). Dessa forma, você nunca ficará confuso quando precisar voltar e editar o código.Uma pegadinha com cadeias if-else
Se verificar combos de quantidades diferentes (como CtrlShiftAltEntere CtrlEnter), coloque combos menores depois de combos maiores, caso contrário os combos menores substituirão os combos maiores se forem semelhantes o suficiente. Exemplo:
Gotcha: "Essa combinação de teclas continua sendo ativada mesmo que eu não esteja pressionando as teclas"
Ao lidar com alertas ou qualquer coisa que tenha foco na janela principal, convém incluir
map = []
a redefinição da matriz após a conclusão da condição. Isso ocorre porque algumas coisasalert()
afastam o foco da janela principal e fazem com que o evento 'keyup' não seja acionado. Por exemplo:Gotcha: Padrões do navegador
Aqui está uma coisa chata que eu achei, com a solução incluída:
Problema: como o navegador geralmente possui ações padrão em combinações de teclas (como CtrlDativa a janela de favoritos ou CtrlShiftCskynote no maxthon), convém adicionar
return false
depoismap = []
, para que os usuários do seu site não fiquem frustrados quando o "Arquivo duplicado" função, sendo colocadoCtrlD , marca a página.Sem
return false
, a janela do marcador seria exibida, para desgosto do usuário.A declaração de retorno (nova)
Ok, então você nem sempre deseja sair da função nesse ponto. É por isso que a
event.preventDefault()
função está lá. O que ele faz é definir um sinalizador interno que instrua o intérprete a não permitir que o navegador execute sua ação padrão. Depois disso, a execução da função continua (enquantoreturn
sairá imediatamente da função).Entenda essa distinção antes de decidir se deve usar
return false
ou nãoe.preventDefault()
event.keyCode
está obsoletoO usuário SeanVieira apontou nos comentários que foram
event.keyCode
preteridos.Lá, ele ofereceu uma excelente alternativa
event.key
:, que retorna uma representação em cadeia da tecla que está sendo pressionada, como"a"
para Aou"Shift"
paraShift .Fui em frente e cozinhei uma ferramenta para examinar as ditas cordas.
element.onevent
vselement.addEventListener
Os manipuladores registrados com
addEventListener
podem ser empilhados e são chamados na ordem do registro, enquanto a configuração.onevent
diretamente é bastante agressiva e substitui tudo o que você tinha anteriormente.A
.onevent
propriedade parece substituir tudo e o comportamento deev.preventDefault()
ereturn false;
pode ser bastante imprevisível.Nos dois casos, os manipuladores registrados via
addEventlistener
parecem ser mais fáceis de escrever e raciocinar.Também existe
attachEvent("onevent", callback)
na implementação fora do padrão do Internet Explorer, mas isso está além de obsoleto e nem pertence ao JavaScript (refere-se a uma linguagem esotérica chamada JScript ). Seria do seu interesse evitar o máximo possível o código poliglota.Uma classe auxiliar
Para resolver confusão / reclamações, escrevi uma "classe" que faz essa abstração ( link pastebin ):
Essa classe não faz tudo e não lida com todos os casos de uso concebíveis. Eu não sou um cara da biblioteca. Mas, para uso interativo geral, tudo bem.
Para usar essa classe, crie uma instância e aponte para o elemento ao qual você deseja associar a entrada do teclado:
O que isso fará é anexar um novo ouvinte de entrada ao elemento
#txt
(vamos supor que seja uma área de texto) e definir um ponto de controle para a combinação de teclasCtrl+5
. Quando ambosCtrl
e5
estão inativos, a função de retorno de chamada que você passou (nesse caso, uma função que adiciona"FIVE "
à área de texto) será chamada. O retorno de chamada está associado ao nomeprint_5
; portanto, para removê-lo, basta usar:Para desanexar
input_txt
dotxt
elemento:Dessa forma, a coleta de lixo pode pegar o objeto (
input_txt
), caso ele seja jogado fora, e você não terá um ouvinte de evento zumbi antigo sobrando.Para mais detalhes, aqui está uma referência rápida à API da classe, apresentada no estilo C / Java para que você saiba o que eles retornam e quais argumentos eles esperam.
Atualização 2017-12-02 Em resposta a uma solicitação para publicá-la no github, criei uma essência .
Atualização 2018-07-21 Eu jogo com programação de estilo declarativo há um tempo e agora é o meu favorito: fiddle , pastebin
Geralmente, ele funciona com os casos que você deseja realisticamente (ctrl, alt, shift), mas se precisar pressionar, digamos,
a+w
ao mesmo tempo, não seria muito difícil "combinar" as abordagens em um pesquisa com várias teclas.Espero que esta
resposta minimamente explicadaseja útil :)fonte
return false
vspreventDefault()
keyCode
está obsoleto - se você alternar parakey
, obtém a representação real de caracteres da chave, o que pode ser bom.myString[5]
é o mesmo que5[myString]
e nem sequer fornece um aviso de compilação (mesmo com-Wall -pedantic
)? É porque apointer[offset]
notação pega o ponteiro, adiciona o deslocamento e desreferencia o resultado, fazendomyString[5]
o mesmo que*(myString + 5)
.Você deve usar o evento keydown para acompanhar as teclas pressionadas, e deve usar o evento keyup para acompanhar quando as teclas são liberadas.
Veja este exemplo: http://jsfiddle.net/vor0nwe/mkHsU/
(Atualização: estou reproduzindo o código aqui, caso o jsfiddle.net seja bloqueado :) O HTML:
... e o Javascript (usando jQuery):
Nesse exemplo, estou usando uma matriz para acompanhar quais teclas estão sendo pressionadas. Em um aplicativo real, você pode querer
delete
cada elemento depois que a chave associada for liberada.Observe que, embora eu tenha usado o jQuery para facilitar as coisas para mim neste exemplo, o conceito funciona tão bem quando se trabalha com Javascript 'bruto'.
fonte
onblur
manipulador de eventos, que remove todas as teclas pressionadas da matriz. Depois de perder o foco, faria sentido pressionar todas as teclas novamente. Infelizmente, não há JS equivalente aGetKeyboardState
.fonte
Eu usei desta maneira (tive que verificar onde Shift + Ctrl é pressionado):
fonte
para quem precisa de código de exemplo completo. Direita + esquerda adicionada
fonte
Faça com que o keydown chame várias funções, com cada função verificando uma chave específica e respondendo adequadamente.
fonte
Eu tentaria adicionar um
keypress
Event
manipuladorkeydown
. Por exemplo:Isso serve apenas para ilustrar um padrão; Não entrarei em detalhes aqui (especialmente não no nível2 + específico do navegador
Event
).Envie de volta, por favor, se isso ajuda ou não.
fonte
Se uma das teclas pressionadas for Alt / Crtl / Shift, você poderá usar este método:
fonte
fonte
Este não é um método universal, mas é útil em alguns casos. É útil para combinações como CTRL+ somethingou Shift+ somethingou CTRL+ Shift+ something, etc.
Exemplo: quando você deseja imprimir uma página usando CTRL+ P, a primeira tecla pressionada é sempre CTRLseguida por P. Mesmo com CTRL+ S, CTRL+ Ue outras combinações.
fonte
Não é o melhor caminho, eu sei.
fonte
fonte