Aplet - metoda drawImage()

0
	
..............................
	if(wybrano>=0){
				
			//arg0.drawString("Wybrano karte nr." + wybrano, 10, 350);	
			arg0.drawImage( Talia[wybrano] , rect[wybrano].x ,rect[wybrano].y ,rect[wybrano].width ,rect[wybrano].height, this );
			
			
		}
			
			
	   if(wybrano2>=0){   
		   
			arg0.drawImage( Talia[wybrano2] , rect[wybrano2].x ,rect[wybrano2].y ,rect[wybrano2].width ,rect[wybrano2].height, this ); //Błąd obrazek sie nie ładuje
			arg0.drawString("Wybrano karte nr." + wybrano2, 10, 350);   //tekst sie wyświetla
.............................
	

Błąd polega na tym, że rysuje grafiki na obiekcie arg0, wykonuje kolejna funkcje. Grafiki znajduja sie w tablicy Talia i ma zostac wyswietlona w odpowiednim obiekcie klasy Rectangle (rect jest rowniez tablicą). Powyzszy kod jest zawarty w funkcji paint(); Dodam ze nie ma tu żadnych bledow wynikajacych ze zlego indexowania. Całość kodu jest grą która w 90% procentach działa dobrze, jednak w pewnych przypadkach nie ładuje sie grafika i juz nie wiem od czego to zalezy? Zmienne wybrano i wybrano2 sa generowane przez klikniecie w odpowiedni obszar

0

To, że przez większość czasu kod działa, a tylko czasem nie jest charakterystyczne dla niemal wszystkich źle napisanych programów. :-/ Dobrze zrobione programy albo nie działają wcale, albo perfekcyjnie. :d

Pytanie 1: Czy kod tego apletu był wrzucony do uruchomienia pod jakimkolwiek okienkiem Frame lub JFrame? i czy działał pod debuggerem na pułapce warunkowej?
Pytanie 2: Jakiej klasy jest obiekt arg0?
Pytanie 3: Jakiej klasy są, mogą być lub na pewno są obiekty trzymane w tablicy Talia?
Pytanie 4: Czy wybrano lub wybrano2 może przyjąć wartość ujemną?
Pytanie 5: Jeżeli to jest gra z animacją to dlaczego używany jest obserwator w postaci this?
W drawImage obserwator powinien być null jeżeli obrazek ma być gotowy do druku, a nie pozwalać mu na próby dogrywania się. W takim programie obrazek niezaładowany = bug.
Pytanie 6: Czy sprawdzałeś wykorzystanie pamięci? Kiedy coś idzie źle całkowita ilość pamięci (totalMemory) zrównuje się z maksymalną ilością pamięci (maxMemory), a wtedy wyczerpanie wolnej pamięci (freeMemory) powoduje śmierć aplikacji lub apletu (zaczynają się kaskady wyjątków i błędy wynikające z błędów).

Trzeba pomyśleć, co może pójść w tym kodzie źle:

  • Talia może zawierać pod przynajmniej jednym indeksem null. Może to nie być wykrywane jeżeli gdzieś w kodzie łapany jest wyjątek, który akurat pasuje do NullPointerException
  • tablica rect może zawierać na którymś indeksie współrzędne, które wyjeżdżają w kosmos i obrazek się drukuje, tyle, że gdzieś w przestrzeni kosmicznej. :d
  • coś może dziać się z obrazkiem w ten sposób, że drawImage będzie próbował ponownie go wgrać ze źródła.
  • może zwyczajnie zabraknąć pamięci jeżeli referencje do tworzonych obiektów nie będą zwalniane lecz niepotrzebnie przechowywane.

Co można zrobić:

  1. logować wszystkie dane liczbowe idące do drawImage do jakiejś dużej tablicy, a po dojściu do jej końca zatrzymać aplet i przejrzeć lub zrzucić te dane.
  2. Napakować wszystkie możliwe warunki poprawnego zadziałania drawImage do asercji
  3. Odpalić aplet w oknie traktując go jako panel i sprawdzić jak wtedy się to wszystko zachowuje (trzeba napisać kilkanaście wierszy kodu, żeby to zadziałało).
  4. Wykosić obserwatory przez zamianę this na nulle.
  5. Sprawdzić stan pamięci (monitorować na bieżąco) - być może w pewnym momencie aplet zabiera jej za dużo i niektóre obiekty lub dane idą w maliny. Z tego co zauważyłem aplety dostają w większości przeglądarek nie więcej niż 95 MB całkowitej pamięci RAM do wykorzystania. Dla apletu, który bawi się obrazkami, to bardzo mało ponieważ już 40 średniej wielkości obrazków BufferedImage zapycha całą pamięć apletu. Można w tym celu spróbować łapać wyjątek OutOfMemoryError.
0

Dzięki za tak wyczerpujaca odp. choc i tak nic mi na razie nie pomogła. Jest to aplet gry memory.
Aplet działa, nie sypią się żadne błędy. Warunki tak jak pisałem są dobre. Tablica Talia[] przechowuje obiekty typu Image. Nawet podwojne buforowanie nie pomogło. zmienna wybrano i wybrano2 są zmieniane w trakcie klikniecia klawisza myszy na odpowiedni obraz.

Problem dotyczy następujących linii:
if(wybrano2>=0){

		//   Buffer.drawImage( Talia[wybrano] , 0,0 ,100 ,100, this );
		   
		   Buffer.drawImage( Talia[wybrano2] , 0, 0 ,100 ,100, this );
		   Buffer.drawString("Wybrano karte nr."  + wybrano2, 10, 350);

Gdy odkomentuje Buffer.drawImage( Talia[wybrano] , 0,0 ,100 ,100, this ); to grafika zawsze sie zaladuje, ale nie ta ktora bym chcial.

Buffer.drawString("Wybrano karte nr." + wybrano2, 10, 350); zawsze pokazuje prawidlowy indeks tablicy. Uwaga i co dziwne zawsze sie prawidlowo wykona ta funkcja! Dzwieki ktore są wewnatrz tez prawidlowo sa odtwarzane.

Zrobiłem wiele testów i wynika z nich mianowicie cos takiego:
Gdy wybrano2==wybrano Grafika zawsze sie wyswietli, natomiast gdy wybrano2=!wybrano juz nie zawsze i nie wiem od czego to zalezy. Tak jakby nie zdarzyl zaladować do Buffor'a (Graphics) grafiki i przeszedl do wykonywania kolejnej funkcji. Dziwi mnie takie zachowanie i po klikaniu w karty i odkrywaniu karty odslaniaja sie w 90% prawidlowo, ale nie zawsze laduje sie jedna z kart. Błąd wynikający z ładowania 2 karty pojawia się w róznych chwilach i nie zalezy od żadnej ze zmiennych (tak przynajmniej mi się wydaje). Zawsze Od razu po uruchomieniu programu problem sie pojawia (przy pierwszym odslonieciu kart), natomiast pozniej juz mozna grac dalej az do napotkania ponownie tego bledu.

Funkcja rysująca:

	public void update(Graphics arg0) {
	
			paint(arg0);				
		 
			for (int i=0;i<ilosckart;i++){
				if (i==wybrano2)continue;
				if (i==wybrano)continue;
				Buffer.drawImage( karta , rect[i].x ,rect[i].y ,rect[i].width ,rect[i].height, this);
			}
						
			if(wybrano>=0){
				Buffer.drawImage( Talia[wybrano] , rect[wybrano].x ,rect[wybrano].y ,rect[wybrano].width ,rect[wybrano].height,this);
				  //arg0.drawString("Wybrano karte nr." + wybrano, 10, 350);	
				
				   
			}
				
			
			
			
		   if(wybrano2>=0){    
		
			//   Buffer.drawImage( Talia[wybrano] , 0,0 ,100 ,100, this );
			   
			   Buffer.drawImage( Talia[wybrano2] , 0, 0 ,100 ,100, this );
			   Buffer.drawString("Wybrano karte nr."  + wybrano2, 10, 350);
			  
				int i,j;
					
					 for (i=0;i<ilosckart;i++){	
						 if(wybrano==pary[i])break;	 	 
					 }
					
					 for (j=0;j<ilosckart;j++){	
						 if(wybrano2==pary[j])break;	 	 
					 }
					 
				if(wybrano!=wybrano2){	 
					if((i%(ilosckart/2))==(j%(ilosckart/2))){
						 rect[wybrano].setSize(0, 0);
						 rect[wybrano2].setSize(0, 0);
						 trafienia++;
						 audiohorn.play();
						}
					else{
						pudla++;
						audiocrash.play();
					}
							
					wybrano=-1;
					wybrano2=-1;		
				}	
				

				uspij=true;

				
			}
				
		      	
			
			if(trafienia>=ilosckart/2){  koniec=true;
						Buffer.drawString("KONIEC GRY", 150, 200 );	
								repaint();
								
								try
								{
					                Thread.sleep(200); // metoda powoduje że program "śpi" przez sekundę (1000milisekund)
								} catch (InterruptedException e) {}	
								
							}	 

		arg0.drawImage(Offscreen,0,0,this);
			
		if(uspij==true){
			
			try
			{
                Thread.sleep(1000); // metoda powoduje że program "śpi" przez sekundę (1000milisekund)
                repaint();
			} catch (InterruptedException e) {}	
		
			uspij=false;
		}	
				
			
}		

Obsluga myszy:

public void mousePressed(MouseEvent arg0) {
		myszx = arg0.getX();
		myszy = arg0.getY();
		
		
		for(int i=0;i<ilosckart;i++){
		if (rect[i].contains(myszx, myszy))
		{
			
			if(wybrano<0){
				wybrano= i;
				repaint();
				}
		
			if(wybrano!=i){ //wybrano!=i
					wybrano2=i;
					repaint();
				}	

			break;
		}

	}
0

Gdy wybrano2==wybrano Grafika zawsze sie wyswietli, natomiast gdy wybrano2=!wybrano juz nie zawsze i nie wiem od czego to zalezy. Tak jakby nie zdarzyl zaladować do Buffor'a (Graphics) grafiki i przeszedl do wykonywania kolejnej funkcji.

No bo właśnie tak to działa w Javie. Obrazki wczytują się dopiero podczas operacji drawImage. Trzeba się upewniać, że obrazek już tam jest. Metoda ta jest asynchroniczna czyli zawsze natychmiast wraca z działania czy coś narysuje czy nie. Poczytaj dokładnie dokumentację drawImage.

0

To czy istnieje metoda/sposob na synchroniczne wyrysowanie, badz jak zaladowac grafike do pamieci?

1 użytkowników online, w tym zalogowanych: 0, gości: 1