Sprite Animation

Selman

Neues Mitglied
Hi

Kann mir bitte jemand erklären wie genau eine Sprite Animation funktioniert??

Versuche mir Java bei zu bringen indem ich ein Spiel "Programmiere". Versuche nun meine Spielfigur zu animieren .Ich hab mir schon alles mögliche auf Youtube angeguckt.Nur krieg ich es leider nicht in meine Birne rein :(.

Ich verstehe ja das aus einem Bild nur bestimmte "teile" angezeigt werden ich verstehe aber den restlichen benötigten Code nicht.Hänge seit ewig dran. Wäre nett wenn mir das jemand schritt für schritt erklären könnte .Am besten für ganz blöde :rolleyes:

Danke
 

RalleYTN

Bekanntes Mitglied
Du hast ein Bild mit mehreren Frames.

capguy-walk.png


Nehmen wir einfach mal an, dass alle diese Subbilder, die einen Frame darstellen eine einheitliche Größe haben.
Das erste was man tun muss, ist das Bild zu laden.
Java:
BufferedImage atlas = ImageIO.read(<bild ressource>);
Als nächstes müssen wir dieses zerlegen.
In dem Beispielbild gibt es acht Frames in einer Reihe.
Also erhalten wir die Breite eines Subbildes, indem wir die Breite des Bildes durch acht teilen.
Die Höhe wäre einfach die Höhe des Bildes.
Hätten wir zwei Zeilen, dann müssten wir die Höhe des Bildes durch zwei teilen.
Java:
final int NUMBER_OF_FRAMES_ON_WIDTH = 8; // Spalten
final int NUMBER_OF_FRAMES_ON_HEIGHT = 1; // Zeilen
BufferedImage[] frames = new BufferedImage[NUMBER_OF_FRAMES_ON_WIDTH * NUMBER_OF_FRAMES_ON_HEIGHT];
int frameWidth = atlas.getWidth() / NUMBER_OF_FRAMES_ON_WIDTH;
int frameHeight = atlas.getHeight() / NUMBER_OF_FRAMES_ON_HEIGHT;
int currentFrameIndex = 0;

// Iteriere über den Atlas.
// X und Y sind die Koordinaten im Atlas in Pixel
for(int x = 0; x < atlas.getWidth(); x += frameWidth) {
    for(int y = 0; y < atlas.getHeight(); y += frameHeight) {
        frames[currentFrameIndex] = atlas.getSubImage(x, y, frameWidth, frameHeight);
        currentFrameIndex++;
    }
}
Jetzt haben wir sämtliche Frames im Array "frames" gespeichert.
Alles was jetzt noch bleibt ist das ganze zu animieren.
Ich nehme mir da gerne noch eine weitere Textdatei.
Die Datei gibt dann an, welcher Frame wie lange angezeigt werden soll.
Links steht immer der Index des Frames, dann kommt ein Seperator gefolgt von den Millisekunden die der Frame angezeigt werden soll.

Beispiel:
Code:
0|1000
2|500
3|2000
2|500
1|300

Hier erstellen wir noch mal schnell eine Klasse Animation.

Java:
public class Animation {
    private int currentFrameIndex; // Index des Frames, der angezeigt werden soll, NICHT MIT DEM FRAME INDEX ZUM ZERLEGEN  DES BILDES VERWECHSELN
    private int currentAnimationIndex;  // Aktuelle Zeile in unserer Beschreibungsdatei
    private BufferedImage[] frames;
    private List<Integer> indices;
    private List<Long> animationTimes;
    private boolean running; // true, wenn die animation gerade läuft.

    public Animation(BufferedImage atlas, framesOnWidth, framesOnHeight, File animationDescriptor)) {
        <hier kommt der ganze code den wir schon hatten. man muss ihn nur noch auf die neuen Variablennamen umstellen um richtig hier reinzupassen>

        this.indices = new ArrayList<>(); // Enthält die Reihenfolge, in der wir alles animieren wollen
        this.animationTimes = new ArrayList<>(); // Wie lange soll ein Frame gezeichnet werden

        // Lese die Datei ein mit der wir die Animation definieren können.
        try(BufferedReader reader = new BufferedReader(new FileReader(animationDescriptor))) {
            String line = null;
            while((line = reader.readLine) != null) {
                String[] parts = line.split("\\|");  // Teile die Zeile am Seperator. Für '|' müssen noch '\\' eingefügt werden, weil RegEx
                this.indices.add(Integer.parseInt(parts[0]));
                this.animationTimes.add(Long.parseLong(parts[1]));
            }
        } catch(Exception exception) {
            // Ausnahmebehandlung
        }
    }

    // Um die Animation zu starten
    public void start() {
        this.running = true;
        // Lambda für einen Runnable
        new Thread(() -> {
            while(running) {
                java.util.Timer.schedule(() -> {
                    currentAnimationIndex++;

                    // Wir dürfen natürlich nicht vergessen, die Animation zurückzusetzen, sobald sie einmal durchgelaufen ist.
                    if(currentAnimationIndex >= indices.size()) {
                         currentAnimationIndex = 0;
                    }

                    currentFrameIndex = indices.get(currentAnimationIndex);
                }, animationTimes.get(currentAnimationIndex))
            }
        }).start();
    }

    public void stop() {
        this.running = false;

       // Das hier weglassen um die Animation zu pausieren
        this.currentAnimationIndex = 0;
        this.currentFrameIndex = 0;
    }

    // Diese Methode musst du dann Aufrufen um das Bild zu erhalten, welches du zeichen musst.
    public BufferedImage getCurrentFrame() {
        return this.frames[this.currentFrameIndex];
    }
}

Alles was du jetzt noch machen müsstest ist eine neues Animation Objekt erstellen, die Animation starten und dann in der paintComponent(Graphics) Methode den aktuellen Frame malen.

WARNUNG!
Das ist alles ungetesteter Code den ich mal eben so hingeschmiert habe.
 
Zuletzt bearbeitet:

Selman

Neues Mitglied
@RalleYTN
Danke . Ich werde es mir ein paar mal durch lesen.

Würdest du sagen, dass es der komplizierteste Teil ist??
Mein Ziel ist es später einfache Android Apps(2D Spiele) zu entwickeln.
 

RalleYTN

Bekanntes Mitglied

Ähnliche Java Themen

Neue Themen


Oben