2017-02-26 5 views
0

私はJavaFXを使い慣れていますが、オブジェクト指向のJavaをよく理解しています。次のプログラムは、2つの例の組み合わせです.1つは、アニメーションとシェイプを移動させ、もう1つは、マウスボタンでオブジェクトをアニメートします。機能の多くは私のニーズに応じて削除または変更されています。キー入力時にJavaFXでスプライトをアニメーション化

私は多くの例を検索しましたが、スプライトの移動とキープレスのアニメーションに関して完全に理解しているものは見つかりませんでした。私のプログラムでは、ゲームを作成するために適切なクラスを使用していないと確信しています私はそれが動作することができると確信しています。

printlnの機能を追加してアニメーションをテストしました。問題は、walkSouthアニメーションのKeyFrame部分が動作していない/再生していないようです。

、私の質問は:私は、スプライトシートのアニメーションを作成するために、さまざまなJavaFXのクラスを使用する必要があり

  1. このコードを簡単に機能させることができるので、JavaFXの仕組みをよりよく理解できます。ここで

メインクラスです。ここ

package testing; 

import javafx.animation.KeyFrame; 
import javafx.animation.Timeline; 
import javafx.application.Application; 
import javafx.scene.Parent; 
import javafx.scene.Scene; 
import javafx.scene.image.Image; 
import javafx.scene.layout.Pane; 
import javafx.stage.Stage; 
import javafx.util.Duration; 

public class Main extends Application { 

    private enum UserAction{ 
     NONE,NORTH,SOUTH; 
    } 
    private static int APP_W = 200; 
    private static int APP_H = 200; 

    private Scene scene; 

    private UserAction action = UserAction.NONE; 

    private Timeline timeline = new Timeline(); 
    private boolean running = true; 
    private int FPS = 60; 

    private Parent createContent(){ 
     Pane root = new Pane(); 
     root.setPrefSize(APP_W,APP_H); 

     Image cat_image = new Image("file:res/cata.png"); 
     GameObject obj = new GameObject(cat_image,12,8); 
     obj.setTranslateX(100); 
     obj.setTranslateY(100); 

     KeyFrame frame = new KeyFrame(Duration.millis(1000/FPS), event -> { 
      if(!running) 
       return; 

      switch(action){ 
       case NORTH: 
        obj.setTranslateY(obj.getTranslateY()-1); 
        break; 

       case SOUTH: 
        obj.walkSouth(); 
        obj.setTranslateY(obj.getTranslateY()+1); 
        break; 
       case NONE: 
        obj.pauseAnimation(); 
        break; 
      } 
     }); 

     timeline.getKeyFrames().add(frame); 
     timeline.setCycleCount(Timeline.INDEFINITE); 

     root.getChildren().add(obj); 

     return root; 
    } 

    private void restartGame(){ 
     stopGame(); 
     startGame(); 
    } 
    private void stopGame(){ 
     running = false; 
     timeline.stop(); 
    } 
    private void startGame(){ 
     timeline.play(); 
     running = true; 
    } 

    public void start(Stage primaryStage) throws Exception{ 
     scene = new Scene(createContent()); 

     scene.setOnKeyPressed(event -> { 
      switch (event.getCode()) { 
       case W: 
        action = UserAction.NORTH; 
        break; 
       case S: 
        action = UserAction.SOUTH; 
        break; 
      } 
     }); 

     scene.setOnKeyReleased(event -> { 
      switch (event.getCode()) { 
       case W: 
        action = UserAction.NONE; 
        break; 
       case S: 
        action = UserAction.NONE; 
        break; 
      } 
     }); 

     primaryStage.setTitle("Simple Animation"); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
     startGame(); 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 
} 

は、ゲームオブジェクトのクラスである:

package testing; 

import javafx.animation.KeyFrame; 
import javafx.animation.Timeline; 
import javafx.beans.property.IntegerProperty; 
import javafx.beans.property.SimpleIntegerProperty; 
import javafx.geometry.Rectangle2D; 
import javafx.scene.image.Image; 
import javafx.scene.image.ImageView; 
import javafx.scene.layout.Pane; 
import javafx.util.Duration; 


/** 
* Created by matt on 26/02/17. 
*/ 
public class GameObject extends Pane { 

    ObjectImage objectImage; 

    public GameObject(Image image, int columns, int rows){ 
     objectImage = new ObjectImage(image,columns,rows); 
     getChildren().setAll(objectImage); 
    } 

    public void pauseAnimation(){ 
     getChildren().setAll(objectImage); 
     objectImage.pauseAnimation(); 
    } 

    public void walkSouth(){ 
     getChildren().setAll(objectImage); 
     objectImage.walkSouth(); 
    } 

} 

class ObjectImage extends ImageView { 

