2D-Grafik .GIF macht mir Probleme

Kayuke

Mitglied
Guten Tag, ich schreibe gerade ein 2D Sidescroller Helicopter spiel und hänge an folgendem Problem:

Wenn ich einen Gegner abschiesse soll dort eine Explosion die ich als .GIF habe erscheinen, ansich dachte ich absolut kein Problem, einfach in der paint Methode ein drawimage der .GIF an genau den Koordinaten wo der Gegner war.

Java:
	public void paint(Graphics g){
	
		super.paint(g);
		Graphics2D g2d = (Graphics2D) g;

		// Explosion
		if (gegner.tot)
		g2d.drawImage(exp, gegner.x, gegner.y, null);
	}

und oben habe ich es halt deklariert:
Java:
	ImageIcon n =  new ImageIcon(Frame.pfad+"ressourcen/img/game/explosion.gif");
	exp = n.getImage();

Nun ist es so, aus irgendeinem mir bisher nicht nachvollziehbarem Grund wird die Explosion nicht angezeigt. Ich habe testweise alles ausprobiert: Wenn ich direkt am anfang ohne das ein Gegner Tot ist einfach

Java:
g2d.drawImage(exp, 100, 100, null);

mache wird die Grafik einmal abgespielt und danach nicht mehr, obwohl die Paint Funktion die ganze Zeit aufgerufen wird. Nun hatte ich versucht das ich z.B. nach exp = n.getImage(); die Variable exp = null; setze und jedesmal bei einer Explosion sollte er die .gif neu laden aber es klappt einfach nicht :/
 
Überschreibe mal stat der paint()- die paintComponent()-Methode:
Java:
    protected void paintComponent(Graphics g){    
        super.paintComponent(g);
 
        // Explosion
        if (gegner.tot) {
           g.drawImage(exp, gegner.x, gegner.y, this);
        }
    }
 
kein Unterschied leider, ich habs halt ohne die if-Abfrage probiert, dann erscheint direkt am Anfang einmal die Explosion, danach kann er diese nicht mehr zeichnen warum auch immer.

Ich bin mal ein paar Funktionen durchgegangen und habe die Funktion:

Java:
getImageLoadStatus()

ausgetestet und mir ausgeben lassen, als Rückgabewert erhalte ich am Anfang eine 2, sobald das Bild aber agespielt wurde erhalte ich eine 8. Ich weiß nicht ob es hilfreich ist aber wollte es einfach mal erwähnen. Ich glaube ich muss das Bild iwie "reloaden" oder so aber ich weiß leider nicht wie :/ Ist eine .GIF ohne Endlosschleife.
 
es ist zwar richtig das GIF ein datenformat ist was animationen erlaubt ... allerdings müssen diese auch gezeichnet werden ...

der grund liegt im aufbau von GIF ...
die einzelnen ebenen der animation müssen geladen und dann im definierten interval gezeichnet werden ...
ich weis nicht ob java mit sowas von haus aus umgehen kann ... aber für animationen kann man auch etwas anderes verwenden ...

entweder einzel-bilder oder ein bild was man dann teilt ...

auf jeden fall musst du selbst die einzelnen teile zeichnen ... und das noch in einen game-loop einbauen .. naja ... keine leichte aufgabe ... aber einfach mal ein GIF nehmen dürfte wohl kaum funktionieren ...



btw : alles andere was du kennst was ein GIF "darstellen" kann verwendet auch solche algorithmen ... die halt die meta-daten und einzel-ebenen aus dem GIF lesen und dann in einem loop "abspielen" ... und das musst du halt selbst programmieren ... zumindest wüsste ich nicht das java das von haus aus so kann
 
huhu, also Java kann sehr wohl mit .GIF umgehen, als ich die Explosion mit einer Endlosschleife versehen hatte (also direkt in der .GIF eingestellt) explodierte es die ganze Zeit. Ich verstehe auch was du meinst und hatte mich daran versucht, habe die .GIF in Einzelbilder gemacht und wollte dann selber mit einer Schleife den Ablauf machen, leider hab ich das aber nicht hinbekommen. Das Problem ist das ich nicht weiß wie man genau den Abstand zwischen den Bildern macht (Zeitlich), die Explosion z.B. läuft bei 7 FPS und es sind 12 Bilder. Also bräuchte ich eine Pause von 170 Millisekunden zwischen den Bildern.

