java.awt.image.RasterFormatException beim erstellen von Subimages

Hey!

Ich bastle gerade immer noch an meinem neuen Game, bin aber auf ein paar Probleme gestoßen…

Ich verwende folgende Methode um Kollisionen zu berechnen (Habe ich noch von Quaxli da sie sich als nützlich und gut funktionierend erwiesen hat):

	public boolean checkOpaqueColorCollisions(Entity s){

		Rectangle2D.Double cut = (Double) this.createIntersection(s);
		if ((cut.width<1) || (cut.height<1)){
			return false;
		}

		Rectangle2D.Double sub_me = getSubRec(this, cut);
		Rectangle2D.Double sub_him = getSubRec(s, cut);
		
		System.out.print("currentpic: width "+pics[currentpic].getWidth()+" height "+pics[currentpic].getHeight()+" | sub_him: x "+sub_him.x+" y "+sub_him.y+" width "+sub_him.width+" height "+sub_him.height);

		BufferedImage img_me = pics[currentpic].getSubimage((int)sub_me.x, (int) sub_me.y, (int) sub_me.width, (int) sub_me.height );
		BufferedImage img_him = s.pics[s.currentpic].getSubimage((int)sub_him.x, (int) sub_him.y, (int) sub_him.width, (int) sub_him.height );

		for (int i = 0; i<img_me.getWidth(); i++){

			for (int n = 0; n<img_him.getHeight(); n++){

				int rgb1 = img_me.getRGB(i, n);
				int rgb2 = img_him.getRGB(i, n);

				if (isOpaque(rgb1 )&& isOpaque(rgb2)){
					return true;
				}


			}

		}
		return false;

	}```


Diese Methode hat bisher auch immer funktioniert.... aber bei meinem neusten Charakter bekomme ich dort eine Fehlermeldung ausgedruckt:



Fehlermeldung
[spoiler]Exception in thread "Thread-3" java.awt.image.RasterFormatException: (y + height) is outside of Raster
	at sun.awt.image.ByteInterleavedRaster.createWritableChild(Unknown Source)
	at java.awt.image.BufferedImage.getSubimage(Unknown Source)
	at org.black_ixx.manawar.entities.Entity.checkOpaqueColorCollisions(Entity.java:161)
	at org.black_ixx.manawar.managers.EntityManager.doLogic(EntityManager.java:69)
	at org.black_ixx.manawar.CoreTicking.run(CoreTicking.java:38)
	at java.lang.Thread.run(Unknown Source)[/spoiler]




Ich habe keine Ahnung was hier das Problem sein kann...

Infos die geprintet wurden:
currentpic: 
width 60 
height 119
sub_him: 
x 107.04909539999983 
y 52.0 
width 2.9509046000001717
height 119.0


Dieser Fehler passiert nur, wenn der "Shadow" Charakter auf dem Boden steht.

Hier funktioniert alles problemlos:


Error, Spiel crasht:



Wisst ihr vielleicht woran das liegen könnte?

*** Edit ***

Wenn ich die Rects bei den "Kollisionen" zeichnen lasse sieht das in etwa so aus:



(Hier: "Kollision" mit Kiste und Spieler)

Nur kurz draufgeschaut: Die Exception kommt aus einer der beiden getRGB-Zeilen?
Waren bisher vielleicht alle Bilder gleich groß, und das neue ist jetzt größer oder kleiner? :wink:

[QUOTE=Marco13]Nur kurz draufgeschaut: Die Exception kommt aus einer der beiden getRGB-Zeilen?
Waren bisher vielleicht alle Bilder gleich groß, und das neue ist jetzt größer oder kleiner? ;)[/QUOTE]

Danke für die Antwort :slight_smile:

Das hier ist die Fehlerquelle:
BufferedImage img_him = s.pics[s.currentpic].getSubimage((int)sub_him.x, (int) sub_him.y, (int) sub_him.width, (int) sub_him.height );

und jap: Das Spiel crasht immer sobald ein Bild mit einer anderen Größe gezeichnet wird.

Der Assassine Charakter hat eine „Schlag-Animation“ die in einer extra PNG gespeichert ist und ganz am Anfang zusammen mit den Lauf/Jump Animationen in eine Array „geladen“ wird. Diese „Schlag-Animation“ hat eine andere Größe da sie mehr Platz benötigt und ich zu faul ware alle alten Animationen zu erweitern (+ ich habe meine Rand-Markierungen schon gelöscht)

Hast du schon eine Idee/Lösung? :open_mouth:

Die Ausgabe dort bezieht sich ja auf das Bild von “this”. Vielleicht würde sowas schon helfen:

System.out.print("currentpic:");
System.out.println("width  "+s.pics[s.currentpic].getWidth()); // Bei s.pics gibt's ein Problem (nicht bei 'pics')
System.out.println("height "+s.pics[s.currentpic].getHeight());
System.out.println("sub_him.x "+sub_him.x);
System.out.println("sub_him.y "+sub_him.y);
System.out.println("sub_him.width "+sub_him.width);
System.out.println("sub_him.height "+sub_him.height);
BufferedImage img_him = s.pics[s.currentpic].getSubimage((int)sub_him.x, (int) sub_him.y, (int) sub_him.width, (int) sub_him.height );

[QUOTE=Marco13]Die Ausgabe dort bezieht sich ja auf das Bild von “this”. Vielleicht würde sowas schon helfen:

System.out.print("currentpic:");
System.out.println("width  "+s.pics[s.currentpic].getWidth()); // Bei s.pics gibt's ein Problem (nicht bei 'pics')
System.out.println("height "+s.pics[s.currentpic].getHeight());
System.out.println("sub_him.x "+sub_him.x);
System.out.println("sub_him.y "+sub_him.y);
System.out.println("sub_him.width "+sub_him.width);
System.out.println("sub_him.height "+sub_him.height);
BufferedImage img_him = s.pics[s.currentpic].getSubimage((int)sub_him.x, (int) sub_him.y, (int) sub_him.width, (int) sub_him.height );
```[/QUOTE]


