10

Javaで簡単な2Dゲームを作ろうとしています。

これまでのところJFrame、メニューバーを備えた、と、そのメソッドを拡張JPanelおよびオーバーライドするクラスがありますpaint。次に、画像の位置などを更新するゲームループを実行する必要があります。しかし、私はこれを達成するための最善の方法に固執しています。確かに、メインスレッドに無限ループを設定すると、UI(したがってメニューバー)がフリーズするため、マルチスレッドを使用する必要がありますか?

これまでの私のコードは次のとおりです。

import java.awt.Color;
import java.awt.Graphics;

import javax.swing.JPanel;

@SuppressWarnings("serial")
public class GameCanvas extends JPanel {

    public void paint(Graphics g) {
        while (true) {
            g.setColor(Color.DARK_GRAY);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

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

@SuppressWarnings("serial")
public class Main extends JFrame {

    GameCanvas canvas = new GameCanvas();
    final int FRAME_HEIGHT = 400;
    final int FRAME_WIDTH = 400;

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

    public Main() {
        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);
    }
}

ポインタやヒントはありますか?ループはどこに置くべきですか?私のメインクラスですか、それともGameCanvasクラスですか?

4

3 に答える 3

13

ゲームループ(モデル)は、GUIクラス(ビュー)の近くに配置しないでください。GUIクラスを使用しますが、仲介者(コントローラー)を介して実行したい場合もあります。それが正しく行われていることを確認する良い方法は、モデルに単一の「includejavax.swing。???」がないことを確認することです。

あなたができる最善のことは、ゲームループをそれ自身のスレッドに保つことです。GUIに変更を加えたいときはいつでも、SwingWorkerまたは幼い子供たちが今使用しているものを使用して、その1回の操作だけでGUIスレッドに強制的に適用します。

これは、GUI操作(コントローラーを構成する)の観点から考えることができるため、実際には素晴らしいものです。たとえば、移動の背後にGUIロジックを持つ「移動」というクラスがあるとします。ゲームループは、適切な値(移動するアイテム、最終的な場所)を使用して「移動」をインスタンス化し、それをGUIループに渡して処理する場合があります。

その時点に到達すると、GUI操作ごとに簡単な「元に戻す」を追加するだけで、任意の数の操作を簡単に元に戻すことができることに気付きます。また、SwingGUIをWebGUIに置き換える方が簡単です...

于 2010-05-18T23:46:57.520 に答える
6

ゲームループ用に1つのスレッドが必要であり、マウスクリックやキー押下などのSwingUIイベントを処理するために1つのスレッドが必要です。

Swing APIを使用すると、イベントディスパッチスレッドと呼ばれるUI用の追加スレッドが自動的に取得されます。コールバックは、メインスレッドではなく、このスレッドで実行されます。

プログラムの実行時にゲームを自動的に開始する場合は、メインスレッドでゲームループを実行できます。Swing GUIを使用してゲームを開始および停止する場合は、メインスレッドにGUIを開始させると、ユーザーがゲームを開始したいときにGUIがゲームループの新しいスレッドを作成できます。

いいえ、ゲームループをメインスレッドに入れてもメニューバーはフリーズしません。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    
    }
}
于 2010-05-21T00:02:54.037 に答える
4

Javaは、イベント駆動型プログラミングに非常に適しています。基本的に、タイマーイベントを設定してリッスンします。'tick-tock'ごとに、ゲームロジックを更新します。各GUIイベントで、ゲームロジックメソッドが読み取るデータ構造を更新します。

于 2010-05-18T23:51:37.623 に答える