Начинаем создавать свою игру на JavaFX

в 14:51, , рубрики: game development, java, разработка игр

Небольшое отступление.

JavaFX — платформа для создания RIA, позволяет строить унифицированные приложения с насыщенным графическим интерфейсом пользователя для непосредственного запуска из-под операционных систем, работы в браузерах и на мобильных телефонах, в том числе работающих с мультимедийным содержимым.

Приступаем к нашему коду. У нас на данный момент должно быть 3 класса.

  • Главный класс. (Main,launcher и т.д.)
  • Контроллер. (Вся работа с UI)
  • Дополнительный класс. (Utils)

Приступаем к созданию главного класса. Из этого класса будет запускаться наше приложение.

Вот код нашего главного класса как он должен выглядеть:

Main.java

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception{
        Parent root = FXMLLoader.load(Controller.class.getResource("sample.fxml"));
        primaryStage.setTitle("First my game");
        primaryStage.setScene(new Scene(root, 640, 480));
        primaryStage.show();
    }


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

Разберем что у нас в этом классе. Тут создается первоначальное окно из sample.fxml

sample.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.GridPane?>

<AnchorPane fx:id="parent" prefHeight="480.0" prefWidth="640.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="com.w2d.scene.Controller" />

Это шаблон нашего окна. Данный файл будем редактировать из JavaFX Scene Builder

Метод launch(args) запускает уже приложение JavaFX весь наш код как говориться.

На этом обзор главного класса мы завершим.

Следующий класс который нам нужен это Controller. Из этого класса мы будем полностью управлять UI который у нас есть в sample.fxml.

Дополнительно

Controller — класс будет управлять UI только который есть в sample.fxml.

Наш Controller:

Controller.java

public class Controller {
    @FXML
    AnchorPane parent;

}

Переменная parent — это аналог Контейнера из Java Swing. Имена переменных должны совпадать с ID из sample.fxml так же обязательно должна быть аннотация @FXML.

Перейдем к нашему классу Utils. Здесь мы будем делать какие-то вычисления. Например подгружать ресурсы.

Код класса Utils:

Utils.java

public class Utils {
    public static class Resource {
    // подгрузка ресурсов
    
    public static HashMap<String,Scene> scenes = new HashMap<>();
    
    public static void load() throws IOException
    {
        // подгружаем сцену после вызываем её через Utils
    }
    
  }
}

Данный класс, будет подгружать наши все сцены которые у нас есть, после мы будем их менять через Stage.setScene(). Пример подгрузки сцен.

Пример подгрузки и после использования

    public static void load() throws IOException
    {
        Parent rootSplash = FXMLLoader.load(Game.class.getResource("Splash.fxml"));
        Scene splash = new Scene(rootSplash);
        
        Parent rootMenu = FXMLLoader.load(Game.class.getResource("Menu.fxml"));
        Scene menu= new Scene(rootMenu );
        
        Parent rootGame = FXMLLoader.load(Game.class.getResource("Game.fxml"));
        Scene game = new Scene(rootGame);
        
        scenes.put("splash", splash);
        scenes.put("Menu",menu);
        scenes.put("game", game);
    }

Использовать так.

...
Stage.setScene(Resource.scenes.get("game");
...

Мы создали скелет нашей будущей игры. Теперь можно создавать свою игру опираясь на наш «скелет».

Давай-те сделаем Splash screen.

Splash screen - что это?

Это в основном картинка когда вы запускаете игру, где мы можем подгрузить наши ресурсы игры.

Примеры:

image

Начинаем создавать свою игру на JavaFX - 2

Создадим класс SplashController который реализует интерфейс Initializable. Наш класс должен выглядит примерно так

SplashController

public class SplashController implements Initializable{
    // Splash.fxml
    @FXML
    private ImageView splash; // Наше изображение
    @FXML 
    private AnchorPane parent; // Наш контейнер
    // Вызывается при появление контейнера
    @Override
    public void initialize(URL location, ResourceBundle resources) {
    	// code
    }
}

Как должен выглядеть наш FXML файл.

Splash.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.layout.*?>

<AnchorPane id="AnchorPane" fx:id="parent" onMouseClicked="#click" prefHeight="480.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="game.SplashController">
  <children>
    <ImageView fx:id="splash" fitHeight="479.0" fitWidth="638.6666666666666" layoutX="1.0" layoutY="1.0" pickOnBounds="true" preserveRatio="true">
      <image>
        <Image url="@../resource/splash.png" />
      </image>
    </ImageView>
  </children>
</AnchorPane>

Так. Теперь можно приступать к коду который должен быть в контроллере. Просто SplashScreen как-то не красиво. Поэтому я решил сделать чтобы он появился, после плавно пропал под воздействием смены альфа-прозрачности.

Увы, способ с анимацией плохо работает (Уже были эксперименты), поэтому я решил, что надо через Timer (java.util.Timer) реализовать этот способ. Моя реализация плавного перехода с SplashScreen на другой Screen.

SplashController полный код

public class SplashController implements Initializable{
    
    @FXML
    private ImageView splash;
    @FXML
    private AnchorPane parent;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        Timer timer = new Timer();
        
        timer.schedule(new TimerTask() {
        @Override
        public void run() {
             Platform.runLater(new Runnable() {
                boolean isTimer = false;
                @Override
                public void run() {
                    if(!isTimer){
                        if(splash.getOpacity() < 0) {
                            isTimer = true;
                            timer.cancel();
                            Game.STAGE.setScene(Resource.scenes.get("main"));
                        }
                    splash.setOpacity(splash.getOpacity()-0.05);
                    }
                }
            });
        }
        }, 500,100);
        
    }
}

На этом я закончу данную статью, надеюсь, кому-то понравилось.

Автор: white2demon

Источник


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js