Ich habe jetzt alles mögliche geprüft (zb. ob vielleicht currentpic verändert wird während die Methode ausgeführt wird) aber leider ohne Erfolg.



Ergebnisse
[spoiler]
currentpic: width  110
height 171
sub_him.x 107.94319450000023
sub_him.y 52.0
sub_him.width 2.0568054999997685
sub_him.height 119.0
currentpic: width  110
height 171
sub_him.x 107.94319450000023
sub_him.y 52.0
sub_him.width 2.0568054999997685
sub_him.height 119.0
currentpic: width  110
height 171
sub_him.x 107.94319450000023
sub_him.y 52.0
sub_him.width 2.0568054999997685
sub_him.height 119.0
Exception in thread "Thread-3" java.awt.image.RasterFormatException: (y + height) is outside of Raster
	at sun.awt.image.ByteInterleavedRaster.createWritableChild(Unknown Source)
	at java.awt.image.BufferedImage.getSubimage(Unknown Source)
	at org.black_ixx.manawar.entities.Entity.checkOpaqueColorCollisions(Entity.java:178)
	at org.black_ixx.manawar.managers.EntityManager.doLogic(EntityManager.java:70)
	at org.black_ixx.manawar.CoreTicking.run(CoreTicking.java:38)
	at java.lang.Thread.run(Unknown Source)
currentpic: width  140
height 170
sub_him.x 107.94319450000023
sub_him.y 52.0
sub_him.width 2.0568054999997685
sub_him.height 119.0[/spoiler]


Klar ich könnte die Größen aller Bilder mit viel Mühe anpassen, aber es gibt doch auch eine bessere Lösung oder?

