# Gif Animantionen lesen



## Tapsi (26. Nov 2008)

Ich habe da mal eine Frage. Ist es Möglich aus einem Gif eine Animation zu lesen um diese mit drawImage zu zeichnen ?
Es wäre schon eine enorme Hilfe wenn ich wüsste wie ich aus einer Gif mit 4 Einzelbildern , diese auslesen könnte...

Um die Animation im Fenster zu zeichnen muss man die 4 Einzelbilder immer nacheinander zeichnen , oder gibt es dafür eine Funktion ?


----------



## Quaxli (26. Nov 2008)

Üblicherweise nimmt man keine animierten GIF's sondern bastelt die Animation selbst. Ich habe die Erfahrung gemacht, daß animierte GIFS nicht immer ordentlich dargestellt werden.

Bei mir sieht das z. B. so aus:







Dabei lese ich beim Starten des Programms die Einzelbilder aus und habe in der entpsrechenden Klasse die Logik, die mir je nachdem die richtige Abfolge an Bildern anzeigt.


----------



## Tapsi (26. Nov 2008)

Okay danke , so hab ich es bis jetzt auch gemacht ^^


----------



## Titanpharao (28. Nov 2008)

Wie bastelst du die dann zusammen? Habe meine Animationen immer als Gif Any gehabt.
Bzw, gibts ein Fileformat was "halbtranspartent" etc unterstüzt? PNG glaube ich ja, aber finde in java sieht es wieder wie normal aus, alles oder nichts.


----------



## Tapsi (28. Nov 2008)

Also ich habe bis jetzt meine gif dateien mit InfanVie in Teile zerlegt und diese dann als Buffered images gespeichert.
Dann lasse ich sie in Java alle 20 ms wechselnd anzeigen.

Ich suche immernoch ne Möglichkeit direkt die Layer aus Gif files zu lesen ohne die praktisch zu zerfleddern  :cry:


----------



## Ark (28. Nov 2008)

@Tapsi: Und was passiert dann anderes? Wenn du ein animiertes GIF-Bild in den Speicher lädst, wird es genauso nur "zerlegt" vorgehalten.

Ark


----------



## mantax (28. Nov 2008)

Titanpharao hat gesagt.:
			
		

> Wie bastelst du die dann zusammen?...





			
				Tapsi hat gesagt.:
			
		

> ...
> Ich suche immernoch ne Möglichkeit direkt die Layer aus Gif files zu lesen ohne die praktisch zu zerfleddern  :cry:



Wenn ich Tapsi & Titanpharao richtig verstanden habe, dann suchen sie, so wie ich^^, ne Lösung, um die Bilder aus dem großen Zusammengesetzten auszuschneiden und richtig anzeigen zu lassen, ohne jeden Frame als einzelne Datei abspeichern zu müssen.

Ich hab mir schon Quaxli's Tutorial durchgelesen. Da wird ja auch genau das gemacht. Allerdings werde ich daraus nicht schlau   

Habe mich am CropImageFilter versucht, aber es funktioniert nicht.


Die Funktion drawPlayer() wird in paint() (also in der Hauptschleife) aufgerufen.

```
// Gekürzte Version!

import java.awt.*;
import java.awt.image.*;

public class Player {
  
  public int x;
  public int y;
  
  public int mouse_x;
  public int mouse_y;

  public boolean falling;
  public boolean jumping;


  private Image crosshair = Toolkit.getDefaultToolkit().getImage("images/crosshair.gif");
  private Image img = Toolkit.getDefaultToolkit().getImage("images/sprites.gif");
  private Image img2;

  public Player() {
    this.x = 32;
    this.y = 32;

    this.falling = false;
    this.jumping = false;
    
    this.mouse_x = 0;
    this.mouse_y = 0;
  }
  
  public void drawPlayer(Graphics g) {
     if(this.mouse_x < this.x) {
       if(this.jumping || this.falling) {
         img2 = Toolkit.getDefaultToolkit().createImage(new FilteredImageSource(img.getSource(), new CropImageFilter(0, 78, 22, 26)));
       } else {
         img2 = Toolkit.getDefaultToolkit().createImage(new FilteredImageSource(img.getSource(), new CropImageFilter(0, 0, 22, 26)));
       }
     } else {
       if(this.jumping || this.falling) {
         img2 = Toolkit.getDefaultToolkit().createImage(new FilteredImageSource(img.getSource(), new CropImageFilter(22, 78, 22, 26)));
       } else {
         img2 = Toolkit.getDefaultToolkit().createImage(new FilteredImageSource(img.getSource(), new CropImageFilter(22, 0, 22, 26)));
       }
     }

    g.drawImage(img2,this.x,this.y,null);
  }
}
```
Nun wird aber gar nichts angezeigt  ???:L 

