Autor Wątek: Java ME - wyświetlenie 8 klatek animacje.  (Przeczytany 3048 razy)

Offline LinK

  • Użytkownik

# Styczeń 25, 2011, 02:01:04
Witam wszystkich serdecznie,
Mam kolejny problem, a mianowicie chcę aby została wyświetlona sekwencja klatek animacji, a następnie zniknęła. Czyli wyświetla się TYLKO raz animacja wybuchu składająca się z 8 klatek i znika. Próbuje coś wykąbinować tak jak to jest przedstawione poniżej, ale niestety animacja wyświetla się z 16 razy i znika. Nie mam już pomysłu jak to rozwiązać. Proszę o jakąś rade. POZDRAWIAM
static int licznik = 0;
static boolean czyWybucha = true;
for(int i = 0; i < timer; i++) {
if(czyWybucha) {
licznik++;
if(licznik == 192) czyWybucha = false;
mina.wybuch.nextFrame();
} else {
licznik = 0;
mina.wybuch.setVisible(false);
}
}

Offline Mr. Spam

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

Offline Lerhes

  • Użytkownik

# Styczeń 25, 2011, 11:51:36
Nie wiadomo jak masz zrobiona synchronizację czasową, ale zakładam, że poprawnie (wygląda to tak, jakbyś korzystał z timerów).
Tak czy siak,  może po prostu zrób: if(licznik == 16) czyWybucha = false;  ??
Lerhes

Offline LinK

  • Użytkownik

# Styczeń 25, 2011, 12:25:53
Witam,
Niestety wiświetla się tylko jedna klatka animacji i na tym koniec. Timer pochodzi z metody przedstawionej poniżej. Niby problem wydaje się prosty, ale nie potrafie sobie z nim poradzić.
//Narzędzia
//Pobierz czas oczekiwania pomiędzy odświerzaniem ekranu.
//Normalnie czekamy tylko pojedynczą milisekunde tylko po
//to aby dać szanse głównemu wątkowi do aktualizacji
//informacji dotyczących naciśniętych klawiszy, ale ta
//metoda zapewnia nas o tym, że gra nie pokarze wiecej
//niż 20 klatek na sekunt. (zachowanie płynności gry na
//różnych urządzeniach)
static long getWaitTime() {
long retWartosc = 1;
long roznica = System.currentTimeMillis() - ostatniCzasOdswierzania;
if(roznica < 50) {
retWartosc = 50 - roznica;
}
return(retWartosc);
}

Offline Lerhes

  • Użytkownik

# Styczeń 25, 2011, 13:55:00
Sam to napisałeś? Bo mi się wydaje trochę zła. Do pełni obrazu brakuje mi jeszcze informacji jak inicjalizowana i zmieniana jest wartość ostatniCzasOdswierzania.

Funkcja zwraca czas opóźnienia. Ustalone jest, że klatka ma być renderowana co 50 milisekund. Spoko. Jak się nie wyrobi z rysowaniem, to powinien rysować od razu następną, bez opóźnienia, więc:
long retWartosc = 0; ma być raczej.
Tak jak mówiłem, nie wiem gdzie zmienia się ostatniCzasOdswierzania, ale chyba najlepiej zrobić to w tej funkcji właśnie:
static long getWaitTime() {
long retWartosc = 0;
long roznica = System.currentTimeMillis() - ostatniCzasOdswierzania;
ostatniCzasOdswierzania = System.currentTimeMillis();
if(roznica < 50) {
retWartosc = 50 - roznica;
}
return(retWartosc);
}
No i spoko, gdzieś w kodzie wywołujesz zapewne funkcję (nie wiem co to za API):
System.delay( getWaitTime() );

Więc teraz moje pytanie: ale skąd Ci się timer wzięło w funkcji do rysowania klatek, skoro ta główna pętla przetwarzania realizowana jest na opóźnieniu??
Lerhes
« Ostatnia zmiana: Styczeń 25, 2011, 14:16:28 wysłana przez Lerhes »

Offline Krzysiek K.

  • Redaktor
    • DevKK.net

# Styczeń 25, 2011, 14:04:17
LinK: Powiedz mi, bo nie rozumiem: po jaki średnik masz w tym kodzie użyte "for"?

Offline LinK

  • Użytkownik

