2016-11-15 2 views
1

Я создаю базовую стратегическую стратегию пространства в реальном времени, которая требует очень большой карты, но будет отображать только небольшую часть карты за раз. Я обнаружил, что это очень легко сделать с видовым окном с использованием imageview. К сожалению, для просмотра изображений требуется изображение, которое нужно передать, и я использовал холст, чтобы нарисовать все спрайты на фоне. Я использую моментальный снимок для получения изображения полностью визуализированной сцены и передачи этого изображения, чтобы я мог использовать видовое окно, но это привело к серьезному снижению производительности. Без использования моментального снимка игра работает со скоростью 60 кадров в секунду, однако при использовании моментального снимка fps всегда 15 или ниже. Использование моментального снимка не было проблемой, когда сцена была 1024x512, но теперь она 4096x2048. Есть ли лучший способ использовать просмотр изображений и просмотр 60 раз в секунду без использования моментального снимка? Пример код, что я делаю ниже:javafx моментальный снимок с низкой производительностью

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(); 

полный код на https://github.com/WiredOverload/ObliterateEverything

Я знаю, что я мог бы использовать асинхронный снимок, чтобы избежать задержек остальной части коды, пока снимок происходит, но что все равно оставит игру со скоростью 15 кадров в секунду. Мы ценим любые предложения.

ответ

0

Просто написать свое собственное viewport свойство с слушателем, который регулирует GraphicsContext «s преобразования, чтобы применить преобразование & шкалы, которая соответствует окну просмотра к Canvas» размеру s:

@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

Смежные вопросы