如何确定我使用JavaFX编写的游戏是否使用了足够的系统资源?

时间:2019-01-27 20:27:56

标签: intellij-idea javafx

我编写了一个简单的纸牌游戏(使用IntelliJ 3.3),该游戏每秒更新gui并包含游戏中的许多节点,这些节点用于显示游戏事件和动画。尝试过该游戏的人说,他们的系统速度变慢,内存和cpu使用率上升(当我从朋友的一个屏幕上看到它使用了约1.4 GB内存时,我感到震惊)

我检查了一些与javaFX内存使用问题有关的问题,但与我的问题无关。在一篇文章中,我读到在JavaFX游戏中使用多个节点可能会导致较高的内存使用率。

在短时间内运行:

最小内存使用量约为100-250 MB

最大内存使用量约为800-1200 MB

平均内存使用量约为500-700 MB

重要提示:

一个没有FX ID的10X10网格中有100个按钮

在gameButtonClicked的匹配项中找到button.indexOf(event.getSource())

UML DIAGRAM

  • Main.java
  

导入:

     

导入javafx.application.Application;

     

导入javafx.application.Platform;

     

导入javafx.fxml.FXMLLoader;

     

导入javafx.scene.Parent;

     

导入javafx.scene.Scene;

     

导入javafx.scene.media.Media;

     

导入javafx.scene.media.MediaPlayer;

     

导入javafx.stage.Stage;

     

导入javafx.util.Duration;

     

导入java.net.URL;

     

import java.util.ArrayList;

     

import java.util.Collections;

     

导入java.util.HashMap;

     

import java.util.Random;

     

import java.util.concurrent.atomic.AtomicLong;

    public class Main extends Application {
        static boolean isMuted;
        static Stage window;
        static MediaPlayer mediaPlayerBGM;
        static MediaPlayer mediaPlayerSFX;
        private static HashMap<String, Media> sounds;
        private static ArrayList<Long> usage;
        private final String[] SOUND_LIST = {"bgm_credits.mp3", "bgm_game.mp3", "bgm_game_1.mp3", "bgm_game_2.mp3", "bgm_game_3.mp3",
                "bgm_how_to.mp3", "bgm_menu.mp3", "bgm_victory.mp3", "sfx_button_clicked.wav",
                "sfx_card_unfold.wav", "sfx_toggle.wav"
        };

    public static void main(String[] args) {
        launch(args);
        AtomicLong sum = new AtomicLong();
        usage.forEach(sum::addAndGet);
        long average = sum.get() / usage.size();
        System.out.printf("minimum usage: %d, maximum usage: %d, average usage: %d",
                Collections.min(usage), Collections.max(usage), average);
    }

    static void playBGM(String key) {
        mediaPlayerBGM.stop();
        mediaPlayerBGM.setStartTime(Duration.ZERO);
        if (key.equals("bgm_game")) {
            String[] suffix = {"", "_1", "_2", "_3"};
            Random random = new Random();
            mediaPlayerBGM = new MediaPlayer(sounds.get(key + suffix[random.nextInt(4)]));
        } else {
            mediaPlayerBGM = new MediaPlayer(sounds.get(key));
        }
        mediaPlayerBGM.setCycleCount(MediaPlayer.INDEFINITE);
        if (isMuted) {
            mediaPlayerBGM.setVolume(0.0);
        }
        mediaPlayerBGM.play();
    }

    static void playSFX(String key) {
        if (mediaPlayerSFX != null) {
            mediaPlayerSFX.stop();
        }
        mediaPlayerSFX = new MediaPlayer(sounds.get(key));
        if (isMuted) {
            mediaPlayerSFX.setVolume(0.0);
        }
        mediaPlayerSFX.play();
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        sounds = new HashMap<>();
        usage = new ArrayList<>();
        isMuted = false;
        for (String soundName :
                SOUND_LIST) {
            URL resource = getClass().getResource("/" + soundName);
            System.out.println(soundName);
            System.out.println(resource.toString());
            sounds.put(soundName.substring(0, soundName.lastIndexOf('.')), new Media(resource.toString()));
        }
        mediaPlayerBGM = new MediaPlayer(sounds.get("bgm_menu"));
        mediaPlayerBGM.setCycleCount(MediaPlayer.INDEFINITE);
        mediaPlayerBGM.play();
        window = primaryStage;
        Parent root = FXMLLoader.load(getClass().getResource("menu.fxml"));
        // long running operation runs on different thread
        Thread thread = new Thread(() -> {
            Runnable updater = () -> {
                if (!Game.isGameIsOver() && Game.getScore() != 0 && window.getTitle().equals("The Main Pick") &&
                        Game.firstClickHappened()) {
                    Game.scoreCalculator();
                }

            };

            while (true) {
                try {
                    usage.add(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory());
                    System.out.printf("Used memory: %d\n", Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory());
                    Thread.sleep(1000);
                } catch (InterruptedException ex) {
                    System.out.println("Interrupted");
                }

                // UI update is run on the Application thread
                Platform.runLater(updater);
            }
        });
        // don't let thread prevent JVM shutdown
        thread.setDaemon(true);
        thread.start();
        window.setTitle("Main Menu");
        window.setScene(new Scene(root, 600, 600));
        window.setResizable(false);
        window.show();
    }
}
  • Controller.java
  