# Styczeń 25, 2011, 14:28:55
Funkcja getWaitTime() wywoływana jest w klasie dziedziczącej po Thread w metodzie run(). Kod poniżej:
//Uruchomienie gry.
public void run() {
//Wyczyść wszystkie naciśnięcia przycisku przed
//rozpoczęciem gry.
pCanvas.czyscKlawisze();
czyStop = false;
czyPause = false;
while(true) {
ostatniCzasOdswierzania = System.currentTimeMillis();
if(czyStop) {
break;
}
pCanvas.sprawdzKlawisze();
pCanvas.aktualizujEkran();
//Robimy bardzo krutką przerwe aby wątek
//miał czas na aktualizacje iformacji
//na temt klawisza który został naciśniety
//i regulujemy prędkość animacji.
synchronized (this) {
try {
wait(getWaitTime());
} catch (Exception e) {
// TODO: handle exception
}
}
if(czyPause) {
synchronized (this) {
try {
wait();
} catch (Exception e) {
// TODO: handle exception
}
}
}
}
}

Metody getWaitTime() nie napisałem sam, wziąłem ją z książki C. Hamer Creating Mobile Games [ENG]. Odnośnie pytania skąd wzięła się wartość zwracana przez metode getWaitTimer() w funkcji rysowania klatek, to muszę się przyznać szczerze, że nie miałem już pomysłu jak smusić wyświetlanie się tych 8 klatek animacji i do jakiego timera podporządkować całą tą animacje. Dalej jestem w martwym punkcie, ponieważ nie wiem jak to zrobić.
Odpowiedz na pytanie użytkownika Krzysiek K.:
Użyłem "for", bo miałem nadzieję, że po wejściu w pętle wykona się odpowiednia ilość animacji i dość. Próbowałem też tylko na "if'ach", ale bez rezultatu.
Zaznaczam jeszcze, że wunkcja, która wyświetla animacje jest wywoływana w głównym wątku gry i za każdym tyknięciem gry wywoływana jest ta funkcja czyli animacja wyświetla się bez przerwy dopuki nie ustawie jeje jako niewidocznej czyli setVisible(false).
Czekam z niecierpliwością na wasze sugestie.
POZDRAWIAM

Offline Krzysiek K.

  • Redaktor
    • DevKK.net

# Styczeń 25, 2011, 14:36:22
Cytuj
Użyłem "for", bo miałem nadzieję, że po wejściu w pętle wykona się odpowiednia ilość animacji i dość.
Nadzieja dobra rzecz, ale w programowaniu się nie sprawdza. Pomyśl, że po wejściu w taką pętlę musi wykonać się wszystko w niej, zanim ruszy reszta gry.

Cytuj
Zaznaczam jeszcze, że wunkcja, która wyświetla animacje jest wywoływana w głównym wątku gry i za każdym tyknięciem gry wywoływana jest ta funkcja
Wniosek: za każdym tyknięciem funkcja powinna przerzucić animację na następną klatkę i nic więcej.

Offline Lerhes

  • Użytkownik

# Styczeń 25, 2011, 14:46:44
Tak jak Krzysiek mówi: Umieść w komentarzu for(int i = 0; i < timer; i++) {   i jego zamykający nawias }. A licznik zmień na if( licznik == 16 ) czyWybucha = false;
Btw: Dalej jestem ciekawe wtf is timer w tej pętli....

Edit down: Iterowałeś klatki animacji tyle milisekund ile zwróciła funkcja opóźniająca? WTF? I co miałeś na myśli przez to osiągnąć?
Lerhes
« Ostatnia zmiana: Styczeń 25, 2011, 15:57:50 wysłana przez Lerhes »

Offline LinK

  • Użytkownik

# Styczeń 25, 2011, 15:32:05
Ok, dzięki jak będę w domu to spróbuje. Oczywiście ta metoda która jest wywoływana w głównym wątku gry ustawia kolejną klatkę animacji.
Jeśli chodzi o zmienna timer, jest to zmienna statyczna w której jest przechowywana wartość zwaracana przez metodę getWaitTime(). Pewnie to był zły pomysł umieszczając ją w tej pętli??
POZDRAWIAM

Offline LinK

  • Użytkownik

# Styczeń 26, 2011, 13:43:31
Witam,
Niestety, to nadal nie działa. Tym razem wogóle nic się nie wyświetla. Może przyczyną jest to, że metoda ta jest wywoływana od razu jak tyklo rozpocznie się gra?
"Iterowałeś klatki animacji tyle milisekund ile zwróciła funkcja opóźniająca? WTF? I co miałeś na myśli przez to osiągnąć?". Nie bardzo rozumie, iterowałem zmienna o nazwie "licznik", a nie "timer". Wartość timer była jedynie zmienną do której była porównywana wartość "i" w pętli "for".
POZDRAWIAM