Als ich nach Pausen in Java gegoogelt habe kam ich zu dem Thema "Thread" und mit Threads habe ich mich leider noch nicht sehr viel auseinandergesetzt.
 
Sitze jetzt seit knapp 4 Stunden an dem einem Problem und hab keine Idee mehr was zu machen ist :/

Der Weihnachtsmann im Adventskalender ist halt ne .gif mit einer Endlosschleife, so klappts bei mir auch, aber wenn ich die Explosion aufrufe klappts nur einmal. Ich schaff es nicht das er die Grafik immer wieder neu lädt obwohl ich die Variablen ganz neu mache und auch eigtl. das Bild neu in die Variable lade bei jeder Explosion.
 
Werde ich machen, danke sehr 🙂
Das Problem ist jetzt etwas anders bzw. ich weiß wo das Problem ist, kenne aber keine Lösung:

Ich habe es bei Gegnern derzeit so, die Klasse Gegner hat den boolean wert isVisible und explode, und in meiner Paint steht drinne fals beim Gegner isVisible == true ist wird dieser aufm Bildschirm weiter gezeichnet. Wenn nicht also false und gleichzeitig auch gegner.explode noch auf false ist soll die Explosion gezeichnet werden und gegner.explode wird auf true gesetzt.

Das Problem ist das er das Bild wo der Gegner explodiert zeichnet aber nach 10 Millisekunden (beim nächsten zeichnen) schon sieht das gegner.explode auf true ist und ihn also nicht weiter zeichnet.

Mit dem Gegner.explode wollt ich halt prüfen welcher Gegner explodiert ist und welcher noch nicht, Problem ist halt jetzt das er erst gegner.explode auf true setzen soll, wenn die .gif einmal komplett abgespielt wurde. Da häng ich jetzt fest, vlt hast du dafür einen Tipp, ich schau solange weiter 🙂
Und danke für die ganze Bemühung 🙂)

[EDIT]Hmm das Problem ist jetzt doch wieder da das er es nur einmal zeichnet. Ich kriege eine Explosion hin, aber danach lädt er das Bild nicht von neu oder so :/

Also der erste Gegner explodiert, dannach wird die .gif nicht mehr gezeichnet oder abgespielt.[/EDIT]
 
@Lex
gut ... aber in deinem beispiel überlässt du swing das animieren einer "endlos"-gif ...
TO hat ja das problem das er alles selbst zeichnet ... und darauf war eher meine frage abgezielt ob java das dann so immer noch selbst auf die reihe bekommt ...
sicher .. ein einfaches adden als JComponent (oder was auch immer) sollte schon funktionieren ... bloß TO hat ja irgendwie das problem wenn die GIF eben nicht endlos ist (auch wenn ich bisher nicht wusste das man sowas einstellen kann) ...

daher kam ja auch die idee mit dem "selbst animieren" ...
 
Vor ImageIO konnte man Gifs noch so animieren.
Java:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;

import javax.swing.JFrame;
import javax.swing.JPanel;

