J'essaie de faire un jeu 2D simple en Java.
Jusqu'à présent, j'ai un Voici mon code jusqu'à présent: P > jframe code>, avec une menuGar et une classe qui s'étend
jPanel code> et remplace sa méthode
peinture code>. Maintenant, j'ai besoin d'obtenir une boucle de jeu, où je vais mettre à jour la position des images et ainsi de suite. Cependant, je suis coincé à la meilleure façon de y parvenir. Devrais-je utiliser multi-threading, car sûrement, si vous mettez une boucle infinie sur le thread principal, l'interface utilisateur (et donc ma barre de menu) gèlera? P>
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);
}
}
3 Réponses :
Votre boucle de jeu (modèle) ne doit être nulle part près de vos classes d'interface graphique (voir). Il utilise vos cours d'interface graphique - mais même que vous voulez probablement faire via un intermédiaire (contrôleur). Un bon moyen de vous assurer que vous faites bien, c'est vérifier que votre modèle ne dispose pas d'un seul «incluent Javax.swing. ???». P>
La meilleure chose à faire est de garder la boucle de jeu dans son propre fil. Chaque fois que vous souhaitez modifier l'interface graphique, utilisez SwingWorker ou quels que soient les jeunes enfants, utilisez-la maintenant pour le forcer sur le fil de l'interface graphique pour une seule opération. P>
Ceci est réellement génial car cela vous fait penser en termes d'opérations d'interface graphique (qui constituerait votre contrôleur). Par exemple, vous pourriez avoir une classe appelée «Move» qui aurait la logique de l'interface graphique derrière un mouvement. Votre boucle de jeu pourrait instancier un «déplacement» avec les bonnes valeurs (élément à déplacer, emplacement final) et transmettez-la à une boucle d'interface graphique pour le traitement. P>
Une fois que vous arrivez à ce point, vous réalisez que l'ajout d'un «annulation» trivial pour chaque opération d'interface graphique vous permet de défaire facilement un certain nombre d'opérations. Vous trouverez également plus facilement de remplacer votre interface graphique swing avec une interface graphique Web ... p>
Java est vraiment adapté à Programmation axée sur les événements . Fondamentalement, configurez un événement de minuterie et écoutez. À chaque 'Tick-TOCK', vous mettez à jour votre logique de jeu. Dans chaque cas d'interface graphique, vous mettez à jour vos structures de données que la méthode de la logique de jeu sera lue. P>
Vous avez besoin d'un fil pour vous boucle de jeu et un fil pour gérer des événements de l'interface utilisateur Swing comme les clics de souris et pressions sur les touches.
Lorsque vous utilisez l'API Swing, vous obtenez automatiquement un fil supplémentaire pour votre interface utilisateur appelé le thread de répartition des événements. Vos callbacks sont exécutés sur ce fil, pas le fil principal. P>
Votre thread principal est très bien pour votre boucle de jeu si vous voulez que le jeu démarre automatiquement lors de l'exécution des programmes. Si vous voulez démarrer et arrêter le jeu avec une interface graphique Swing, alors alors thread principal démarrer une interface graphique, l'interface graphique peut créer un nouveau thread pour la boucle de jeu lorsque l'utilisateur veut lancer le jeu. P>
non, votre barre de menu ne gèle pas si vous mettez votre boucle de jeu dans le thread principal. Votre barre de menu geler si votre callbacks Swing prennent beaucoup de temps à la fin. P>
données partagées entre les threads doivent être protégés avec des serrures. P>
Je vous suggère de facteur votre code Swing dans sa propre classe et seulement mettre votre boucle de jeu dans votre classe principale. Si vous utilisez le fil principal de votre boucle de jeu, ceci est une idée approximative de la façon dont vous pourriez concevoir. P>
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 } }