Ich vermute, dass drawPlayer() mit dem Zerschneiden nicht nachkommt, also zu langsam ist. Denn wenn ich alle "crops" in drawPlayer() auskommentiere und das Bild schon im Konstruktor schneide und somit nur 1x "gecropt" wurde, funktionierts. :x 

Könnte ich mit meiner Annahme Recht haben? Und wenn ja, was kann ich besser machen?
Danke im Vorraus  :wink:


----------



## Quaxli (29. Nov 2008)

Ich fahre ganz gut mit folgender Methode (ich beziehe mich mal auf den Hubschrauber oben):

- Pro Sprite lege ich die Grafiken so ab, wie oben gezeigt. Ein Bild für alle Sprites wäre mir zu viel Gefrickel, vor allem, wenn man im Nachhinein noch was ändern will.

- Außerdem habe ich mir eine SpriteLib geschnitzt, welche die Bilder lesen kann und je nachdem was ich als Anzahl Spalten und Anzahl Zeilen beim Methodenaufruf mitgebe, mir das Bild in Sub-Images zerlegt und als Array von BufferedImages zurück liefert. Ein Methodenaufruf sieht dann in etwa so aus: 

   BufferedImage[] helipic = SpriteLib.getImage("path/....", 4,6); 

Wobei ich diesen Methodenaufruf meist in den Konstruktor meiner SpriteKlasse packe, die sowieso ein BufferedImage bzw. ein Array davon erwartet

- die Animation steuere ich dann komplett im eigentlichen Objekt. Dabei setze ich z. b. min/max-Grenzen für die
Animation von - bis fest. Wenn das Ding also nach links gesteuert wird, setzt ein Methodenaufruf die Zähler auf 0 - 3, so daß nur die ersten 4 Bilder des Arrays für die Animation herangezogen werden, eben die auf denen der Hubschrauber nach links fliegt.

- in der paint-Methode selbst ist relativ wenig Code. Eigentlich wird nur das Bild gezeichnet, daß dem aktuellen Animations-Counter entspricht. Den Animations-Counter wiederum überprüfe ich in einer Methode namens doLogic(), die alle meine Sprites haben, um dort solche und weitere Vorgaben zu prüfen. Hier wird dann u. a. geprüft, ob die voreingestellte Zeit in ms für die Animation um ist. Wenn ja, wird der Zähler erhöht, bzw auf den Startwerrt gesetzt, wenn er das aktuelle Maximum überschritten hat. 

Wie man es letztlich macht, ist eine Frage, wie gut es funktioniert und wie man selbst damit zurecht kommt. Es gilt aber grundsätzlich, daß man relativ wenig Code ausführen sollte, bzw. Code der wenig aufwändig ist. Damit gehören in der Regel alle Modifikationen, die mit dem Erzeugen, Zerlegen oder Abändern von Grafiken zu tun haben, nicht in eine Methode, die während des Spiels aufgerufen wird. Hierfür ist es z. B. ggeignet eine Initialisations-Methode zu haben, die zu Anfang diese zeitaufwändigen Arbeiten übernimmt. Hier gibt es sicher auch Ausnahmen, die die Regel bestätigen, aber meist ist das so. Warum wohl haben viele Spiele, die man als Flash oder was auch immer im Netz findet, einen Fortschrittsbalken, der nach dem Spielstart angezeigt wird?


----------



## mantax (29. Nov 2008)

Hab das ganze jetzt einfach anders gelöst:

Ich benutze nicht subImage oder CropImageFilter, sonder drawImage mit den Parameter d1-d4 und s1-4

siehe Doku

nun klappt alles wunderbar und ich muss nicht jeden Frame als einzelnes Bild abspeichern! :wink:


----------

