2016-11-15 10 views
1

私は非常に大きなマップを必要とする基本的なスペースリアルタイム戦略ゲームを作成していますが、一度にマップの小さな部分のみを表示します。私はこれが非常にイメージビューを使用してビューポートで行うことが容易であることがわかった。残念ながら、画像ビューには画像を渡す必要があり、キャンバスを使用してすべてのスプライトを背景に描画しています。私は完全にレンダリングされたシーンのイメージを撮ってイメージビューに渡すためにスナップショットを使っていましたので、ビューポートを使うことができましたが、それはパフォーマンスの重大な低下を引き起こしています。スナップショットを使用しない場合、ゲームは60+ fpsで動作しますが、スナップショットを使用する場合はfpsは常に15以下です。スナップショットの使用は、シーンが1024x512だったときは問題ありませんでしたが、シーンは現在4096x2048です。スナップショットを使用せずに秒間に60回イメージビューとビューポートを使用するより良い方法はありますか?私は以下のやっているのコード例:https://github.com/WiredOverload/ObliterateEverythingjavafxスナップショットのパフォーマンスが遅い

私は、私はスナップショットが行われている間、残りのコードを遅らせることを避けるために、非同期スナップショットを使用することができることを知っているが、その時

Group trueRoot = new Group(); //shown image 
    Group root = new Group(); //invisible unedited image 

    Canvas canvas = new Canvas(4096, 2048); //unedited canvas 
    root.getChildren().add(canvas); 
    GraphicsContext gc = canvas.getGraphicsContext2D(); 

    Scene scene2 = new Scene(trueRoot); 
    primaryStage.setScene(scene2); 

    WritableImage sceneImage = root.snapshot(new SnapshotParameters(), null); //snapshot of fully rendered root scene 
    ImageView imageView = new ImageView(sceneImage); //imageView can be used to resize or crop 
    Rectangle2D viewportRect = new Rectangle2D(0, 0, 1024, 512); //for cropping 
    imageView.setViewport(viewportRect); //for cropping 
    trueRoot.getChildren().add(imageView); //also for resizing/cropping 

    new AnimationTimer() { 
     public void handle(long currentNanoTime) { 

       //simple animated background 
       if (cloudTimer == 16384) 
        cloudTimer = 0; 
       else 
        cloudTimer++; 

       gc.drawImage(stars, 0, 0); 
       gc.drawImage(clouds1, cloudTimer % 16384, 0); 
       gc.drawImage(clouds1, (cloudTimer % 16384) - 8192, 0); 
       gc.drawImage(clouds2, (cloudTimer/2) % 16384, 0); 
       gc.drawImage(clouds2, ((cloudTimer/2) % 16384) - 8192, 0); 

       p1.update(p2, root); 
       p2.update(p1, root); 
       p1.render(gc, root); 
       p2.render(gc, root); 

       root.snapshot(new SnapshotParameters(), sceneImage); //takes root scene and hands it to trueRoot 
     } 
    }.start(); 


    primaryStage.show(); 

完全なコードまだ15 fpsでゲームを離れるだろう。任意の提案をいただければ幸いです。

答えて

0

ジャストGraphicsContext SサイズさんはCanvasにビューポートに合う変換&規模適用する変換「調整リスナーを使用して独自のviewportプロパティを記述します。

@Override 
public void start(Stage primaryStage) { 
    Canvas canvas = new Canvas(); 
    GraphicsContext context = canvas.getGraphicsContext2D(); 

    ObjectProperty<Rectangle2D> viewport = new SimpleObjectProperty<>(Rectangle2D.EMPTY); 
    Pane root = new Pane(canvas); 
    root.setPrefSize(400, 400); 
    canvas.setManaged(false); 
    root.layoutBoundsProperty().addListener((observable, oldBound, newBounds) -> { 
     canvas.setWidth(newBounds.getWidth()); 
     canvas.setHeight(newBounds.getHeight()); 
     Rectangle2D vp = viewport.get(); 
     viewport.set(new Rectangle2D(vp.getMinX(), vp.getMinY(), newBounds.getWidth(), newBounds.getHeight())); 
    }); 

    viewport.addListener((observable, oldViewport, newViewport) -> { 
     // combined transform & scale transfromation 
     context.setTransform(canvas.getWidth()/newViewport.getWidth(), 0, 
       0, canvas.getHeight()/newViewport.getHeight(), 
       -newViewport.getMinX(), -newViewport.getMinY()); 
     redraw(context); 
    }); 


    // sample movement animation 
    Transition scale = new Transition() { 

     { 
      setCycleDuration(Duration.seconds(2)); 
      setCycleCount(2); 
      setAutoReverse(true); 
     } 

     @Override 
     protected void interpolate(double frac) { 
      double scale = 1 + 2 * frac; 
      Rectangle2D vp = viewport.get(); 
      viewport.set(new Rectangle2D(vp.getMinX(), vp.getMinY(), canvas.getWidth()/scale, canvas.getHeight()/scale)); 
     } 

    }; 

    Transition move = new Transition() { 

     { 
      setCycleDuration(Duration.seconds(2)); 
      setCycleCount(2); 
      setAutoReverse(true); 
     } 

     @Override 
     protected void interpolate(double frac) { 
      double posX = 300 * frac; 
      Rectangle2D vp = viewport.get(); 
      viewport.set(new Rectangle2D(posX, 0, canvas.getWidth(), canvas.getHeight())); 
     } 

    }; 

    SequentialTransition animation = new SequentialTransition(scale, move); 
    animation.setCycleCount(Animation.INDEFINITE); 
    animation.play(); 

    Scene scene = new Scene(root); 

    primaryStage.setScene(scene); 
    primaryStage.show(); 
} 

private static Color[] colors = new Color[]{ 
    Color.RED, 
    Color.BEIGE, 
    Color.GREEN, 
    Color.ORANGE, 
    Color.BLACK, 
    Color.BLUE, 
    Color.WHEAT, 
    Color.CORAL, 
    Color.CRIMSON, 
    Color.PURPLE, 
    Color.AQUAMARINE, 
    Color.YELLOW, 
    Color.CHOCOLATE 
}; 

public static void redraw(GraphicsContext gc) { 
    Bounds bounds; 
    try { 
     bounds = gc.getTransform().inverseTransform(gc.getCanvas().getLayoutBounds()); 
    } catch (NonInvertibleTransformException ex) { 
     throw new IllegalStateException(); 
    } 
    gc.clearRect(bounds.getMinX(), bounds.getMinY(), bounds.getWidth(), bounds.getHeight()); 
    for (int i = 0; i < colors.length; i++) { 
     gc.setFill(colors[i]); 
     gc.fillRect(i * 50, 0, 50, 50); 
    } 
} 
+0

おかげで、私がしようとするでしょう私のコードにこれを実装してください。私がそれを正しく入れることができれば、それはうまくいっているかどうかを言うでしょう。 – WiredOverload

関連する問題