Autor Wątek: [allegro] clear_keybuf()  (Przeczytany 3318 razy)

Offline nnwiltb

  • Użytkownik

# Styczeń 30, 2008, 15:14:54
Cześć, a więc mam problem z allegro i przydała by się jakaś rada.
Mam zagnieżdżoną pętle while której warunkiem jest wciśniecie klawisza esc:
while (!key[KEY_ESC]) {
   while (!key[KEY_ESC]) {
       //blok 1
   }
   clear_keybuf();
}
tak.. i gdy program jest w bloku 1 to teoretycznie do wyjścia z całej tej pętli potrzebował by dwukrotnego wciśnięcia esc, a tak nie jest (wystarczy raz). Co ciekawe pomaga funkcja rest() i zawieszenie aplikacji na ok pół sekundy po wywołaniu funkcji clear_keybuf(), ale niestety nie mogę pozwolić sobie na taką zwłokę  :-\.

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline Złośliwiec

  • Użytkownik
    • Dark Cult

# Styczeń 30, 2008, 15:45:22
Teoretycznie powinno działać tak jak działa :). Nie myl teorii ze swoimi oczekiwaniami :).

Musisz wprowadzić jakiegoś timeouta po wyjściu z wewnętrznej pętli - ale tylko po wyjściu z niej. Krótko mówiąc, coś w stylu:

Kod: (cpp) [Zaznacz]
while (!key[KEY_ESC])
{
  while (true)
  {
       //blok 1
 
   if (key[KEY_ESC])
   {
    rest(n);
    clear_keybuf();
    break;
   }
  }
   clear_keybuf();
}

Nie wiem czy to zadziała, bo Allegro nie używałem od lat, ale ten przykład ilustruje o co chodzi :).

hitronic

  • Gość
# Kwiecień 26, 2008, 12:29:12
Wystarczy napisać coś takiego:

while (!key[KEY_ESC]) {
   while (!key[KEY_ESC]) {
       //blok 1
   }
   key[KEY_ESC]=false;
}

Offline RedHot

  • Użytkownik

# Kwiecień 26, 2008, 23:44:40
Jedno wciśnięcie klawisza może wrzucić parę "zdarzeń" czy jak to nazwać, do bufora. Rest zapobiega przechwyceniu zbyt wielu klawiszy. Na bardzo starych kompach takiego problemu by nie było.  Co do kodu goriniego to nie działa.

Offline Krzysiek K.

  • Moderator
    • DevKK.net

# Kwiecień 27, 2008, 00:02:18
Mylicie dwie różne rzeczy. Tablica key[] przechowuje aktualny stan klawiszy i generalnie nie powinno się w niej grzebać samemu. Do tego istnieje bufor wciśnięć klawiszy, do którego wrzucane są wszystkie przychodzące zdarzenia wciśnięć i powtórzeń klawiszy i właśnie ten bufor czyści funkcja clear_keybuf(), ale z reguły się ona do niczego nie przydaje, bo każdy odczyt klawisza usuwa odczytany klawisz z bufora. Do obsługi tego bufora należy użyć funkcji keypressed() (zwraca informację, czy cokolwiek znajduje się w buforze) oraz readkey() (zwraca scancode i kod ASCII wciśniętego klawisza).

Tak poza tym, to nie mam pojęcia, jak miały by działać prezentowane pętle, bo skoro pierwsze wciśnięcie Esc miało by wychodzić tylko z pętli wewnętrznej, to pętla zewnętrzna natychmiast wrzuciła by sterowanie z powrotem do pętli wewnętrznej.

Offline Złośliwiec

  • Użytkownik
    • Dark Cult

# Kwiecień 27, 2008, 00:24:26
Tak poza tym, to nie mam pojęcia, jak miały by działać prezentowane pętle, bo skoro pierwsze wciśnięcie Esc miało by wychodzić tylko z pętli wewnętrznej, to pętla zewnętrzna natychmiast wrzuciła by sterowanie z powrotem do pętli wewnętrznej.