导入:

     

打包com.sample;

     

import javafx.animation.FadeTransition;

     

import javafx.collections.ObservableList;

     

import javafx.event.ActionEvent;

     

导入javafx.fxml.FXML;

     

导入javafx.fxml.FXMLLoader;

     

importjavafx.scene.Node;

     

import javafx.scene.Parent;

     

导入javafx.scene.Scene;

     

导入javafx.scene.control.Button;

     

导入javafx.scene.control.Label;

     

导入javafx.scene.control.RadioButton;

     

导入javafx.scene.layout.GridPane;

     

导入javafx.util.Duration;

     

import java.io.IOException;

public class Controller
{
    @FXML
    public RadioButton musicOnOff;
    @FXML
    public Button newGame;
    @FXML
    public Button howTo;
    @FXML
    public Button credits;
    @FXML
    public Button exit;
    @FXML
    public Button menu;
    @FXML
    public GridPane pane;
    @FXML
    public Label score;
    @FXML
    public Label time;
    @FXML
    public Label tries;
    private boolean animating;
    public void initialize() {
        if (score != null && time != null && tries != null) {
            score.textProperty().bind(Game.scoreProperty);
            time.textProperty().bind(Game.timeProperty);
            tries.textProperty().bind(Game.triesProperty);
            animating=false;
        }
        if (musicOnOff!=null){
            if(Main.isMuted){
                musicOnOff.setSelected(true);
            }
        }
    }

    public void newGameButtonClicked() {
        try {
            Main.playSFX("sfx_button_clicked");
            new Game();
            Main.window.hide();
            Main.window.setScene(getScene("game"));
            Main.window.setTitle("The Main Pick");
            Main.window.setMaximized(true);
            Main.playBGM("bgm_game");
            Main.window.show();
        } catch (IOException e) {
            System.out.println("could not change the scene to: game");
        }
    }

    public void menuButtonClicked() {
        try {
            Main.playSFX("sfx_button_clicked");
            Main.playBGM("bgm_menu");
            if (Main.window.getTitle().equals("The Main Pick")) {
                Main.window.hide();
                Game.setGameOver();
                Main.window.setScene(getScene("menu"));
                Main.window.setMaximized(false);
                Main.window.show();
            } else {
                Main.window.setScene(getScene("menu"));
            }
            Main.window.setTitle("Main Menu");
        } catch (IOException e) {
            System.out.println("could not change the scene to: game");
        }
    }

    public void gameButtonClicked(ActionEvent event) {
        ObservableList<Node> buttons = pane.getChildren();
        int index = buttons.indexOf(event.getSource());
        int column = index % 10;
        int row = (index - index % 10) / 10;
        if (!((Button) event.getSource()).getStyleClass().toString().equals("button button-treasure") &&
                !((Button) event.getSource()).getStyleClass().toString().equals("button button-uncovered"))
        {

            FadeTransition transition = new FadeTransition();
            transition.setNode((Button) event.getSource());
            transition.setDuration(new Duration(500));
            transition.setFromValue(1.0);
            transition.setToValue(0.0);
            transition.setCycleCount(1);
            transition.setOnFinished(actionEvent -> {
                if (((Button) event.getSource()).getStyleClass().toString().equals("button button-treasure")) {
                    loadVictoryScene();

                }
                if (!((Button) event.getSource()).getStyleClass().toString().equals("button button-treasure") &&
                        !((Button) event.getSource()).getStyleClass().toString().equals("button button-uncovered"))
                {

                    transition.setFromValue(0.0);
                    transition.setToValue(1.0);
                    System.out.println(((Button) event.getSource()).getStyleClass().toString());
                    ((Button) event.getSource()).getStyleClass().remove("button-covered");
                    ((Button) event.getSource()).getStyleClass().add(Game.click(row, column));
                    transition.play();
                    transition.setOnFinished(ActionEvent->animating=false);
                }
            });
            System.out.println(animating);
            if(!animating){
            animating=true;
            transition.play();
            Main.playSFX("sfx_card_unfold");}
        }

        System.out.printf("button index:%d,row:%d,column:%d\n", index, row, column);
    }