    private Rectangle2D[] clips; 
    private double width,height; 
    private Timeline timeline = new Timeline(); 

    public ObjectImage(Image image,int columns,int rows){ 

     width = image.getWidth()/columns; 
     height = image.getHeight()/rows; 

     clips = new Rectangle2D[rows*columns]; 
     int count=0; 
     for(int row =0;row < rows;row++) 
      for(int column = 0 ; column < columns; column++,count++) 
       clips[count] = new Rectangle2D(width * column, height * row,width,height); 

     setImage(image); 
     setViewport(clips[0]); 

    } 

    public void pauseAnimation(){ 
     timeline.pause(); 
    } 

    public void walkSouth(){ 
     System.out.println("walk south test"); 
     IntegerProperty count = new SimpleIntegerProperty(0); 

     KeyFrame frame = new KeyFrame(Duration.millis(1000/5), event -> { 
      if(count.get() < 2) count.set(count.get()+1); 
      else count.set(0); 
      setViewport(clips[count.get()]); 
      System.out.println("frame test"); 
     }); 

     timeline.setCycleCount(timeline.INDEFINITE); 
     timeline.getKeyFrames(); 
     timeline.play(); 
    } 
} 

This is the sprite-sheet image I'm working with

This is the outcome

+0

私は今あなたの2つの質問に答えることができないかもしれませんが、ウォークスルーメソッドでタイムラインにフレームを追加するのを忘れていることがわかります。そのためアニメーションが機能しません。 –

答えて

0

コメントで示唆したとおり、あなたがました追加するのを忘れるwalkSouthメソッドのフレーム。

public void walkSouth(){ 
    System.out.println("walk south test"); 
    IntegerProperty count = new SimpleIntegerProperty(0); 

    KeyFrame frame = new KeyFrame(Duration.millis(1000/FPS), event -> { 
     if(count.get() < 2) count.set(count.get()+1); 
     else count.set(0); 
     setViewport(clips[count.get()]); 
    }); 

    timeline.setCycleCount(timeline.INDEFINITE); 
    timeline.getKeyFrames().add(frame); //This was the offending line. 
    timeline.play(); 
} 

をあなたの最初の質問に答えるために、イエスのクラスの他の多くのオプションがあなたがそこに可能性があります:(。?また、あなたが200msのにwalkSouth方法における各映像フレームを設定し、あなたがそれを変更するためのものでした)ここで変更した後のコードですつかいます。 2つのオプションは、AnimationTimerまたはTransitionクラスを使用することです。両方を簡単に説明します(コードサンプルあり)。しかし、あなたはそれぞれのフレームと呼ばれるアニメーションを使用しない場合は、拡張することができ

public void walkSouth(){ 
    System.out.println("walk south test"); 
    IntegerProperty count = new SimpleIntegerProperty(0); 

    AnimationTimer tmr = new AnimationTimer() { 
     @Override 
     public void handle(long nanoTime) 
     { 
      //nanoTime specifies the current time at the beginning of the frame in nano seconds. 
      if(count.get() < 2) count.set(count.get()+1); 
      else count.set(0); 
      setViewport(clips[count.get()]); 
     } 

    }; 
    tmr.start(); 
    //call tmr.stop() to stop/ pause timer. 
} 

AnimationTimerは、私はあなたがこれを望むかもしれないと信じて、レンダリングのすべてのサイクルまたはフレームと呼ばれ、 Transition。トランジションは、時間に対して増加する0〜1の範囲のfrac(分数)の値を持ちます。私は多くの細部に入るつもりはありませんが、apiの情報をもっと見ることができます。

public void walkSouth(){ 
    System.out.println("walk south test"); 
    IntegerProperty count = new SimpleIntegerProperty(0); 

    Transition trans = new Transition() { 
     { 
      setCycleDuration(Duration.millis(1000/60.0)); 
     } 
     @Override 
     public void interpolate(double frac) 
     { 
      if (frac != 1) 
       return; 
      //End of one cycle. 
      if(count.get() < 2) count.set(count.get()+1); 
      else count.set(0); 
      setViewport(clips[count.get()]); 
     } 

    }; 
    trans.setCycleCount(Animation.INDEFINITE); 
    trans.playFromStart(); 
    //Use trans.pause to pause, trans.stop to stop. 
} 
+0

偉大な、ありがとう、私は今働いているし、間違いなくアニメーションとトランジションクラスを使用するように変換しようとします。 「walkSouth」メソッド内の 'IntegerProperty'に注意するべき点は、ボタンを押したままでも、カウントサイクルをリセットするたびにメソッドの外でメソッドを作成して初期化する必要があります。 – mattstack

+0

あなたは通常のインスタンスの整数変数を使ってみることができます – theKidOfArcrania

関連する問題