Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[Allegro] Losowanie wartości

Ostatnio zmodyfikowano 2011-05-09 00:58
Autor Wiadomość
dmx81
» 2011-05-06 14:58:47
C/C++
bool pr = false;
int hit = 0;

if( kolizja( player.x, player.y, player.s, player.w, enemy.x, enemy.y, enemy.s, enemy.w ) == true )
{ if( key[ KEY_Z ] ) pr = true;
   
    hit = rand() % 100;
    if( !key[ KEY_Z ] && pr == true )
    {
        if( hit <= 66 ) { masked_blit( dymek, bufor, 0, 0, enemy.x + 10, enemy.y + 10, enemy.s, enemy.w ); } else masked_blit( trafienie, bufor, 0, 0, enemy.x + 10, enemy.y + 10, enemy.s, enemy.w );
       
    } }
przeczytaj swoj kod ze zrozumieniem, zacznijmy od linii po losowaniu hit:

- jesli nie wciskasz klawisza Z, a ustawione masz, ze byl wcisniety i jesli dodatkowo hit <= 66 to wyswietl dymek...
o to ci chodzi?

pomysl teraz, jak bedzie wygladal przebieg calego programu (wg kodu,ktory widac tutaj)
przykladowe zdarzenie:
pr ustawiasz na false zawsze;
sprawdzasz czy kolizja, jesli tak, sprawdzasz, czy wcisniety klawisz, jesli tak, to ustawiasz pr na true;
losujesz liczbe;
sprawdzasz, czy klawisz puszczony, ale czy byl wcisniety, jesli tak, to sprawdzasz,ile wynosi hit i w pewnym przedziale jego wartosci wykonujesz odpowiednia akcje - to byla jedna klatka , teraz bedzie nastepna:

pr znow ustalasz na false, powtarzasz operacje - jesli trzymalbys ciagle wcisniety klawisz-dymka nie bedzie, bo blokujesz go przez linie pod losowaniem hit, wiec trzeba pomyslec,kiedy tak naprawde bedzie dymek??

bedzie tylko i wylacznie w momencie puszczenia klawisza Z - czyli przez jedna klatke z np 100 na sekunde - zdarzysz zauwazyc? A dlaczego akurat tylko wtedy? bo zeby aktywowac swoja akcje - klawisz musi miec status wcisnietego (czyli pr==true) co uzyskasz przez wcisniecie Z, ale Z nie moze byc wcisniety, bo tak masz zapisane w kodzie - czyli klawisz musisz puscic - wtedy bedzie krociotko dymek... a pr znow ustalisz na false, wiec kolejnej klatki animacji nie bedzie

Troche sie rozpisalem, ale mam nadzieje, ze widzisz problem, sprobuj go rozwiazac, nie jest to trudne,trzeba logicznie pomyslec i poprostu to przelac na kod...
podpowiem,ze mozesz np uzyc jakiegos licznika czy cos takiego, aby animacja trwala dluzej....
nie wiem,czy stosujesz timery (dobrze by bylo)
C/C++
int i = 100;
if( i > 0 )
{
    masked_blit(...);
    i--;
}
w ten sposob bedzie wyswietlac sie tak dlugo, jak szybko dziala twoj program (przy 100FPS bedzie to sekunda)

