在本文中,我將解釋如何在JavaFX中編寫自定義動畫,以及如何使用這種方法為Sprite動畫創建類。 (這對我在33rd Conference上的會議來說也是一種好習慣。我計劃在短短一個小時內用JavaFX編寫一個游戲。這將很有趣!)
![]() |
運動中的馬 |
有很多非常好的文章介紹了預定義的過渡(TranslateTransition,RotateTransition等)和時間表。 在大多數情況下,這些方法是足夠的,但在某些情況下,只需要更大的靈活性即可。 這就是Transition類開始起作用的時候,可以擴展該類以定義自定義動畫。 要通過擴展Transition編寫自己的動畫類,需要兩個步驟:
- 指定一個周期的持續時間
- 實現interpolate()方法
一個周期的持續時間
您可以通過調用受保護的方法setCycleDuration()來設置周期的持續時間。 在大多數情況下,持續時間是固定的(如果動畫僅使用一次)或可由用戶配置。 JavaFX運行時中幾乎所有預定義的轉換都屬于第二類。 他們通過duration屬性公開了周期的持續時間,您可能也想在您的課程中做到這一點。 在極少數情況下,循環的持續時間取決于其他值。 例如,SequentialTransition和ParallelTransition的持續時間取決于其子代的持續時間。
您可以隨意更改循環持續時間,但是請注意,它不會影響當前正在運行的動畫。 只有在動畫停止并重新開始之后,才考慮新的循環持續時間。
interpolate()方法
interpolate()方法是抽象的,需要重寫。 它定義了動畫的實際行為。 播放動畫時,運行時在每幀中調用interpolate()方法。 傳入值frac,0.0到1.0之間的雙精度值(包括兩端值),用于指定當前位置。 值0.0標記動畫的開始,值1.0標記動畫的結束。 之間的任何值都定義相對位置。 請注意,計算frac的值時已經考慮了可能的內插器。
類SpriteAnimation
為了演示如何定義自定義過渡,我們將看一個允許我們制作Sprite動畫的類。 它會拍攝具有幾幀的圖像,然后將視口隨時間從一幀移到另一幀。 我們將用Eadweard Muybridge著名的“運動中的馬”測試這一節課。 聊夠了,這里是代碼:
package sandboxfx;import javafx.animation.Interpolator;
import javafx.animation.Transition;
import javafx.geometry.Rectangle2D;
import javafx.scene.image.ImageView;
import javafx.util.Duration;public class SpriteAnimation extends Transition {private final ImageView imageView;private final int count;private final int columns;private final int offsetX;private final int offsetY;private final int width;private final int height;private int lastIndex;public SpriteAnimation(ImageView imageView, Duration duration, int count, int columns,int offsetX, int offsetY,int width, int height) {this.imageView = imageView;this.count = count;this.columns = columns;this.offsetX = offsetX;this.offsetY = offsetY;this.width = width;this.height = height;setCycleDuration(duration);setInterpolator(Interpolator.LINEAR);}protected void interpolate(double k) {final int index = Math.min((int) Math.floor(k * count), count - 1);if (index != lastIndex) {final int x = (index % columns) * width + offsetX;final int y = (index / columns) * height + offsetY;imageView.setViewport(new Rectangle2D(x, y, width, height));lastIndex = index;}}
}
為了簡單起見,此示例類僅接受構造函數中的所有參數,不允許以后更改它們。 在大多數情況下,這就足夠了。
該類需要一個ImageView,一個周期的持續時間(即遍歷所有幀應花費的時間),幀數,列數(圖像中的一行中有多少幀),第一幀的偏移量以及所有幀的寬度和高度。 通過調用setCycleDuration()將整個周期的持續時間傳遞給超類,并存儲所有其他值。 作為構造函數的最后一步,將內插器設置為線性。 默認情況下,為所有過渡設置緩動插值器,因為通常這會產生最佳效果。 但是在我們的例子中,我們希望以相同的速度遍歷所有幀,并且緩和插值器看起來很奇怪。 interpolate()方法采用傳入的值并計算當前需要顯示的幀。 如果自上次調用interpolate()以來它發生了變化,則將計算新幀的位置,并相應地設置ImageView的視口。 而已。
運動中的馬
為了演示SpriteAnimation類,我們將對“運動中的馬”進行動畫處理。 做到這一點的代碼很簡單,大部分工作已經完成。 它創建一個將視口設置為第一幀的ImageView,并實例化SpriteAnimation類。 參數僅是估計值,您可能需要對其進行一些調整。
package sandboxfx;import javafx.animation.Animation;
import javafx.application.Application;
import javafx.geometry.Rectangle2D;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.stage.Stage;
import javafx.util.Duration;public class SandboxFX extends Application {private static final Image IMAGE = new Image("http://upload.wikimedia.org/wikipedia/commons/7/73/The_Horse_in_Motion.jpg");private static final int COLUMNS = 4;private static final int COUNT = 10;private static final int OFFSET_X = 18;private static final int OFFSET_Y = 25;private static final int WIDTH = 374;private static final int HEIGHT = 243;public static void main(String[] args) {launch(args);}public void start(Stage primaryStage) {primaryStage.setTitle("The Horse in Motion");final ImageView imageView = new ImageView(IMAGE);imageView.setViewport(new Rectangle2D(OFFSET_X, OFFSET_Y, WIDTH, HEIGHT));final Animation animation = new SpriteAnimation(imageView,Duration.millis(1000),COUNT, COLUMNS,OFFSET_X, OFFSET_Y,WIDTH, HEIGHT);animation.setCycleCount(Animation.INDEFINITE);animation.play();primaryStage.setScene(new Scene(new Group(imageView)));primaryStage.show();}
}
結論
通過擴展Transition類來定義自己的動畫非常簡單。 但是,這是一種非常強大的方法,因為以這種方式創建的動畫具有常規動畫所具有的所有功能。 例如,您可以通過更改速率來越來越慢地播放它,甚至可以向后播放它。 您可以循環運行它,也可以在ParallelTransition和SequentialTransition中使用它來創建更復雜的動畫。
參考: JCG合作伙伴 Michael Heinrichs 使用JavaFX創建Sprite動畫 ? 在Mike的Blog上 。
翻譯自: https://www.javacodegeeks.com/2012/03/javafx-creating-sprite-animation.html