IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

avec Java Discussion :

Passer d'un jFrame a un jeu.


Sujet :

avec Java

  1. #21
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2018
    Messages
    15
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Mai 2018
    Messages : 15
    Points : 3
    Points
    3
    Par défaut
    Donc je serais mieux de refaire un autre jeu ?

  2. #22
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Bah, ça dépend. C'est quoi le but de ce projet. C'est quoi qu'on vous demande au juste ? C'est déjà assez bizarre pour moi de voir que tu intègres juste un jeu fait par d'autres dans un projet. C'est peut-être ce qu'on vous demande, mais j'aurais trouvé plus logique qu'on vous demande de le coder vous même. Surtout qu'en théorie, tu n'as pas le droit le faire si les auteurs ne l’autorise pas. Un code open source n'est pas forcément libre.
    Ensuite, faut voir si ça te gêne ou pas. Au pire, si le jeu tourne en mémoire, ça consomme du cpu et de la mémoire. Si tu le lances une fois, ce n'est pas très important. Et pour la stacktrace, ça peut s'expliquer. Tu intègres un jeu qui n'est pas fait pour l'être.
    Tu as aussi l'option de le faire tourner comme un programme externe, comme ça il n'aura pas d'influence sur ton programme, et il tournera dans sa JVM comme c'est prévu.
    Ou tu peux choisir un autre jeu. C'est toi qui vois.

    En tout cas, voici un exemple pour faire tourner le jeu en externe (le fichier jar du jeu doit être mis dans le dossier de lancement de ton programme) (dans un IDE, pour tester, le dossier d'exécution, c'est le dossier du projet). J'ai simulé ton cas en faisant juste une fenêtre avec un togglebutton pour lancer/arrêter.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    import java.awt.GridBagLayout;
    import java.io.IOException;
    import java.util.Arrays;
     
    import javax.swing.JFrame;
    import javax.swing.JOptionPane;
    import javax.swing.JPanel;
    import javax.swing.JToggleButton;
     
    public class Demo {
     
    	private static final String FRAME_TITLE = "Lanceur PacMan";
    	private static final String START_LABEL = "Démarrer";
    	private static final String STOP_LABEL = "Arrêter";
    	private static Process process;
     
    	public static void main(String[] args) {
     
    		JFrame frame = new JFrame(FRAME_TITLE);
    		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     
    		// ça c'est pour arrêter le pacman si on ferme la fenêtre du lanceur
    		Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
     
    			@Override
    			public void run() {
    				if ( process!=null ) {
    					process.destroy();
    				}
    			}
    		}));
     
    		// la fenêtre affiche juste un bouton au milieu
    		JPanel panel = new JPanel(new GridBagLayout());
    		frame.add(panel);
     
    		// on utilise un toggle button pour lancer le jeu ou l'arrêter
    		JToggleButton button = new JToggleButton(START_LABEL);
    		button.addActionListener(e-> togglePacman(button));
     
    		panel.add(button);
     
    		// on affiche la fenêtre du lanceur
    		frame.pack();
    		frame.setLocationRelativeTo(null);
    		frame.setVisible(true);
     
    	}
     
    	private static void togglePacman(JToggleButton button) {
    		if ( !button.isSelected() ) {
    			// si le bouton a été cliqué alors qu'il était "enfoncé", alors on arrête le jeu
    			process.destroy(); // on kill le process
    			process=null;
    			button.setText(START_LABEL); // on remet le texte pour redémarrer
    		}
    		else {
    			// on lance le programme de jeu dans une autre jvm
    			ProcessBuilder processBuilder = new ProcessBuilder(Arrays.asList("java.exe","-jar","JavaPacman.jar")).inheritIO();
    			try {
    				process = processBuilder.start();
    				// on lance un thread qui va attendre que le programme se termine pour remettre le bouton correctement
    				new Thread(new WaitForPacman(process,button)).start();
    				button.setText(STOP_LABEL); // on met le texte pour arrête le jeu
    			} catch (IOException e) {
    				e.printStackTrace();
    				JOptionPane.showMessageDialog(null, "Le jeu n'a pas démarré. Voir la console pour l'erreur.");
    				button.setSelected(false);
    			}
    		}
    	}
     
    	private static class WaitForPacman implements Runnable {
    		private Process process;
    		private JToggleButton button;
     
    		public WaitForPacman(Process process, JToggleButton button) {
    			this.process=process;
    			this.button=button;
    		}
     
    		@Override
    		public void run() {
    			try {
    				process.waitFor(); // on attend que le jeu de pacman se termine
    			} catch (InterruptedException e) {
    			}
    			// on remet le bouton pour redémarrer le jeu
    			button.setText(START_LABEL);
    			button.setSelected(false);
    			process=null;
    		}
    	}
     
     
    }
    Le même avec deux boutons, un pour démarrer, un pour arrêter :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    import java.awt.GridBagConstraints;
    import java.awt.GridBagLayout;
    import java.awt.Insets;
    import java.io.IOException;
    import java.util.Arrays;
     
    import javax.swing.BorderFactory;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JOptionPane;
    import javax.swing.JPanel;
     
    public class Demo2 {
     
    	private static final String FRAME_TITLE = "Lanceur PacMan";
    	private static final String START_LABEL = "Démarrer";
    	private static final String STOP_LABEL = "Arrêter";
    	private static Process process;
     
    	public static void main(String[] args) {
     
    		JFrame frame = new JFrame(FRAME_TITLE);
    		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     
    		// ça c'est pour arrêter le pacman si on ferme la fenêtre du lanceur
    		Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
     
    			@Override
    			public void run() {
    				if ( process!=null ) {
    					process.destroy();
    				}
    			}
    		}));
     
    		// la fenêtre affiche juste deux boutons, un pour démarre, un pour arrêter
    		JPanel panel = new JPanel(new GridBagLayout());
    		frame.add(panel);
     
    		// on utilise un toggle button pour lancer le jeu ou l'arrêter
    		JButton startButton = new JButton(START_LABEL);
    		JButton stopButton = new JButton(STOP_LABEL);
    		stopButton.setEnabled(false);
    		startButton.addActionListener(e-> togglePacman(startButton, stopButton));
    		stopButton.addActionListener(e-> togglePacman(startButton, stopButton));
     
    		GridBagConstraints gbc = new GridBagConstraints();
    		gbc.gridy=0;
    		gbc.gridx=GridBagConstraints.RELATIVE;
    		gbc.insets = new Insets(0, 0, 0, 10);
    		panel.add(startButton,gbc);
    		panel.add(stopButton,gbc);
    		panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 0));
     
    		// on affiche la fenêtre du lanceur
    		frame.pack();
    		frame.setLocationRelativeTo(null);
    		frame.setVisible(true);
     
    	}
     
    	private static void togglePacman(JButton startButton, JButton stopButton) {
    		if ( !startButton.isEnabled() ) {
    			// si le bouton start est désactivé, alors on arrête le jeu
    			process.destroy(); // on kill le process
    			process=null;
    			startButton.setEnabled(true);// on réactive le bouton pour redémarrer
    			stopButton.setEnabled(false);
    		}
    		else {
    			// on lance le programme de jeu dans une autre jvm
    			ProcessBuilder processBuilder = new ProcessBuilder(Arrays.asList("java.exe","-jar","JavaPacman.jar")).inheritIO();
    			try {
    				process = processBuilder.start();
    				// on lance un thread qui va attendre que le programme se termine pour remettre le bouton correctement
    				new Thread(new WaitForPacman(process,startButton, stopButton)).start();
    				startButton.setEnabled(false);
    				stopButton.setEnabled(true);; // on active le bouton pour arrête le jeu
    			} catch (IOException e) {
    				e.printStackTrace();
    				JOptionPane.showMessageDialog(null, "Le jeu n'a pas démarré. Voir la console pour l'erreur."); 
    			}
    		}
    	}
     
    	private static class WaitForPacman implements Runnable {
    		private Process process;
    		private JButton startButton;
    		private JButton stopButton;
     
    		public WaitForPacman(Process process, JButton startButton, JButton stopButton) {
    			this.process=process;
    			this.startButton=startButton;
    			this.stopButton=stopButton;
    		}
     
    		@Override
    		public void run() {
    			try {
    				process.waitFor(); // on attend que le jeu de pacman se termine
    			} catch (InterruptedException e) {
    			}
    			// on remet le bouton pour redémarrer le jeu
    			startButton.setEnabled(true);
    			stopButton.setEnabled(false);
    			process=null;
    		}
    	}
     
     
    }

  3. #23
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2018
    Messages
    15
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Mai 2018
    Messages : 15
    Points : 3
    Points
    3
    Par défaut
    En fait on nous demande de faire choisir un jeu et de le modifier ( le code, les images...)

  4. #24
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Donc si tu dois modifier le code du jeu, alors fais-le.

    Il y a deux principaux problèmes :

    1. Avoir le contrôle sur la fenêtre et le moteur du jeu pour pouvoir l'arrêter
    2. Pourvoir arrêter la boucle de jeu, rapidement et sans erreur (ou du moins, sans qu'elles se voient pour faire simple).


    La boucle de jeu est définie dans la classe Display :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
        private class MainLoop implements Runnable {
     
            @Override
            public void run() {
                long desiredFrameRateTime = 1000 / 60;
                long currentTime = System.currentTimeMillis();
                long lastTime = currentTime - desiredFrameRateTime;
                long unprocessedTime = 0;
                boolean needsRender = false;
                while (running) {
                    currentTime = System.currentTimeMillis();
                    unprocessedTime += currentTime - lastTime;
                    lastTime = currentTime;
     
                    while (unprocessedTime >= desiredFrameRateTime) {
                        unprocessedTime -= desiredFrameRateTime;
                        update();
                        needsRender = true;
                    }
     
                    if (needsRender) {
                        Graphics2D g = (Graphics2D) bs.getDrawGraphics();
                        g.setBackground(Color.BLACK);
                        g.clearRect(0, 0, getWidth(), getHeight());
                        g.scale(game.screenScale.getX(), game.screenScale.getY());
                        draw(g);
                        g.dispose();
                        bs.show();
                        needsRender = false;
                    }
                    else {
                        try {
                            Thread.sleep(1);
                        } catch (InterruptedException ex) {
                        }
                    }
     
                }
            }
     
        }
    1. la première chose qu'on doit pouvoir faire, c'est arrêter la boucle while(running)Pour faire çà :
      1. il faut une méthode qu'on va ajouter à la classe
        Code : Sélectionner tout - Visualiser dans une fenêtre à part
        1
        2
        3
        public void stop() {
            running=false;
        }
      2. en multithread et en particulier avec plusieurs cores, le fait d'avoir besoin de modifier running dans un thread alors qu'il est testé dans un autre (celui de la boucle) pose un problème. La modification faite par un thread peut ne pas être vue par l'autre. Un moyen simple et rapide de résoudre le problème est de déclarer la variable volatile :
        Code : Sélectionner tout - Visualiser dans une fenêtre à part
        private volatile boolean running
      3. Un autre souci est qu'il y a une autre boucle à l'intérieur de la boucle while(running) et qu'il faut aussi qu'elle s'arrête quand running devient false.
        Code : Sélectionner tout - Visualiser dans une fenêtre à part
        1
        2
        3
        4
        5
        while (running && unprocessedTime >= desiredFrameRateTime) {
                            unprocessedTime -= desiredFrameRateTime;
                            update();
                            needsRender = true;
                        }
      4. on pourrait interrompre le thread (et donc traiter cette interruption dans le catch(InterruptedException) mais on va s'en passer et laisser mourir le thread tranquille.
        seulement dans la boucle on manipule des composants graphiques qui ne seront plus utilisables lorsqu'on va arrêter le jeu. Il faut donc éviter de le faire, sinon on a une exception. Ce n'est pas très grave parce que ça plante pas le programme, mais on la voit dans la console, donc ce n'est pas très clean. Pour faire simple, on pourrait mettre un try/catch, mais on va utiliser un système qui permet d'intercepter toute exception dans le thread et de faire ce qu'on veut, comme simplement les ignorer pour juste laisser mourir le thread en silence
        Dans la méthode start de Display, on a ajouter un UncaughtExceptionHandler :
        Code : Sélectionner tout - Visualiser dans une fenêtre à part
        1
        2
        3
        4
        5
        6
        7
        8
        9
        Thread thread = new Thread(new MainLoop());
                thread.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
         
        			@Override
        			public void uncaughtException(Thread t, Throwable e) {
        				// ignore all
        			}
        		});
                thread.start();
    2. il est très important de libérer les ressources réservées pour le BufferStrategy
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      public void stop() {
          running=false;
          bs.dispose();
      }
    3. Ensuite, il faut gérer la fenêtre et l'instance de display, pour pouvoir l'arrêter. On va faire une classe de contrôle, et pour simplifier le contrôle, comme, à priori, on ne veut afficher qu'une seul instance de jeu à la fois, on va faire du static.

      En résumé, il s'agit de :

      • conserver une référence sur la JFrame pour pouvoir la fermer (appeler dispose())
      • conserver une référence sur l'instance de Display pour pouvoir arrêter la boucle de jeu (appeler stop())
      • remplacer le comportement de System.exit() lorsqu'on ferme le jeu, mais plutôt de libérer notre instance de contrôle, de fermer la fenêtre et d'arrêter la boucle de jeu
      • d'ajouter un système de callback (le paramètre onStop) pour qu'on puisse gérer l'interface de lancement (pour l'adapter à l'arrêt du jeu par la fenêtre du jeu et non par le bouton de l'interface principale)



      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      78
      79
      80
      81
      82
      83
      mport java.awt.event.WindowAdapter;
      import java.awt.event.WindowEvent;
       
      import javax.swing.JFrame;
       
      import test.br.ol.pacman.PacmanGame;
      import test.br.ol.pacman.infra.Display;
       
      public class PacMan {
       
      	private static final String DEFAULT_NAME = "PacMan";
       
      	private static volatile PacMan pacman;
       
      	private PacmanGame game;
      	private Display view;
      	private JFrame frame;
       
      	private Runnable onStop;
       
      	private PacMan(String name, Runnable onStop) {
      		this.onStop=onStop;
      		game = new PacmanGame();
                      view = new Display(game);
                      frame = new JFrame();
                      setTitle(name);
                      frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
                      frame.addWindowListener(new WindowAdapter() {
       
              	   @Override
              	   public void windowClosing(WindowEvent e) { 
                  	      stop();
              	   }
      		});
                      frame.getContentPane().add(view);
                      frame.pack();
                      frame.setLocationRelativeTo(null);
                      frame.setVisible(true);
                      view.requestFocus();
                      view.start();
      	}
       
      	private void setTitle(String name) {
      		if ( name==null ) {
      			name=DEFAULT_NAME;
      		}
      		frame.setTitle(name);
      	}
       
      	private void shutdown() { 
      		view.stop();
      		frame.dispose();
          	        if ( onStop!=null ) onStop.run();
      	}
       
      	public static synchronized PacMan start(String name, Runnable onStop) {
      		if ( pacman==null ) {
      			pacman = new PacMan(name, onStop);
      		}
      		else {
      			pacman.setTitle(name);
      		}
      		return pacman;
      	}
       
      	public static synchronized void setFrameTitle(String name) {
      		if ( pacman!=null ) {
      			pacman.setTitle(name);
      		}
      	}
       
      	public static boolean isRunning() {
      		return pacman!=null;
      	}
       
      	public static synchronized void stop() {
      		if ( pacman!=null ) {
      			pacman.shutdown();
      			pacman = null;
      		}
      	}
       
      }
    4. Et pour la classe de démo/test, sur base de toggle button :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
       
      import java.awt.GridBagLayout;
       
      import javax.swing.JFrame;
      import javax.swing.JPanel;
      import javax.swing.JToggleButton;
       
      public class Demo {
       
      	private static final String FRAME_TITLE = "Lanceur PacMan";
      	private static final String GAME_TITLE = "PacMan !!!";
      	private static final String START_LABEL = "Démarrer";
      	private static final String STOP_LABEL = "Arrêter";
       
      	public static void main(String[] args) {
       
      		JFrame frame = new JFrame(FRAME_TITLE);
      		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
       
      		JPanel panel = new JPanel(new GridBagLayout());
      		frame.add(panel);
       
       
      		JToggleButton button = new JToggleButton(START_LABEL);
      		button.addActionListener(e-> togglePacman(button));
       
      		panel.add(button);
       
      		frame.pack(); 
      		frame.setVisible(true);
       
      	}
       
      	private static void togglePacman(JToggleButton button) {
      		if ( !button.isSelected() ) {
      			PacMan.stop();
      			button.setText(START_LABEL);
      		}
      		else {
      			button.setText(STOP_LABEL);
      			PacMan.start(GAME_TITLE, ()->resetButton(button));
      		}
      	}
       
      	private static void resetButton(JToggleButton button) {
      		button.setText(START_LABEL);
      		button.setSelected(false);
      	}
       
       
      }

Discussions similaires

  1. passer d'une jframe à une autre à partir d'un jbutton
    Par bensh dans le forum Agents de placement/Fenêtres
    Réponses: 10
    Dernier message: 10/11/2017, 23h41
  2. Passer d'une JFrame à une autre
    Par 6116d dans le forum Agents de placement/Fenêtres
    Réponses: 2
    Dernier message: 18/05/2015, 17h56
  3. Passer d'un JFrame vers un autre en utilisant un vecteur
    Par amal talabi dans le forum Agents de placement/Fenêtres
    Réponses: 6
    Dernier message: 18/09/2012, 18h38
  4. Passer d'une JFrame a une autre
    Par guitariste dans le forum Agents de placement/Fenêtres
    Réponses: 5
    Dernier message: 06/05/2008, 23h01
  5. Passer d'une JFrame à un Jdialog
    Par e1lauren dans le forum Agents de placement/Fenêtres
    Réponses: 4
    Dernier message: 07/11/2006, 16h15

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo