Как нарисовать в графическом контексте в игровом цикле? - PullRequest
0 голосов
/ 04 июля 2019

Я делаю игру с фруктами-ниндзя и хочу на некоторое время приостановить анимационный таймер и установить изображение нарезанного изображения фруктов "current.getBufferedImages () [1]", когда оно будет нарезано, но я получаю то же изображение не нарезанный фрукт "current.getBufferedImages () [0]", хотя я изменяю изображение, которое будет нарисовано в graphicsContext.setImage ()

        public void startGame(Stage primaryStage) throws Exception {
        ga = GameActions.get();
        canvas = new Canvas(1024,683);

        gc = canvas.getGraphicsContext2D();

        timeline = new Timeline(new KeyFrame(Duration.millis(falling), event -> {
            time += falling / 3000;
            IGameObject c = ga.createGameObject();
            drop.add(c);
        }));
        timeline.setCycleCount(4000);
        timeline.play();

        timer = new AnimationTimer() {

            @Override
            public void handle(long arg0) {
                gameUpdate(primaryStage);
            }

        };
        timer.start();
        scene = new Scene(root, 1024, 683);


        root.getChildren().addAll(ivBackground,lblMissed,canvas,back,reset);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

         public void gameUpdate(Stage stage){
        Image k;
        gc.drawImage(background, 300, 300);
        gc.clearRect(0, 0, 1024, 683);
        Iterator<IGameObject> itr = drop.iterator();
        while(itr.hasNext()) {
            IGameObject current = itr.next();
            EventHandler<MouseEvent> e = new EventHandler<MouseEvent>() {

                @Override
                public void handle(MouseEvent event) {
                    if(current.insideBounds(event.getX(), event.getY()))
                        current.slice();
                }

            };
            gc.getCanvas().setOnMousePressed(e);
            if(!current.isSliced()) {
                k = SwingFXUtils.toFXImage(current.getBufferedImages()[0], null);
            }else {
                k = SwingFXUtils.toFXImage(current.getBufferedImages()[1], null);
                if(current.getObjectType().toString().equalsIgnoreCase("dangerousbomb")) {
                    for(int i=0;i<150000;i++) {
                        gc.drawImage(k, current.getXlocation(), current.getYlocation());
                        timer.stop();
                    }
                    timer.start();
                    itr.remove();
                    lives--;
                    lblLives.setText("Lives: " + String.valueOf(lives));
                }else if(current.getObjectType().toString().equalsIgnoreCase("fatalbomb")) {
                    gameOver();
                    break;
                }else if(current.getObjectType().toString().equalsIgnoreCase("specialfruit")) {
                    for(int i=0;i<150000;i++) {
                        gc.drawImage(k, current.getXlocation(), current.getYlocation());
                        timer.stop();
                    }
                    timer.start();
                    itr.remove();
                    score+=5;
                    lblScore.setText("Score: " + String.valueOf(score));
                    if(score >= highestScore) {
                        highestScore = score;
                        ga.saveHighScore(highestScore);
                        lblHighestScore.setText("Highest Score: "+highestScore);
                    }
                }else if(current.getObjectType().toString().equalsIgnoreCase("fruit")) {
                    for(int i=0;i<150000;i++) {
                        gc.drawImage(k, current.getXlocation(), current.getYlocation());
                        timer.stop();
                    }
                    timer.start();
                    itr.remove();
                    score++;
                    lblScore.setText("Score: " + String.valueOf(score));
                    if(score >= highestScore) {
                        highestScore = score;
                        ga.saveHighScore(highestScore);
                        lblHighestScore.setText("Highest Score: "+highestScore);
                    }
                }
            }

            gc.drawImage(k, current.getXlocation(), current.getYlocation());
            ga.updateObjectsLocations(time,current);


            }
        }
    }

1 Ответ

2 голосов
/ 04 июля 2019

gameUpdate выполняется в потоке приложения JavaFX. Это означает, что любая задержка возврата этого метода просто останавливает графический интерфейс, пока метод не вернется. По этой причине те

for(int i=0;i<150000;i++) {
    gc.drawImage(k, current.getXlocation(), current.getYlocation());
    timer.stop();
}

петли не работают.

Самый простой способ «приостановить» здесь - сэкономить время, в течение которого AnimationTimer разрешено продолжать.

timer = new AnimationTimer() {

    @Override
    public void handle(long arg0) {
        gameUpdate(arg0);
    }

};
private long pauseEnd = 0L;

/**
 * Continue updates after a certain number of milliseconds after the current time
 */
private void pauseFor(long currentTime, long durationMillis) {
    pauseEnd = currentTime + 1_000_000L * durationMillis;
}

public void gameUpdate(long timestamp) {
    if (timestamp >= pauseEnd) { // only redraw, if not paused
        ...

        //for(int i=0;i<150000;i++) {
        //    gc.drawImage(k, current.getXlocation(), current.getYlocation());
        //    timer.stop();
        //}
        //timer.start();
        //itr.remove();
        //score++;
        gc.drawImage(k, current.getXlocation(), current.getYlocation());
        itr.remove();
        score++;
        pauseFor(timestamp, 3000); // start updates again in 3000 ms

        ...
    }
}

Кроме того, вы заменяете EventHandler для каждого игрового объекта на каждой итерации игрового цикла. Таким образом, только один игровой объект проверяется на пересечение с мышью. Вам нужно проверить их все с помощью одного обработчика событий. Помимо удаления регистрации обработчика событий из метода gameLoop, добавьте следующий код в метод start, чтобы проверить все объекты на предмет пересечений:

canvas.setOnMousePressed(event -> {
    for (IGameObject current : drop) {
        if(current.insideBounds(event.getX(), event.getY())) {
            current.slice();
        }
    }
});

Кроме того, я настоятельно рекомендую не конвертировать BufferedImage s в каждой итерации игрового цикла снова и снова. Предпочтительно заменить BufferedImage s непосредственно на JavaFX Image s или оставить Map<BufferedImage, Image>, содержащий каждый результат преобразования ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...