PS>> oczywiscie ten kod powyzej musisz przerobic, zeby i nie ustawialo ci sie na 100 za kazdym razem, tylko kiedy zejdzie do zera, a po drugie uwzglednij tez swoje warunki, kiedy to odliczanie ma nastapic - ja dalem tylko pomysl :)
P-32742
thamiar
Temat założony przez niniejszego użytkownika
» 2011-05-06 21:24:48
bedzie tylko i wylacznie w momencie puszczenia klawisza Z - czyli przez jedna klatke z np 100 na sekunde - zdarzysz zauwazyc? A dlaczego akurat tylko wtedy? bo zeby aktywowac swoja akcje - klawisz musi miec status wcisnietego (czyli pr==true) co uzyskasz przez wcisniecie Z, ale Z nie moze byc wcisniety, bo tak masz zapisane w kodzie - czyli klawisz musisz puscic - wtedy bedzie krociotko dymek... a pr znow ustalisz na false, wiec kolejnej klatki animacji nie będzie
Początkowo myślałem, że to jest właśnie problem. Niestety, jak pisałem wcześniej, zdaje się, że program po wciśnięciu tego nieszczęsnego „Z” nie ustawia pr. By udowodnić swoją tezę, w funkcji ustawiłem, by zamiast obrazka wroga, wyświetlać trupa kiedy hpwrog>0 Oczywiście dodatkowo dodałem warunek, by postać nie mogła atakować  tego trupa:
Wartością wyjściową hpwrog jest 2 (wielkość ustalona poza pętlą while(!key[KEY_ESC]) ), czyli tam gdzie zgodnie z poradnikiem umieszczamy zmienne.
C/C++
bool pr = false;
if( kolizja( player.x, player.y, player.s, player.w, enemy.x, enemy.y, enemy.s, enemy.w ) == true )
{
    if( key[ KEY_Z ] ) pr = true;
   
    hit = rand() % 100;
    if( !key[ KEY_Z ] && hpwrog > 0 && pr == true )
    { pr = false;
        if( hit <= 66 ) { masked_blit( dymek, bufor, 0, 0, enemy.x + 10, enemy.y + 10, enemy.s, enemy.w ); }
        else { hpwrog--;
            masked_blit( trafienie, bufor, 0, 0, enemy.x + 10, enemy.y + 10, enemy.s, enemy.w );
        } } }
 Nie zmienia się dosłownie nic! Klikam to z jak oszalały, animacji nie widać, przeciwnik stoi uśmiechnięty, ogólnie kaszana. Co więcej, dopisałem
play_sample( dzwiek2, 255, 127, 1000, 0 );
  do obu przypadków: trafienia i pudła!– obrazu nie zobaczę, ale dźwięk usłyszę, głuchy nie jestem… niestety cisza jak w grobie. Natomiast kiedy w powyższym kodzie zmienię jedna linijkę.
    if( key[ KEY_Z ] ) pr = true;
hit=rand() % 100;
    if( key[ KEY_Z ]&&hpwrog>0&&pr==true) //Zamiast if( !key[KEY_Z]&&hpwrog>0&&pr==true)
 Przy wciśniętym Z, w ciągu paru sekund widzę na ekranie trupa przeciwnika, zaś z głośniczków leci dźwięk. Więc nie jestem pewien, czy to po prostu problem z szybkością wyświetlania tych dymków.




Oczywiście zanim doszedłem do powyższych wniosków, próbowałem spowolnić obrazki. Najpierw spróbowałem wstawić Rest…
{ while( i > 0 ) { masked_blit( dymek, bufor, 0, 0, enemy.x + 10, enemy.y + 10, enemy.s, enemy.w ); rest( 2000 ); i--; }; play_sample( dzwiek1, 255, 127, 1000, 0 ); }
Pomiędzy atakami pojawiła się przerwa, ale obrazek znika ciągle tak samo szybko.
Następnie zaproponowane pętle while, potem spróbowałem do-while. Efekt identyczny jak w powyższym przypadku. Dymki znikają błyskawicznie. Myślałem, że „i” jest za małe… po jego zwiększeniu powtarza się ten sam problem. Program wyświetla obrazek z prędkością błyskawicy a potem przez moment czeka(oczywiście bez dymku który znika równie szybko co się pojawia).
C/C++
if( kolizja( player.x, player.y, player.s, player.w, enemy.x, enemy.y, enemy.s, enemy.w ) == true )
{ int i = 80000;
    if( key[ KEY_Z ] ) pr = true;
   
    hit = rand() % 100;
    if( key[ KEY_Z ] && pr == true )
    { pr = false;
        if( hit <= 66 )
        { while( i > 0 ) { masked_blit( dymek, bufor, 0, 0, enemy.x + 10, enemy.y + 10, enemy.s, enemy.w ); i--; }; }
        else
        {
            while( i > 0 ) { masked_blit( trafienie, bufor, 0, 0, enemy.x + 10, enemy.y + 10, enemy.s, enemy.w ); i--; };
           
        }
    }
}
Potem oczywiście w desperacji dodałem oba while do timerowej pętli while( speed > 0 ), ale zgodnie z oczekiwaniami, niczego to nie zmieniło.
Niestrudzenie próbowałem dalej,
C/C++
if( hit <= 66 ) { for( int i = 0; i < 100000; i++ ) { masked_blit( dymek, bufor, 0, 0, enemy.x + 10, enemy.y + 10, enemy.s, enemy.w ); } }
else { hpwrog--;
    for( int i = 0; i < 100000; i++ ) { masked_blit( trafienie, bufor, 0, 0, enemy.x + 10, enemy.y + 10, enemy.s, enemy.w ); }
} }
 Dało identyczny niechciany rezultat.