public final class ImageViewer3
extends JPanel
{
	private static final long serialVersionUID = 1L;
	private Image toDraw;

	private ImageViewer3(Image img)
	{
		if(img == null) {
			throw new IllegalArgumentException("null image");
		}
		toDraw = img;
		do{
			setMaximumSize(new Dimension(img.getWidth(this), img.getHeight(this)));
			setMinimumSize(new Dimension(1, 1));
			setPreferredSize(getMaximumSize());
			setSize(getPreferredSize());
		} while(getWidth() < 1 || getHeight() < 1);
	}

	@Override
	public void paint(Graphics g)
	{
		g.setColor(getBackground());
		g.fillRect(0, 0, getWidth(), getHeight());
		g.drawImage(toDraw, 0, 0, getWidth(), getHeight(), this);
	}

	@Override
	public boolean imageUpdate(Image img, int infoflags, int x, int y, int w, int h) {
		if(super.imageUpdate(img, infoflags, x, y, w, h)) {
			repaint();
			return true;
		}
		return false;
	}

	public static void main(String[] args)
	{
		if(args == null || args.length == 0) {
			args = new String[] {"juhz.gif"};
		}
		if(args.length < 2) {
			args = new String[] {args[0]};
		}
		Image img = Toolkit.getDefaultToolkit().createImage(args[0]);
		final ImageViewer3 iv = new ImageViewer3(img);
		iv.setBackground(Color.GREEN);
		final JFrame f = new JFrame("ImageViewer: " + args[0]);
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		f.add(iv);
		f.pack();
		f.setVisible(true);
	}
}
Allerdings habe ich noch keine Möglichkeit gefunden, ein Gif nach genau einem Durchlauf zu stoppen und in "imageUpdate()" immer einen Timer implementiert.
Bei mehreren Animationen kann man in "imageUpdate()" z.B. eine "Map<Image, ImageValues>" verwalten und das KeySet dieser Map in den jeweiligen Paint-Methoden mit den zugehörigen ImageValues zeichnen. ImageValues kann neben den Koordinaten der Gifs z.B. auch Start- und Laufzeit der Animation beinhalten.
 
Hmm also ich hab eine Art gefunden wie ich es schaffe das er mir die .GIF einmal abspielt, diese hat auch keine Endlosschleife aber er zeichnet sie dannach nie wieder und das geht mir nicht in den Kopf :/

in en.killed wird System.currentTimeMillis() eingetragen sobald der Gegner stirbt. Da die Gif zum einmal abspielen 1,7 Sekunden braucht die +1700. Damit wirds einmal perfekt abgespielt aber bei jedem weiterem Gegner erscheint nichts mehr. Aus irgendeinem Grund holt sich ImageIcon n die .gif nicht mehr neu aus der Datei, bitte dringend um Hilfe, war schon lange nicht mehr so verzweifelt an einem Problem :/

(steht in der Paint Methode, klappt nur 1 mal :/)

en => Enemy

Java:
        if ((en.isAlive == false) && (en.explode == false))
        {
            ImageIcon n = new ImageIcon(Frame.pfad+"ressourcen/img/game/explosion.gif");
            if (System.currentTimeMillis() < (en.killed+1700)){	
            	g2d.drawImage(n.getImage(),en.getX(),en.getY(), null);
            }
            else
            {
            	en.explode = true;
            	n = null;
            }
        }
 
Das Problem ist er programmiert ganz anders, außerdem sehe ich bei dem Tutorial auch keine .GIF oder bewegliche Animation, bin gerade nochmal drüber geflogen und sehe nur eine Rakete die mit so einer Streifenanimation gemacht wurde. Ich möchte jetzt aber nicht mein ganzes Projekt von neu beginnen und so machen wie er, da ich schon eigtl. wirklich viel habe und es kann doch nicht sein das keiner eine Idee hat wie man eine .GIF ohne Endlosschleife die immer zu einem Zeitpunkt und nur einmal abgespielt wird bei mir implementieren kann.
 
Eine Idee habe ich noch...
Java:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;

import javax.swing.JFrame;
import javax.swing.JPanel;

import datatypes.DataType;
import datatypes.events.MediaEvent;
import datatypes.events.MediaEventListener;
import datatypes.graphics.Image;
import datatypes.interfaces.Playable;

