Лучший способ реализовать игровой цикл без замораживания потока пользовательского интерфейса - PullRequest
9 голосов
/ 19 мая 2010

Я пытаюсь сделать простую 2D-игру на Java.

Пока что у меня есть JFrame с меню и классом, который расширяет JPanel и переопределяет его paint метод.,Теперь мне нужно запустить игровой цикл, где я буду обновлять положение изображений и так далее.Тем не менее, я застрял на том, как лучше всего добиться этого.Должен ли я использовать многопоточность, потому что, конечно, если вы поместите бесконечный цикл в основной поток, пользовательский интерфейс (и, следовательно, моя строка меню) зависнет?

Вот мой код на данный момент:1009 *

Есть указатели или советы?Где я должен поставить свою петлю?В моем основном классе или в классе GameCanvas?

Ответы [ 3 ]

11 голосов
/ 19 мая 2010

Ваш игровой цикл (модель) не должен находиться рядом с любым из ваших классов графического интерфейса (вид). Он использует ваши классы GUI - но даже то, что вы, вероятно, хотите сделать через посредника (контроллер). Хороший способ убедиться, что вы все делаете правильно, это убедиться, что в вашей модели нет ни одного "include javax.swing.???".

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

Это на самом деле потрясающе, потому что заставляет вас думать с точки зрения операций с графическим интерфейсом (которые будут представлять собой ваш контроллер). Например, у вас может быть класс «Move», который будет иметь логику GUI за перемещением. Ваш игровой цикл может создать экземпляр «Move» с правильными значениями (элемент для перемещения, конечное местоположение) и передать его в цикл GUI для обработки.

Как только вы дойдете до этого момента, вы поймете, что простое добавление тривиального «отмены» для каждой операции с графическим интерфейсом позволяет вам легко отменить любое количество операций. Вам также будет проще заменить ваш Swing GUI веб-интерфейсом ...

5 голосов
/ 21 мая 2010

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

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

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

Нет, ваша строка меню не остановится, если вы поместите игровой цикл в основной поток. Строка меню остановится, если обратные вызовы Swing потребуют много времени.

Данные, которые разделяются между потоками, должны быть защищены с помощью блокировок.

Я предлагаю вам включить ваш Swing-код в отдельный класс и поместить только игровой цикл в основной класс. Если вы используете основной поток для своего игрового цикла, это приблизительное представление о том, как вы могли бы его спроектировать.

import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;

class GUI extends JFrame {
    GameCanvas canvas = new GameCanvas();
    final int FRAME_HEIGHT = 400;
    final int FRAME_WIDTH = 400;


    public GUI() {
        // build and display your GUI
        super("Game");

        JMenuBar menuBar = new JMenuBar();
        JMenu fileMenu = new JMenu("File");
        JMenuItem startMenuItem = new JMenuItem("Pause");
        menuBar.add(fileMenu);
        fileMenu.add(startMenuItem);

        super.add(canvas);
        super.setVisible(true);
        super.setSize(FRAME_WIDTH, FRAME_WIDTH);
        super.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        super.setJMenuBar(menuBar);
    }
}

public class Main {

    public static void main(String args[]) {
        GUI ui = new GUI(); // create and display GUI        

        gameLoop(); // start the game loop
    }

    static void gameLoop() {
        // game loop    
    }
}
4 голосов
/ 19 мая 2010

Java действительно подходит для событийного программирования .В основном, установите событие таймера и слушайте.На каждом тик-токе вы обновляете игровую логику.На каждом GUI-событии вы обновляете свои структуры данных, которые будет читать метод логики игры.

...