Myślałem, że to z powodu podwójnego bufforowania, ale przecież 
blit(bufor, screen, 0,0,0,0,640,480); mam poza całą funkcją ataku.
Gdybym wiedział, że coś jest nie tak, próbowałbym różnych kombinacji i nie zawracał wam głowy (Bo faktycznie trochę upierdliwy się robię).
Ale problem w tym, że na logikę wydaje mi się, że wszystko powinno być OK. Pętla while  działa dopóki spełniany jest warunek, for tak samo… w praktyce.
Podobnie z guzikiem, wszystko niby ok. (w tym przekonaniu utrwalił mnie Twój post Dmx81)
Ale w teorii nie robi niczego.

Może mam po prostu zepsute allegro :D
P-32754
dmx81
» 2011-05-07 02:04:07
oj troche tego do przeczytania i przeanalizowania, nie wiem czy dzis dam rade (wlasnie wrocilem z meczu i troszke padniety jestem)
ale pierwsze co rzucilo mi sie w oczy (chociaz nie rozwiazuje pewnie problemu...) to to, ze funkcje sleep(2000) uzywasz w miejscu, gdzie nie ma to sensu - przesylasz obrazek do bufora i czekasz 2 sek...
lepiej by bylo wyswietlic bufor na ekranie i poczekac 2 sekundy (bo obrazka na buforze nie zobaczysz, ale bufor na ekranie)

co do tego, czy dziala klawisz czy nie, poprobuj inne kombinacje, nie wrzucaj od razu wszyskich warunkow i losowania, tylko np
1. jesli klawisz Z wcisniety i pr false- ustaw pr na true, jesli Z puszczony i pr true, ustaw Z na false
2. jesli pr = true, wyswietlaj dymek

taki test pokaze dymek przy wcisnietym klawiszu

pozniej mozesz dopisac do tego (o ile zadziala to powyzej) warunek kolizji
jesli zadziala, dopiszesz jakis warunek, aby zadzialalo jednorazowo, czyli
1.jesli pr=true i cios=false, cios = true i odejmij np 10%zycia;
2.jesli cios = true, animuj dymek
3.jesli pr=false, cios=false;

1.wcisniety klawisz i nie bylo wczesniej ciosu - czyli pierwszy atak
2.cios ustawiony teraz na true, wiec animacja bedzie trwala, az do 3. puszczenia klawisza,ponowny atak sie nie wykona, bo tylko zadziala, jesli cios = false, a pr=true (czyli jak wyzej napisalem, przy pierwszym wcisnieciu klawisza
P-32768
thamiar
Temat założony przez niniejszego użytkownika
» 2011-05-07 13:36:15
Ogólnie, chciałem Ci bardzo podziękować Dmx81, za cierpliwość i czas który mi poświęciłeś.

Haha! Jestem ślepy jak kret ;)
Wystarczyło zmienic 
masked_blit( trafienie, vufor, 0, 0, enemy.x + 10, enemy.y + 10, enemy.s, enemy.w );
 na
masked_blit( trafienie, screen, 0, 0, enemy.x + 10, enemy.y + 10, enemy.s, enemy.w );
I wszystko działa ;) (w końcu nie muszę tego bufforować, bo żadnej animacji nie ma. A elementy buffora na ekran kopiowałem poza pętlą)
Wielkie dzięki Dmx81! Gdyby nie twój post zwyczajnie bym tego nie zauważył, będąc święcie przekonanym, że logicznie wszystko jest w porządku.


