Warsztat - Programowanie gier

Lipiec 30, 2010, 17:31:57 *
Witamy, Gość. Zaloguj się, lub zarejestruj proszę.

Zaloguj się podając nazwę użytkownika, hasło i długość sesji
Aktualności: Warsztat, Regulamin forum, #warsztat, Wiki, FAQ, NoPaste, Mapa
 
   Strona główna   Pomoc Szukaj Zaloguj się Rejestracja  
Strony: [1]
  Drukuj  
Autor Wątek: Klawiatur w winApi  (Przeczytany 1091 razy)
micze
Jr. Member
**

wiadomości: 55


Zobacz profil
« : Lipiec 14, 2007, 15:39:27 »

Jestem w trakcie tworzenia swojego pierwszego projektu (gry) , dlatego wolałbym nie używać DirectInput. Mój problem polega na tym ,ze naciskając raz przycisk odpowiedzialny za wystrzelenie pocisku wylatuje bardzo wiele ( w zależności jak szybko go nacisne, raz udało mi sie "tylko" wystrzelić 3  Smiley  W tutorialu Xion'a jest opisane " opoznienie powtorzenia" - bo chyba tutaj tkwi rozwiązanie problemu. Niestety nie umiem nawet tego zaimplementować bo  po dokładnym przepisaniu kodu( az dwie 3 linijki)  kompilator (VS 6.0) wyrzuca komunikaty
 
SystemParametersInfoA' : missing storage-class or type specifiers
SystemParametersInfoA' : redefinition; different type modifiers

Jakby ktoś spotkał sie z podobnym problem prosiłbym o wyjaśnienie rozwiązania ( implementacji albo głównego wątku)
Zapisane
Mattrick
Sr. Member
****

wiadomości: 484


Zobacz profil WWW
« Odpowiedz #1 : Lipiec 14, 2007, 15:55:41 »

A jak pobierasz stan klawisza? Podaj ten kawałek z funkcji okna.

Edit:
Nie czekając na odpowiedź spróuję ci wyjaśnić. Jeżeli w swoim kodzie masz coś takiego:
Kod
case WM_KEYDOWN:
switch (wParam)
{
case JAKIS_TAM_KLAWISZ:
Strzelaj();
break;
};
break;
 
To program wygonuje te instrukcje jeżeli klawisz jest wciśnięty - a że twoja ręka nie jest taka szybka, to przeleci parę loopów. Jeżeli chcesz, żeby strzał był oddawany tylko raz przy kliknięciu klawisza, zamień kod na:
Kod
case WM_KEYUP:
switch (wParam)
{
case JAKIS_TAM_KLAWISZ:
Strzelaj();
break;
};
break;
 
W tym wypadku instrukcje wykonają się tylko wtedy, gdy klawisz zostanie puszczony (zmieni stan z wciśniętego), czyli wykona się dokładnie jeden raz przy jednym naciśnięciu (i zwolnieniu) klawisza.

Edit2:
Padło formatowanie, muszę je wywalić... ; /

Edit3:
Mniemam, iż chodzi ci o to, że przy jednym naciśnięciu klawisza wylatuje jeden pocisk. W przeciwnym wypadku - poczytaj o GetTickCount() lub innym pobieraczu czasu.
« Ostatnia zmiana: Lipiec 14, 2007, 16:05:48 wysłane przez Mattrick » Zapisane

mail/jabber: mattrick (na) jabster.pl

http://mattrick.jogger.pl
micze
Jr. Member
**

wiadomości: 55


Zobacz profil
« Odpowiedz #2 : Lipiec 14, 2007, 16:07:15 »

A robiłem to na dwa sposoby -
 - w procedurze okienkowej  switch (toupper(wParam))
                                                  ....................
                                                    case 'E'
                                                        {...}

                                                        oraz
                                           if(HIBYTE(GetAsyncKeyState(VK_SPACE))
 efekt oczywiście identyczny ( wykluczam błąd w kodzie "strzału" ,zwłaszcza ze liczba pocisków jest zależna od szybkości nacisku)

                                         
Zapisane
micze
Jr. Member
**

wiadomości: 55


Zobacz profil
« Odpowiedz #3 : Lipiec 14, 2007, 16:10:33 »

Dokładnie to chcialem wiedziec !! Dzieki...zabieram sie za implementacje Smiley
Zapisane
Mattrick
Sr. Member
****

wiadomości: 484


Zobacz profil WWW
« Odpowiedz #4 : Lipiec 14, 2007, 16:12:36 »

@wee
Co do twojej techniki - ja zrobiłem sobie makra
Kod
#define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEY_UP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)
 
Są o wiele wygodniejsze. ; )
Zapisane

mail/jabber: mattrick (na) jabster.pl

http://mattrick.jogger.pl
Reg
Member2000
*******

wiadomości: 3791



Zobacz profil WWW
« Odpowiedz #5 : Lipiec 15, 2007, 11:51:01 »

GetAsyncKeyState jest niefajne, bo reaguje na klawisze nawet kiedy aplikacja gry jest nieaktywna bo użytkownik robi coś innego w innym oknie. Polecam raczej reagować na WM_KEYDOWN i WM_KEYUP. Można sobie z ich pomocą zorganizować odczytywanie stanu wciśnięcia dowolnego klawisza w każdej klatce zapamiętując po prostu w tablicy które klawisze są wciśnięte, mniej więcej tak:

Kod:
bool Klawisze[256];
...
case WM_KEYDOWN:
  if (wParam < 256)
    Klawisze[wParam] = true;
  break;
case WM_KEYUP:
  if (wParam < 256)
    Klawisze[wParam] = false;
  break;

Co do opóźnień, to po pierwsze potrzebujesz funkcji pobierającej bieżący czas, na przykład liczbę sekund czy milisekund od startu systemu czy całej gry. Może to być funkcja GetTickCount lub dokładniejsza - QueryPerformanceCounter wspólnie z QueryPerformaceFrequency.

Teraz mając bieżący czas w danej klatce możesz zapamiętywać w jakiejś zmiennej czas ostatniego wystrzału i robić tak:

Kod:
// Na początku
const CO_ILE_STRZELAĆ = 200; // strzelać co 0.2 sekundy
DWORD CzasOstatniegoWystrzału = 0;

// W każdej klatce na początku
DWORD CzasBieżący = GetTickCount();

// W każdej klatce kiedy chcesz wystrzelić
if (Klawisze[VK_SPACE] == true)
{
  if (CzasOstatniegoStrzału + CO_ILE_STRZELAĆ < CzasBieżący)
  {
    Strzel();
    CzasOstatniegoStrzału = CzasBieżący;
  }
}

To się da zrobić jeszcze lepiej ale mniejsza z tym, najpościej jest tak.
Zapisane

Strony: [1]
  Drukuj  
 
Skocz do:  

Hosting: Polska Strefa - Ogłoszenia
Powered by SMF 1.1.7 | SMF © 2006, Simple Machines LLC