Offline Lerhes

  • Użytkownik

# Styczeń 26, 2011, 15:39:11
Przeczytaj co to jest debugger i sprawdź nim co dokładnie się dzieje w tym fragmencie kodu dotyczącym wyświetlenia.

Generalnie to jak masz 8 klatek animacji a każda wyświetla się co 50 ms, to w sumie animacja wybuchu powinna się wyświetlać przez 400 ms -> czyli niecałe pół sekundy. Może to trochę za szybko ? (chociaż nie widzę możliwości, żeby tego nie zauważyć).

Najważniejsze - sprawdź breakpointem, czy w ogóle osiągasz ten fragment kodu.

Całość powinna wyglądać, mniej więcej tak (specjalnie zwolniłem tempo animacji do 4 sekund):
static int licznik = 0;
static boolean czyWybucha = true;
if(czyWybucha)
{
licznik++;
if(licznik == 80) czyWybucha = false;
if( ! ( licznik % 10)  )   mina.wybuch.nextFrame();
} else {
licznik = 0;
mina.wybuch.setVisible(false);
}
Lerhes

Offline LinK

  • Użytkownik

# Styczeń 26, 2011, 21:31:04
Witam,
Na reszcie udało mi się z tym uporać po całym dniu męki. Jestem wam bardzo wdzięczny za waszą pomoc, bo naprawdę bez was bym sobie nie poradził. Jak mi się udało to zrobić? Najpierw kod:
public int animacjaWybuchu(boolean czy) {

czyWybucha = czy;
if(czyWybucha)
{
licznik++;
//if(licznik == 8) czyWybucha = false;
//if( licznik%10 == 0  )   
if(licznik < 8) {
mina.wybuch.setVisible(true);
mina.wybuch.nextFrame();

} else {
licznik = 0;
mina.wybuch.setVisible(false);
czyWybucha = false;
//czyWybucha = true;
}
}

return(licznik);
}
Nie patrzcie na wartość zwracaną przez tą metode, bo mumieściłem ją sobie aby sprawdzić podczas debuggowania, czy licznik prawidłowo się zwiększa, a następnie po osiągnięciu pożądanej wartości zeruje. No i czy jest wyświetlana ta klatka animacji, która powinna być.
Do rzeczy, Lerhes dzięki za pomoc. Kod który mi zarzuciłeś miał jeden błąd ponieważ nie można wykonać negacji logicznej, na typie "int" więc podczas debuggowania Twojego kodu zmieniłem na "( licznik%10 == 0  )" i klatka animacji była wyświetlana co 10 czyli tak jak to miało być. Ale nie o to chodzi, bo cały czas męczyłem się z tym jak spowodować wywołanie funkcji w czasie w którym wróg(przeciwnik) staje na minę. Użyłem do tego zmiennej statycznej "boolean" i przypisuje jej wartość "TRUE" gdy jest kolizja z miną. No i już prawie jestem w domku. Potem tą samą zmienną przekazuje jako argument do metody zmieniającej animacje, to ta powyżej. Następnie gdy określona liczba animacji jest już wykona, to tą samą zmienną statyczną typu "boolean" inicjalizuje jako "FALSE".
Poniżej kod sprawdzający zmienną statyczną i wrzucający ją jako argument metody:
if(czyWybucha) {
warZwrotna = animacjaWybuchu(czyWybucha);
}
Jeszcze raz OGROMNE podziękowania wszystkim, którzy się zainteresowali moim problemem. A ha, jeszcze wziąłem pod uwagę waszą sugestie odnośnie pętli "for" i dokonałem kilku zmian w kodzie :).
DZIĘKI WIELKIE!

Offline Groshu

  • Użytkownik

# Styczeń 26, 2011, 23:05:53
Jeśli z jakichś powodów (np. rozbudowy programu) dojdzie kiedyś do tego, że częstotliwość wywoływania tej funkcji będzie mniejsza, to możesz mieć problem z tą animacją. Przykładowo niech zostanie wywołana przy wartościach timera 7, 9, 11, 12, 14, 15, 17, 19, 21, 23, 24, 26, 27, 29, 32... i okaże się, że w okresie czasu, w którym powinny być wyświetlone 4 klatki, będzie wisiała ciągle jedna i w efekcie cała animacja "zamuli się". Przy większej liczbie takich animacji gra może się nieźle rozjechać.