public final class ImageViewer
extends JPanel
{
	private static final long serialVersionUID = 1L;
	private Image toDraw;

	private ImageViewer(Image img)
	{
		if(img == null) {
			throw new IllegalArgumentException("null image");
		}
		toDraw = img;
		if(img instanceof Playable) {
			final Playable p = (Playable) img;
			p.addMediaEventListener(new MediaEventListener() {
				@Override
				public void mediaUpdated(MediaEvent e) {
					// hier hat sich etwas am medium veraendert
					repaint();
				}

				@Override
				public void mediaStopped(MediaEvent e) {
					// hier wurde das medium gestartet
				}

				@Override
				public void mediaStarted(MediaEvent e) {
					// hier wurde das medium gestartet
				}

				@Override
				public void mediaReseted(MediaEvent e) {
					// hier ist das medium einmal durch
//					p.stop();
				}

				@Override
				public void mediaPaused(MediaEvent e) {
					// hier wurde das medium pausiert
				}
			});
			p.start();
		}
		setMaximumSize(new Dimension(img.getWidth(), img.getHeight()));
		setMinimumSize(new Dimension(1, 1));
		setPreferredSize(getMaximumSize());
		setSize(getPreferredSize());
	}

	@Override
	public void paint(Graphics g)
	{
		g.setColor(getBackground());
		g.fillRect(0, 0, getWidth(), getHeight());
		g.drawImage(toDraw, 0, 0, getWidth(), getHeight(), null);
	}

	public static void main(String[] args)
	{
		if(args == null || args.length == 0) {
			args = new String[] {"hase_i.gif"};
		}
		if(args.length < 2) {
			args = new String[] {args[0]};
		}
		Object obj = DataType.load(args[0]);
		if(!(obj instanceof Image)) {
			// Datei ist kein Bild (bzw. Animation oder Video)
			throw new IllegalArgumentException("file couldn' t be viewed");
		}
/*		if(!(obj instanceof Listenable)) {
			// Datei ist kein Sound
			throw new IllegalArgumentException("file couldn' t be viewed");
		} */
/*		if(!(obj instanceof Object3D)) {
			// Datei ist kein 3D-Objekt
			throw new IllegalArgumentException("file couldn' t be viewed");
		} */ // aso...
/*		Image img = DataType.load(args[0]);
 		// man kann Dateitypen auch direkt laden und eine ClassCastException riskieren. */
/*		Decoder decoder = DataType.scan(args[0]);
 		// man kann sie aber auch scannen, um den Dateityp zu erfahren. */
 		// das ganze geht mit String, File, URI und URL. */
		Image img = (Image) obj;
		final ImageViewer iv = new ImageViewer(img);
		iv.setBackground(Color.GREEN);
		final JFrame f = new JFrame("ImageViewer: " + args[0]);
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		f.add(iv);
		f.pack();
		f.setVisible(true);
	}
}
Dieses "KSKB" nutzt eine ältere Version meiner(!*) Datatypes Library (siehe Anhang), welche ausschliesslich in einer Oracle-VM (gerade noch mal mit V1_7_U9 kompiliert...) läuft, dafür aber auch alle durch Bilder, die eigentlich per ImageIO und AudioFiles die eigentlich per "javax.sound.sampled.spi" (z.B. JavaZoom) geladen werden unterstützt. Andere Dateitypen lassen sich (wie gewohnt per Modul) hinzufügen. Eine neuere Version, die selbiges für jedwede andere VM tut, ist angedacht, bringt aber einige weitere Probleme mit sich(!*).
[OT]"meiner" muss leider betont werden, denn eines der riesen Probleme ist das, dass meine Idee zwar mögl. von dem ein oder anderen bereits verstanden und für "gut" befunden wurde, jedoch keiner da ist, der genügend Zeit hat, nachzuvollziehen, wie ich das hinbekommen will (bzw. grösstenteils schon hinbekommen habe). Daraus folgt, ich bin immer noch "Einzelkämpfer" und schon mal angesichts der grossen Dateitypenflut dermaßen überfordert, dass ich kaum mit 'ner Dokumentation nachkomme (teilweise gab es schon mal eine, vor dem grossen Redesign).
Ein anderes Problem ist, wenn ich z.B. in Foren (dieses hier nicht ausgeschlossen) nachfrage, wie man in Java z.B. ein Bild dreht und man mich auf Java2D (fällt aus!) verweist. Deswegen muss ich mir passende Antworten darauf halt selber akribisch zusammen suchen und versuchen umzusetzen, was die Entwicklung nochmals verzögert.
Eines ist aber mal sicher. Wenn's fertig und veröffentlicht ist, erübrigen sich Fragen wie "wie lade ich dieses oder jenes Dateiformat in Java?" oder "Wie nutze ich dieses oder jenes Dateiformat in Java?" (ob Oracle, Dalvik, LWJGL, JOAL oder Blähtataig).[/OT]
 

Anhänge


Zurück
Oben