Próbuję stworzyć silnik gry JavaScript i napotkałem ten problem:
- Kiedy naciskam, SPACEpostać skacze.
- Kiedy naciskam, →postać przesuwa się w prawo.
Problem polega na tym, że kiedy naciskam w prawo, a następnie naciskam spację, postać podskakuje, a następnie przestaje się poruszać.
Używam tej keydown
funkcji, aby nacisnąć klawisz. Jak mogę sprawdzić, czy naciśnięto kilka klawiszy jednocześnie?
javascript
keydown
XCS
źródło
źródło
Odpowiedzi:
Uwaga: kod keyCode jest teraz przestarzały.
Wykrywanie wielokrotnych naciśnięć klawiszy jest łatwe, jeśli zrozumiesz tę koncepcję
Sposób, w jaki to robię, wygląda następująco:
Ten kod jest bardzo prosty: ponieważ komputer wykonuje tylko jedno naciśnięcie klawisza na raz, tworzona jest tablica, aby śledzić wiele kluczy. Tablicy można następnie użyć do sprawdzenia jednego lub więcej kluczy naraz.
Aby to wyjaśnić, powiedzmy, że naciskasz Ai B, każdy wywołuje
keydown
zdarzenie, które ustawiamap[e.keyCode]
wartośće.type == keydown
, co daje wartość true lub false . Teraz obamap[65]
imap[66]
są ustawione natrue
. Kiedy puściszA
,keyup
zdarzenie zostaje wyzwolone, powodując, że ta sama logika określa przeciwny wynik dlamap[65]
(A), który jest teraz fałszywy , ale ponieważmap[66]
(B) jest nadal „w dół” (nie wywołał zdarzenia klucza), pozostaje prawdą .map
Array, dzięki obu imprez, wygląda następująco:Możesz teraz zrobić dwie rzeczy:
A) Rejestrator kluczy ( przykład ) można utworzyć jako odniesienie na później, gdy chcesz szybko znaleźć jeden lub więcej kodów kluczy. Zakładając, że zdefiniowałeś element html i wskazałeś na niego zmienną
element
.Uwaga: możesz łatwo pobrać element według jego
id
atrybutu.Tworzy to element html, do którego można łatwo odwołać się w javascript za pomocą
element
Nie musisz go nawet używać
document.getElementById()
ani$()
chwytać. Jednak ze względu na kompatybilność$()
szerzej zalecane jest używanie jQuery .Po prostu upewnij się, że tag skryptu znajduje się po treści kodu HTML. Wskazówka dotycząca optymalizacji : większość znanych witryn umieszcza tag script po tagu body w celu optymalizacji. Dzieje się tak, ponieważ znacznik skryptu blokuje ładowanie dalszych elementów do czasu zakończenia pobierania skryptu. Umieszczenie go przed treścią umożliwia wcześniejsze załadowanie treści.
B (gdzie leży twoje zainteresowanie) Możesz sprawdzić jeden lub więcej kluczy w tym samym czasie, w którym
/*insert conditional here*/
był, weź ten przykład:Edycja : to nie jest najbardziej czytelny fragment. Czytelność jest ważna, więc możesz spróbować czegoś takiego, aby ułatwić oczy:
Stosowanie:
Czy to jest lepsze?
(koniec edycji)
Ten przykład sprawdza CtrlShiftA, CtrlShiftBorazCtrlShiftC
To takie proste :)
Uwagi
Śledzenie kodów kluczy
Zasadniczo dobrą praktyką jest dokumentowanie kodu, zwłaszcza takich rzeczy, jak kody kluczy (np.
// CTRL+ENTER
), Abyś mógł zapamiętać, jakie to były.Powinieneś również umieścić kody kluczy w tej samej kolejności, co w dokumentacji (
CTRL+ENTER => map[17] && map[13]
NIEmap[13] && map[17]
). W ten sposób nigdy nie będziesz zdezorientowany, gdy będziesz musiał wrócić i edytować kod.Gotcha z łańcuchami if-else
Jeśli sprawdzasz kombinacje o różnych ilościach (jak CtrlShiftAltEnteri CtrlEnter), umieść mniejsze kombinacje po większych kombinacjach, w przeciwnym razie mniejsze kombinacje zastąpią większe kombinacje, jeśli są wystarczająco podobne. Przykład:
Rozumiem: „Ta kombinacja klawiszy ciągle się aktywuje, mimo że nie naciskam klawiszy”
W przypadku alertów lub czegokolwiek, co jest aktywowane w oknie głównym, możesz chcieć włączyć
map = []
resetowanie tablicy po spełnieniu warunku. Dzieje się tak, ponieważ niektóre rzeczy, na przykładalert()
, odciągają fokus od głównego okna i powodują, że zdarzenie „keyup” nie jest wyzwalane. Na przykład:Gotcha: ustawienia domyślne przeglądarki
Oto irytująca rzecz, którą znalazłem, z dołączonym rozwiązaniem:
Problem: Ponieważ przeglądarka zwykle ma domyślne działania na kombinacjach klawiszy (np. CtrlDAktywuje okno zakładek lub CtrlShiftCaktywuje skynote na maxthonie), możesz też chcieć dodać
return false
późniejmap = []
, aby użytkownicy Twojej witryny nie byli sfrustrowani, gdy „Duplikat pliku” funkcja, CtrlDzamiast tego tworzy zakładki do strony.Bez
return false
okno zakładek będzie pop-up, ku przerażeniu użytkownika.Instrukcja return (nowa)
Okay, więc nie zawsze chcesz wyjść z funkcji w tym momencie. Dlatego
event.preventDefault()
jest tam funkcja. To, co robi, to ustawienie wewnętrznej flagi, która mówi interpreterowi, aby nie zezwalał przeglądarce na wykonanie jej domyślnej akcji. Po tym wykonywanie funkcji jest kontynuowane (natomiastreturn
natychmiast opuści funkcję).Zrozum to rozróżnienie, zanim zdecydujesz, czy użyć
return false
lube.preventDefault()
event.keyCode
jest przestarzałeUżytkownik SeanVieira wskazał w komentarzach, który
event.keyCode
jest przestarzały.Tam podał doskonałą alternatywę
event.key
:, która zwraca ciąg znaków reprezentujący naciśnięty klawisz, na przykład"a"
for Alub"Shift"
for Shift.Poszedłem do przodu i przygotowałem narzędzie do badania wspomnianych strun.
element.onevent
vselement.addEventListener
Handlery zarejestrowane za pomocą
addEventListener
można łączyć i wywoływać w kolejności rejestracji, podczas gdy.onevent
bezpośrednie ustawienie jest raczej agresywne i zastępuje wszystko, co miałeś wcześniej..onevent
Nieruchomość wydaje się przesłaniać wszystko i zachowanieev.preventDefault()
ireturn false;
może być dość nieprzewidywalne.W obu przypadkach obsługa zarejestrowana za pośrednictwem
addEventlistener
wydaje się być łatwiejsza do napisania i uzasadnienia.Istnieje również
attachEvent("onevent", callback)
niestandardowa implementacja Internet Explorera, ale jest to przestarzałe i nie dotyczy nawet JavaScript (dotyczy to ezoterycznego języka zwanego JScript ). Byłoby w twoim najlepszym interesie unikanie kodu poliglotowego tak bardzo, jak to możliwe.Klasa pomocnicza
Aby rozwiązać problem / skargi, napisałem „klasę”, która wykonuje tę abstrakcję ( link wklejania ):
Ta klasa nie robi wszystkiego i nie poradzi sobie z każdym możliwym przypadkiem użycia. Nie jestem facetem z biblioteki. Ale do ogólnego użytku interaktywnego powinno być dobrze.
Aby użyć tej klasy, utwórz instancję i wskaż element, z którym chcesz skojarzyć wprowadzanie z klawiatury:
To spowoduje dołączenie nowego odbiornika wejściowego do elementu z
#txt
(załóżmy, że jest to obszar tekstowy) i ustawienie punktu obserwacyjnego dla kombinacji klawiszyCtrl+5
. Gdy obaCtrl
i5
są wyłączone,"FIVE "
zostanie wywołana funkcja zwrotna, którą przekazałeś (w tym przypadku funkcja, która dodaje do obszaru tekstowego). Callback jest powiązany z nazwąprint_5
, więc aby je usunąć, wystarczy użyć:Aby odłączyć
input_txt
odtxt
elementu:W ten sposób odśmiecanie może odebrać obiekt (
input_txt
), jeśli zostanie wyrzucony, i nie pozostanie stary odbiornik zdarzeń zombie.Dla dokładności, oto krótkie odniesienie do API klasy, przedstawione w stylu C / Java, abyś wiedział, co zwracają i jakich argumentów oczekują.
Aktualizacja 2017-12-02 W odpowiedzi na prośbę o opublikowanie tego na github stworzyłem streszczenie .
Aktualizacja 2018-07-21 Od jakiegoś czasu bawię się programowaniem w stylu deklaratywnym, a teraz jest to mój ulubiony: skrzypce , pastebin
Generalnie będzie działać z przypadkami, które chcesz realistycznie (ctrl, alt, shift), ale jeśli musisz uderzyć, powiedzmy,
a+w
w tym samym czasie, nie byłoby zbyt trudno „połączyć” podejścia w wyszukiwanie wieloprzyciskowe.Mam nadzieję, że ten
dogłębnie wyjaśnionymini blog okazał się pomocny :)źródło
return false
vspreventDefault()
keyCode
jest przestarzałe - jeśli przełączysz się nakey
, otrzymasz rzeczywistą reprezentację znakową klucza, która może być ładna.myString[5]
to to samo co5[myString]
i nawet nie da ci ostrzeżenia o kompilacji (nawet z-Wall -pedantic
)? Dzieje się tak, ponieważpointer[offset]
notacja pobiera wskaźnik, dodaje przesunięcie, a następnie odwołuje się do wyniku, czyniącmyString[5]
to samo, co*(myString + 5)
.Powinieneś użyć zdarzenia keydown , aby śledzić naciśnięte klawisze, i powinieneś użyć zdarzenia keyup , aby śledzić, kiedy klawisze są zwolnione.
Zobacz ten przykład: http://jsfiddle.net/vor0nwe/mkHsU/
(Aktualizacja: odtwarzam kod tutaj, na wypadek bejdy jsfiddle.net :) HTML:
... i JavaScript (przy użyciu jQuery):
W tym przykładzie używam tablicy, aby śledzić, które klawisze są naciskane. W prawdziwej aplikacji możesz chcieć
delete
każdego elementu po zwolnieniu skojarzonego z nim klucza.Zauważ, że chociaż użyłem jQuery, aby ułatwić sobie pracę w tym przykładzie, koncepcja działa równie dobrze podczas pracy w „surowym” JavaScript.
źródło
onblur
procedurę obsługi zdarzeń, która usuwa wszystkie wciśnięte klawisze z tablicy. Gdy stracisz koncentrację, sensowne byłoby ponowne naciśnięcie wszystkich klawiszy. Niestety nie ma odpowiednika JSGetKeyboardState
.źródło
Użyłem w ten sposób (musiałem sprawdzić, gdzie jest wciśnięty Shift + Ctrl):
źródło
kto potrzebuje pełnego przykładowego kodu. Dodano Prawo + Lewo
źródło
Spraw, aby keydown wywoływał nawet wiele funkcji, przy czym każda funkcja sprawdza określony klawisz i odpowiednio reaguje.
źródło
Spróbuję dodać
keypress
Event
obsługę nakeydown
. Na przykład:To tylko ma na celu zilustrowanie wzoru; Nie będę tutaj wchodził w szczegóły (zwłaszcza nie do
Event
rejestracji na poziomie 2 + konkretnej przeglądarki ).Odeślij proszę, czy to pomaga, czy nie.
źródło
Jeśli jeden z wciśniętych klawiszy to Alt / Crtl / Shift, możesz użyć tej metody:
źródło
źródło
Nie jest to metoda uniwersalna, ale w niektórych przypadkach jest przydatna. Jest to przydatne w przypadku kombinacji takich jak CTRL+ somethinglub Shift+ somethinglub CTRL+ Shift+ somethingitp.
Przykład: Jeśli chcesz wydrukować stronę za pomocą CTRL+ P, po pierwszym naciśnięciu klawisza zawsze CTRLnastępuje P. To samo z CTRL+ S, CTRL+ Ui innymi kombinacjami.
źródło
Wiem, że nie jest to najlepszy sposób.
źródło
źródło