Co do drugiego problemu, zminimalizowałem problem i teraz wyraźnie widzę, że błąd jest w komendzie if( key[ KEY_Z ])
Dla kodu:
C/C++
bool pr = false;
if( key[ KEY_Z ] ) pr = true;

if( !key[ KEY_Z ] && pr == false ) { for( int i = 0; i < 500; i++ ) masked_blit( trafienie, screen, 0, 0, enemy.x + 10, enemy.y + 10, enemy.s, enemy.w ); pr = false; }
 zgodnie z oczekiwaniami, dymek wyświetlany jest non-stop, dopóki nie wcisnę Z. Po zmianie warunku pętli na !key[ KEY_Z ]&&pr==true, znowu nic się nie dzieje.
if( pr == true ) { for( int i = 0; i < 500; i++ ) masked_blit( trafienie, screen, 0, 0, enemy.x + 10, enemy.y + 10, enemy.s, enemy.w ); pr = false; }
 Również działa zgodnie z oczekiwaniami. Obrazek pojawia się gdy wcisnę i przytrzyma z.
Wszystkie moje teorie spiskowe dotyczące powodu niedziałania, obaliłem osobiście. Może warunek !key[ KEY_Z ]&&pr==true jakoś koliduje, czy coś? Pojęcia nie mam. Albo po prostu coś z tą komendąjest nie tak :P


pozniej mozesz dopisac do tego (o ile zadziala to powyzej) warunek kolizji
jesli zadziala, dopiszesz jakis warunek, aby zadzialalo jednorazowo, czyli
1.jesli pr=true i cios=false, cios = true i odejmij np 10%zycia;
2.jesli cios = true, animuj dymek
3.jesli pr=false, cios=false;
 Chyba nie za bardzo rozumiem tej porady. Przecież jeśli będę trzymał przyciśnięte Z, pr ciągle będzie miało wartość TRUE, więc animacja jest jest pokazana non stop, a hp wroga(wiec atak wykonany) ciagle spada. Nie muszę przestać naciskać klawisza.
C/C++
bool pr = false;

if( key[ KEY_Z ] ) { pr = true; }
if( pr == true && cios == false ) cios = true;

if( cios == true ) { for( int i = 0; i < 500; i++ ) { masked_blit( trafienie, screen, 0, 0, enemy.x + 10, enemy.y + 10, enemy.s, enemy.w ); } hpwrog--; pr = false; }
if( pr == false ) cios = false;

P-32786
dmx81
» 2011-05-07 18:07:13

Przecież jeśli będę trzymał przyciśnięte Z, pr ciągle będzie miało wartość TRUE, więc animacja jest jest pokazana non stop, a hp wroga(wiec atak wykonany) ciagle spada.

Zgadza sie :) a ja napisalem ci przyklad, jak zrobic, aby ciagle wcisniecie klawisza spowodowalo tylko jeden atak - ale ciagla animacje, a zeby zadac kolejny cios, ktory zabierze hp, musisz znow wcisnac klawisz (czyli wczesniej go puscic)

Ale to tylko sugestia - a rozwiazan jak sam widzisz, jest multum i tylko od ciebie, jako projektanta gry, zalezy, co tak naprawde bedzie sie dzialo :) wazne, zeby bylo to "intuicyjne", co zapewni dobra grywalnosc:)
P-32794
thamiar
Temat założony przez niniejszego użytkownika
» 2011-05-07 21:58:14
Znaczy kłopot właśnie w tym, że animacja jest ciągle wyświetlana i hp też spada. Właśnie dlatego jest problem!
Po prostu wszystkie kombinacje prócz tej której chcę (!key[ KEY_Z ]&&pr==true)działają, z niezrozumiałych dla mnie przyczyn.
P-32804
Gabes
» 2011-05-07 22:38:52
Zaznacz
if( kolizja( player.x,
...jako komentarz ukośnikami //
albo postaw średnik po ...
enemy.w ) == true )
  może kolizja==false?.


P-32807
dmx81
» 2011-05-07 22:54:43
najlepiej by bylo, jakbys mogl udostepnic kod z obrazkami (na jakims serwerze), to bym sprawdzil co i jak
P-32808
1 2 « 3 » 4
Poprzednia strona Strona 3 z 4 Następna strona