Ich habe auch eine mögliche Fehlerquelle gefunde: Es wird doch bei dem Konstruktor eines Objektes die Größe des Rects anhand des ersten Bildes festgelegt (Width, Height). Später wenn das Bild verändert wird bleibt diese Größe gleich.
Also habe ich diesen Code bei ComputeAnimation hinzugefügt:
		width=pics[currentpic].getWidth();
		height=pics[currentpic].getHeight();```

doch der selbe Fehler tritt immer noch auf.

*** Edit ***

Das hier ist das Problem:

Zuerst:
sub_him.y 52.0
sub_him.height 119.0

height 171

Dann:

sub_him.y 52.0
sub_him.height 119.0

height 170

Doch wie kann ich das verhindern? Ich müsste dazu entweder sub_him.y/sub_him.height um 1 verkleinern bzw height um 1 vergrößern… Ich versuche mal das Bild zu bearbeiten. Vielleicht geht es ja ganz einfach wenn ich es nur um einen Pixel vergrößern muss.

Du müsstest aus den ganzen Werten eigentlich nur zwei Rechtangles machen und dann die SubImages aus deren Intersection erstellen. Wenn diese Intersection leer ist, brauchst du die weitere Kollisionsabfrage nichtmal mehr durchführen.

Behoben: Habe das Bild um 1 Pixel erweitert…

Hm. Was genau du damit meinst, weiß ich nicht … und … durch Draufschauen ist es schwer zu sagen, zumindest ergibt
sub_him.x 107.94319450000023

  • sub_him.width 2.0568054999997685
    = 110
    was eben gerade 1 mehr als der maximale Wert von 109 (bei einer Breite von 110) ist. Im Zweifelsfall könnte man vermutlich auch an einer geeigneten Stelle ein
    width = Math.min(allowedWidth, width);
    einfügen…

[QUOTE=Marco13]Hm. Was genau du damit meinst, weiß ich nicht … und … durch Draufschauen ist es schwer zu sagen, zumindest ergibt
sub_him.x 107.94319450000023

  • sub_him.width 2.0568054999997685
    = 110
    was eben gerade 1 mehr als der maximale Wert von 109 (bei einer Breite von 110) ist. Im Zweifelsfall könnte man vermutlich auch an einer geeigneten Stelle ein
    width = Math.min(allowedWidth, width);
    einfügen…[/QUOTE]

Gemeint habe ich:

"sub_him.y 52.0
sub_him.height 119.0

height 170"

Das Teil-Bild beginnt bei Y 52 von dem Bild und ist 119 Pixel hoch. 52 + 119 ergibt 171. Und genau das war mein Problem. Alle Bilder waren 171 groß bis auf eine kleine Bildreihe.
Als diese Reihe aufgetaucht ist wollte Java wieder ein Teilbild erstellen welches bei Y 52 beginnt und 119 Pixel hoch ist. Da die Bildreihe aber nur 170 hoch war ist Java gecrashed.

Ich habe in den letzten Tagen sehr sehr viel Neues gelernt und ich werde mein ganzes Game in der nächsten Woche neu und besser schreiben.
Dh. ich werde zum Beispiel eine Klasse für “GameModes” schreiben und für jeden einzelnen GameMode eine solche Klasse laden bzw alle Einstellungen des GameModes in diese Klasse packen. Menu und Buttons gehören auch dazu.
Momentan habe ich nämlich alles etwas “hingemurkst” und sehr viel in die Main Klasse gepackt da ich am Anfang mit nur einem einzigen GameMode gerechnet habe.
Sobald mein Spiel fertig ist werde ich es hier auch zum Download bereitstellen.

Mein Bruder und ein paar Freunde haben auch gefallen am Erstellen von Animationen gefunden und helfen mir ein kleines bisschen. Ich habe für sie extra ein kleines Programm erstellt mit dem man die eigenen Animationen schnell abspielen und testen kann:

Dieses Programm werde ich in den nächsten Tagen auch hier in einem Thread veröffentlichen.

Ich frag’ mich ja schon, wo das überhaupt herkommt - also, sollten sich diese Sachen hier

        Rectangle2D.Double cut = (Double) this.createIntersection(s);
...
        Rectangle2D.Double sub_me = getSubRec(this, cut);
        Rectangle2D.Double sub_him = getSubRec(s, cut);

nicht indirekt auf die Bilder beziehen, und demnach dort gar keine ungültig-großen Werte drin vorkommen?!

[QUOTE=Marco13]Ich frag’ mich ja schon, wo das überhaupt herkommt - also, sollten sich diese Sachen hier

        Rectangle2D.Double cut = (Double) this.createIntersection(s);
...
        Rectangle2D.Double sub_me = getSubRec(this, cut);
        Rectangle2D.Double sub_him = getSubRec(s, cut);

nicht indirekt auf die Bilder beziehen, und demnach dort gar keine ungültig-großen Werte drin vorkommen?![/QUOTE]

Ich habe den genauen Grund leider auch nicht herausgefunden aber ich habe schon einen “Anhaltspunkt”:
“this” ist ein Rectangle2D.Double welches eine eigene Größe und eigene Maße hat. Und genau diese werden bei der Methode auch verwendet.
Ich update diese Maße (height und width) zwar jedes Mal wenn das Bild gewechselt wird aber irgendeinen anderer Fehler könnte da schon noch stecken…