    public void howToPlayButtonClicked() {
        try {
            Main.playSFX("sfx_button_clicked");
            Main.playBGM("bgm_how_to");
            Main.window.setScene(getScene("howTo"));
            Main.window.setTitle("How to Play");
        } catch (IOException e) {
            System.out.println("could not change the scene to: how to play");
        }
    }

    public void creditsButtonClicked() {
        try {
            Main.playSFX("sfx_button_clicked");
            Main.playBGM("bgm_credits");
            Main.window.setScene(getScene("credits"));
            Main.window.setTitle("Credits");
        } catch (IOException e) {
            System.out.println("could not change the scene to: credits");
        }
    }

    public void exitButtonClicked() {
        Main.playSFX("sfx_button_clicked");
        Main.window.close();
    }

    public void musicOnOffRadioButtonChecked() {
        Main.playSFX("sfx_toggle");
        if (musicOnOff.isSelected()) {
            Main.isMuted=true;
            Main.mediaPlayerBGM.setVolume(0.0);
            Main.mediaPlayerSFX.setVolume(0.0);
            System.out.println("now selected");
        } else {
            Main.isMuted=false;
            Main.mediaPlayerBGM.setVolume(1.0);
            Main.mediaPlayerSFX.setVolume(1.0);
            System.out.println("unselected");
        }
    }

    private void loadVictoryScene() {
        try {
            Main.window.hide();
            Main.playBGM("bgm_victory");
            Main.window.setScene(getScene("victory"));
            Main.window.setTitle("Victory");
            Main.window.setMaximized(false);
            Main.window.show();
        } catch (IOException e) {
            System.out.println("could not change the scene to: victory");
        }
    }

    private Scene getScene(String name) throws IOException {
        Parent root = FXMLLoader.load(getClass().getResource(name + ".fxml"));
        if (name.equals("game")) {
            return new Scene(root, 800, 800);
        }
        return new Scene(root, 600, 600);
    }
}
  • Game.java
  

导入:

     

打包com.sample;

     

import javafx.beans.property.SimpleStringProperty;

     

import javafx.beans.property.StringProperty;

     

import java.util.Random;

public class Game {
    static StringProperty scoreProperty;
    static StringProperty timeProperty;
    static StringProperty triesProperty;
    private static int time;
    private static int score;
    private static int tries;
    private static int[][] tiles;
    private static boolean gameIsOver;
    private static boolean firstClick;

    public Game() {
        System.out.println("Game created...");
        tries = 0;
        score = 100000;
        time = 0;
        gameIsOver = false;
        firstClick = false;
        scoreProperty = new SimpleStringProperty("" + score);
        timeProperty = new SimpleStringProperty("0");
        triesProperty = new SimpleStringProperty("0");
        tiles = new int[10][10];
        Random random = new Random();
        int treasureColumn = random.nextInt(10);
        int treasureRow = random.nextInt(10);
        tiles[treasureRow][treasureColumn] = 1;
    }

    static boolean firstClickHappened() {
        return firstClick;
    }

    static void setGameOver() {
        gameIsOver = true;
    }

    static boolean isGameIsOver() {
        return gameIsOver;
    }

    static int getScore() {
        return score;
    }

    static void scoreCalculator() {
        time++;
        if (time < 10) {
            score = score - 100;
        } else if (time < 20) {
            score = score - 200;
        } else if (time < 30) {
            score = score - 300;
        } else if (time < 50) {
            score = score - 500;
        } else {
            score = score - 1000;
        }
        if (score < 0) {
            score = 0;
        }
        scoreProperty.setValue("" + score);
        timeProperty.setValue("" + time);
        triesProperty.setValue("" + tries);
        System.out.printf("Score:%s,Time:%s,Tries%s\n", scoreProperty.getValue(), timeProperty.getValue(), triesProperty.getValue());
    }


    static String click(int row, int column) {
        if (!firstClickHappened()) firstClick = true;
        System.out.println(row + "," + column);
        int clickValue = tiles[row][column];
        System.out.println(clickValue);
        if (clickValue == 0) {
            tries++;
            score -= 1000;
        } else {
            setGameOver();
        }
        return (clickValue == 1) ? "button-treasure" : "button-uncovered";
    }
}

0 个答案:

没有答案