Отдельная логика и GUI в java

Я реализую игру на Java, используя приведенные ниже классы для управления логикой игры. Я стараюсь быть предельно ясным, когда объясняю свой вопрос.

  • GamePanel

    • Я использую этот класс для запуска игрового цикла с потоком (только игровой цикл)

      public void run() {
      init(); //initialize gamePanel components
      // game loop
      while (running) {
            start = System.nanoTime();
            gameManager.update();
            KeyInput.update();
            MouseInput.update();
            gameManager.draw(graphic);
            Graphics g2 = getGraphics();
            g2.drawImage(image, 0, 0, null);
            g2.dispose();
      
            elapsed = System.nanoTime() - start;
            wait = targetTime - elapsed / 1000000;
            if (wait < 0)
          wait = 5;
           try {
               Thread.sleep(wait);
           } catch (Exception e) {
           e.printStackTrace();
         }
      
      }
      
  • GameManager

    • Я сделал этот класс для управления каждым аспектом игры как (обновление, графика)

      private void loadState(int state) {
      
      if (state == States.MENU.getValue())
      gameState = new Menu(this);
      else if (state == States.GAME.getValue())
      gameState = new Game(this);
      else if (state == States.PATHSELECT.getValue())
      gameState = new SelectPath(this);
      }
      public void update() {
      if (gameState != null)
      gameState.update();
      }
      
      public void draw(java.awt.Graphics2D graphic) {
       if (gameState != null)
      gameState.draw(graphic);
       else {
      JOptionPane.showMessageDialog(null, JOptionPane.ERROR_MESSAGE);
           }
      }
      
  • GameState

    • GameState - абстрактный класс, который получает в качестве параметра конструктора экземпляр GameManager и имеет абстрактные методы, реализованные в каждом GameState (меню, игра, мультиплеер и т.д.).

    • Этот класс имеет эти абстрактные методы:

      • controller() → , которые проверяют логику состояния

      • update() → в случае, если currentState является многопользовательским, этот метод вызывает метод обновления класса Player и т.д.

      • draw (Graphics g) → рисовать для экранирования объектов currentState

Я думал о создании одноуровневого класса утилиты, который реализует все draw() каждого состояния, но очень неприятно вставлять все в один класс.

Пример:

вместо вызова gameState.draw(graphic); Я вызываю Render.getRenderInstance().draw(graphic,gameState); эти решения работают, но мне это не нравится.

Итак, как можно красиво разделить метод draw от остальной логики?

Некоторые советы? Спасибо.

Ответ 1

Обычный подход состоит в том, чтобы разделить игру на две части:

  • логика, которая выглядит как ОК в вашем случае

  • сцена, где рисуются предметы

Здесь, в псевдокоде, я это делаю:

the main loop:
  gamestate.update()
  scene.render();

В сцене вы должны иметь все графические операции. Вы можете добавить новую графику в сцену, используя вызов, подобный этому:

scene.addObject(SomeGraphic graphic);

Таким образом, сцена сделает визуализацию каждой основной итерации цикла.

Чтобы это произошло, вы должны хранить список или другую коллекцию внутри класса Scene и каждый раз показывать каждый объект. Таким образом, actall scene.render() будет выглядеть так:

public void render() {
  for(SomeGraphic graphic : objects) {
    graphic.draw()
  }
}

Затем вы сможете контролировать то, что находится на сцене из логики игры - вы сможете добавлять и удалять объекты и т.д.