Zakładam, że po wyjściu z wewnętrznej pętli miało się jeszcze coś dziać, lecz autor wątku pominął ten fragment kodu jako nieistotny dla przedstawionego problemu :).

Offline Kosai_

  • Użytkownik
    • devlog

# Kwiecień 27, 2008, 00:32:09
aj aj problem jest o wiele bardziej przyziemny...
jeśli dany klawisz jest wciśnięty, to w tablicy key[] będzie miał wartość true. jeśli jest wciśnięty, a nie został wciśnięty, tzn. dopóki klawisz jest wciśnięty będzie miał w tablicy wartość true.
Problem leży w tym, że gdy program wychodzi z zagnieżdżonej pętli, co dzieje się w baaardzo krótkim czasie, klawisz ESC jest wciąż wciśnięty (kto zna osobę która potrafi tak szybko walić w klawiaturę, żeby dany klawisz nie był wciśnięty więcej niż 20 milisekund, ha!), więc warunek głównej pętli też ma wartość true i pętla się kończy. Aby temu zaradzić wystarczy użyć funkcji rest(100), gdy wychodzimy z zagnieżdżonej pętli

while(!key[KEY_ESC])
{
   while(!key[KEY_ESC])
   {
      ...
   }
   rest(100);   //poczekaj, aż użytkownik zdejmie palec z klawisza
}

Offline RedHot

  • Użytkownik

# Kwiecień 27, 2008, 15:46:25
@up
Ale jeśli to nad czym nnwiltb pracuje to gra, to osiągnie w niej max 10 fps-ów , przy rest(100). Zakładając, że pętla while (ta z //blok 1) też trochę czasu zabierze. Poza tym nie widzę zastosowania  tak zagnieżdżonych dwóch while'i. nnwiltb , możesz powiedzić co chcesz w ten sposób osiągnąć?

Offline Krzysiek K.

  • Moderator
    • DevKK.net

# Kwiecień 27, 2008, 15:57:05
Cytuj
Zakładam, że po wyjściu z wewnętrznej pętli miało się jeszcze coś dziać, lecz autor wątku pominął ten fragment kodu jako nieistotny dla przedstawionego problemu :).
Ja bym raczej strzelał, że to jest bardzo niepomyślna próba zrobienia jakiegoś podmenu, z którego ma się wychodzić klawiszem Esc. :)

Offline Kosai_

  • Użytkownik
    • devlog

# Kwiecień 27, 2008, 17:49:04
@up up
to w takim razie można zrobić kolejną pętlę, która wykonuje się, dopóki klawisz nie będzie naciśnięty
while(!key[KEY_ESC])
{
  while(!key[KEY_ESC])
  {
    ...
  }
  while(key[KEY_ESC]) //esc jest wciśnięty, czekaj, aż zdejmie
  {
    rest(1);
  }
   //użytkownik zdjął palec z klawisza
}

hitronic

  • Gość
# Kwiecień 27, 2008, 17:54:23
A ja sadze, ze nnwiltb juz o problemie nie pamieta, zwlaszcza, ze minely prawie 4 miesiace ;]. Po co bez sensu odgrzewac takie tematy?

PS. Sorry za alfabet czysto lacinski, ale pisze z LFS Live CD ;].

Offline RedHot

  • Użytkownik

# Kwiecień 27, 2008, 18:41:56
OWN3d  :o Nie spojrzałem na datę 1 postu i sugerowałem się odpowiedzią goriniego, argh :/ Dobrze deX(ter), że to zauważyłeś.


@Down

Chodzi o to by rozwiązać problem jak najoptymalniej, a nie byle by go rozwiązać. Dążenie do jak najmniejszej złożoności rzadko bywa trywialne  :-\
« Ostatnia zmiana: Kwiecień 27, 2008, 19:54:48 wysłana przez RedHot »

hitronic

  • Gość
# Kwiecień 27, 2008, 19:07:03
Ten problem i tak był elementarny, kiedyś miałem podobny to przysiadłem i rozwiązałem sobie.