2016-03-07 2 views
0

J'essaye de construire un jeu simple en Java. Ran dans le problème de JTextPanel ne pas mettre à jour jusqu'à ce que la boucle de jeu se termine, ce qui, bien sûr, n'est pas une bonne expérience pour le joueur. Je ne suis pas familier avec le multithreading mais j'essaie de le comprendre. Je peux maintenant exécuter du code séparé dans plusieurs threads, mais je n'arrive pas à comprendre comment faire interagir les threads. Il est fort probable qu'il me manque quelque chose de simple, mais je ne peux pas le trouver en cherchant, alors je me jette à votre merci. Je suis suspendu par un fil ...Multithread sans objets étroitement couplés

Classe de contrôleur et fil principal. J'ai besoin du gamePanel et du jeu pour fonctionner séparément. J'ai essayé d'exécuter la classe Game dans un thread séparé, mais le code du jeu ne fonctionne pas dans le gamePanel.

Controller:

import javax.swing.JFrame; 
import javax.swing.SwingUtilities; 



public class Controller_LetterFall{ 
public static void main(String[] args){ 
    SwingUtilities.invokeLater(new Runnable(){ 
     public void run(){ 
      new MainFrame(); 
     } 
    }); 

    } 
} 

et la classe mainframe. J'essaie d'exécuter gameplay() dans un nouveau thread.

package wordFall; 

import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JTextArea; 

import java.awt.BorderLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

public class MainFrame extends JFrame implements Runnable { 

private GamePlay game; 
private TextPanel gamePanel; 
private Header header; 
private Player player; 
private Dictionary dictionary; 
private GamePlay game; 

public MainFrame(){ 
super("Game"); 
    // Set the size of the frame. 
setSize(400,600); 
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
setVisible(true); 


// Establish default player. 
player = new Player(); 
dictionary = new Dictionary(); 
game = new GamePlay(); 
header = new Header(); 
gamePanel = new TextPanel(); 
add(header, BorderLayout.NORTH); 
add(gamePanel, BorderLayout.CENTER); 

this.game.setBoardInterface( 
     new BoardInterface(){ 
      @Override 
      public void redraw(String text) { 
       gamePanel.appendText(text); 
      } 
     }); 
    } 
    @Override 
    public void run() { 
     game.play(); 
     System.out.println("The game is over."); 
    } 
} 

Toute aide serait appréciée.

+0

Je ne vois aucun thread dans votre exemple. –

Répondre

2

Vous avez besoin de quelque chose comme un conteneur de données thread-safe. Appelons le GameData. Votre objet GamePlay doit savoir que l'objet GameData et l'interface utilisateur doivent également le savoir car les modifications apportées par l'utilisateur doivent être propagées à l'objet GameData.

Dans votre objet GamePlay, vous pouvez rechercher les modifications de l'objet GameData chaque seconde. S'il y a des changements que vous avez quelque chose à faire si ce n'est pas le cas ..

Mais il serait préférable d'utiliser une approche comme l'événement, c'est-à-dire le Observer Pattern. Si des modifications sont effectuées par l'interface utilisateur, le GamePlay sera averti par l'objet observable GameData. En outre, l'interface utilisateur peut également être notifiée lorsque les données changent.

Ceci dissocie très clairement les problèmes et suit le modèle du contrôleur de vue modèle.

2

Eh bien, dans ce cas, votre objet MainFrame est en cours de construction à partir du thread du répartiteur swing. Comme vous l'avez dit, vous devez commencer un nouveau thread pour gérer le jeu. En supposant que vous auriez ce code dans une méthode d'instance d'un objet MainFrame, ce serait:

Thread thr = new Thread(this); 
thr.start(); 

Ensuite, chaque fois que votre fil de jeu séparé veut mettre à jour l'objet ui, il ne devrait pas le faire directement, mais utilisez SwingUtilities .invokeLater:

SwingUtilities.invokeLater(new Runnable() { 
    @Override 
    public void run() { 
     /* Update the ui element... */ 
}}); 

ce runnable sera exécuté dans un thread de répartiteur de swing quand il aura le temps.

+0

Cela fonctionnera bien tant que les mises à jour ne sont pas trop fréquentes et, surtout, que le runnable n'a pas de courses de données ou de problèmes de synchronisation (s'il accède à des champs modifiés dans le thread de jeu, . –

+0

Que serait un problème en cas de changements trop fréquents dépendant des actions du fil de jeu? –

+0

Ahh, pressé ajouter par accident.J'étais sur le point de dire que la chose sur les courses de données est correcte et la synchronisation/collections concurrentes/tout ce qui est nécessaire si les données partagées sont accessibles –