Domanda

Sto cercando di fare un semplice gioco in 2D in Java.

Finora ho un JFrame, con una barra dei menu, e una classe che si estende JPanel e le sostituzioni è il metodo paint. Ora, ho bisogno di ottenere un ciclo di gioco in corso, in cui vi aggiornerò la posizione delle immagini e così via. Tuttavia, mi sono bloccato il modo migliore per raggiungere questo obiettivo. Dovrei usare il multi-threading, perché sicuramente, se si mette un ciclo infinito sul thread principale, l'interfaccia utente (e quindi la mia barra dei menu) si blocca in su?

Ecco il mio codice finora:

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);
    }
}

Tutti gli indicatori o suggerimenti? Dove devo mettere il mio anello? Nella mia classe principale, o la mia classe GameCanvas?

È stato utile?

Soluzione

È necessario un thread per voi gioco loop e un thread per gestire gli eventi swing dell'interfaccia utente come clic del mouse e tasti premuti.

Quando si utilizza l'API di swing, si ottiene automaticamente un thread aggiuntivo per l'interfaccia utente chiamato thread evento spedizione. I suoi callback vengono eseguiti su questo thread, non è il thread principale.

Il filo conduttore è bene per il vostro ciclo di gioco, se si desidera che il gioco per iniziare automaticamente quando i programmi piste. Se si desidera avviare e fermare il gioco con una GUI swing, quindi hanno poi thread principale avviare una GUI, quindi l'interfaccia grafica in grado di creare un nuovo thread per il ciclo di gioco quando l'utente vuole iniziare il gioco.

No, la vostra barra dei menu non sarà congelare se si mette il ciclo di gioco nel thread principale. La vostra barra dei menu si congelerà in su se i tuoi callback dell'oscillazione impiegano molto tempo alla fine.

I dati che viene condiviso tra i fili dovrà essere protetto con serratura.

ti suggerisco di fattore il codice Passa propria classe e solo mettere il ciclo di gioco all'interno della vostra classe principale. Se si utilizza il thread principale per il ciclo di gioco, questa è una vaga idea di come si potrebbe progettare.

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    
    }
}

Altri suggerimenti

Il ciclo di gioco (modello) non dovrebbe essere nemmeno lontanamente le tue classi GUI (vista). Utilizza le classi GUI - ma anche che, probabilmente, si vuole fare attraverso un intermediario (controllore). Un buon modo per garantire che si sta facendo è giusto controllare che il vostro modello non ha un unico "includono javax.swing. ???".

La cosa migliore che si possa fare è quello di mantenere il ciclo di gioco in proprio filo esso è. Ogni volta che si desidera fare un cambiamento nella GUI, utilizzare SwingWorker o qualsiasi altra cosa i ragazzi giovani usano ora per forzarlo sulla filettatura GUI per solo che una sola operazione.

Questo è in realtà impressionante perché ti fa pensare in termini di operazioni di GUI (che costituirebbe il controller). Per esempio, si potrebbe avere una classe chiamata "Move" che avrebbe la logica GUI dietro una mossa. Il tuo ciclo di gioco potrebbe creare un'istanza di un "Move" con i valori giusti (elemento da spostare, la posizione finale) e passarlo a un ciclo di GUI per l'elaborazione.

Una volta che si arriva a quel punto, si rende conto che la semplice aggiunta di un "undo" banale per ogni operazione GUI consente di annullare facilmente qualsiasi numero di operazioni. Troverete anche più facile per sostituire il vostro GUI swing con un web GUI ...

Java è davvero adatto per event-driven di programmazione . In sostanza, impostare un evento timer e ascoltare. Ad ogni 'tic-tac' di aggiornare il tuo logica di gioco. Ad ogni GUI-evento di aggiornare i strutture di dati che il metodo logica di gioco leggerà.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top