JavaFX z Arią - powrót do strony głównej

Sprite animations on JavaFX Canvas

Animacje wykorzystujące arkusze duszków (sprite sheets) są najczęściej używane na stronach internetowych. Wczytywanie znacznej liczby małych obrazków wymaga sporej ilości operacji i/o, a użycie tej techniki pozwala na przyśpieszenie ładowania się strony.
Tutaj dla wprawy pokazuję użycie takiej animacji na JavaFX Canvas.

Układ modułu
Układ modułu
Sprite sheet z biegnącym chłopcem
Sprite sheet (rys. Maciej Krzywicki)
module-info.java
module m2serialanimations {

    requires jdk.jsobject;

    requires java.desktop;
    requires java.logging;
    requires java.net.http;
    requires java.scripting;
    requires java.sql;

    requires javafx.base;
    requires javafx.controls;
    requires javafx.graphics;
    requires javafx.fxml;
    requires javafx.media;
    requires javafx.swing;
    requires javafx.swt;
    requires javafx.web;

    exports p1_javafx_animations to javafx.graphics, javafx.web;
    exports p2_sprite_animations to javafx.graphics, javafx.web;
    exports utils to javafx.graphics, javafx.web;



}
Klasa Animation_Sprite_Canvas
package p2_sprite_animations;

import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.image.Image;
import javafx.scene.image.PixelReader;
import javafx.scene.image.WritableImage;
import javafx.stage.Stage;
import utils.AnimUtil;

public class Animation_Sprite_Canvas extends Application {
    private GraphicsContext gc;
    private Image image;
    private PixelReader pr;
    private long[] durs;
    private final int w = 98;
    private final int h = 137;
    @Override
    public void init(){
        Image image = new Image("m2serialanimations/src/resources/bieg2.png");
        durs = AnimUtil.fill4(180, 8);
        pr = image.getPixelReader();
    }
    @Override
    public void start(Stage stage) {
        try {
            Group root = new Group();
            Canvas canvas = new Canvas(w, h);
            gc = canvas.getGraphicsContext2D();
            root.getChildren().add(canvas);
            Scene scene = new Scene(root);
            stage.setScene(scene);
            stage.setTitle("Sprite Animation");
            stage.setOnCloseRequest(e-> Platform.exit());
            stage.show();
            AnimationTimer timer = new SpriteTimer();
            timer.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    private class SpriteTimer extends AnimationTimer {
       long start = System.currentTimeMillis();
        int counter = 0;
        @Override
        public void handle(long now) {
            long teraz = System.currentTimeMillis();
            long elapsed = teraz - start;
            if(elapsed > durs[counter]) {
                gc.clearRect(0, 0, w, h);
                WritableImage im = new WritableImage(pr, counter * w,0, w, h);
                gc.drawImage(im, 0, 0);
                counter++;
                if (counter > durs.length - 1) {
                    counter = 0;
                    start = System.currentTimeMillis();
                }
            }
        }
    }
}
Metoda AnimUtil.fill4()
 public static long[] fill4(long millis, int frames){
        long d = 0;
        long[] durs = new long[frames];
        for(int i =0; i< frames; i++){
            durs[i]= d;
            d += millis;
        }
        return durs;
    }

Po uruchomieniu klasy zobaczymy animację biegnącego w miejscu chłopca.

Obrazek biegnącego chłopca