ntro.ca

        • Contrats de classe
        • Liens utiles
        • Calendrier
        • Calendrier groupe 3
        • Calendrier groupes 1, 2
        • Structure du cours
        • Évaluations
        • Matériel à se procurer
        • Les profs
          • Marc-Olivier Tremblay
          • Mathieu Bergeron
        • Module 1.1: installation + trier des cartes
        • Module 1.2: rappels POO
          • URL dépôt Git à remettre
        • Module 1.3: tableau d'objets
        • Examen 1
        • Validation des ateliers
        • Module 2.1: données JSON
        • Module 2.2: données en Java
        • Module 2.3: récursivité
        • Examen 2
        • Validation des ateliers
        • Module 3.1: structure générique
        • Module 3.2: efficacité (1)
        • Module 3.3: efficacité (2)
        • Examen 3
        • Validation des ateliers
        • Module 4.1: liste naïve
        • Module 4.2: liste par tableau
        • Module 4.3: liste chaînée
        • Examen 4
        • Validation des ateliers
        • Module 5.1: mappage naïf
        • Module 5.2: mappage par hachage
        • Module 5.3: mappage par arbre
        • Examen 5
        • Validation des ateliers
        • Travail de rattrapage
        • Projets vedettes
          • Contrat gr1
          • Contrat gr2
          • Contrat gr3
        • Survol
        • Structure
        • Calendrier semaines
          • Calendrier gr1
          • Calendrier gr2
          • Calendrier gr3
        • Utilisation IA
        • Évaluations
        • Exemples de pages
        • Exemples de jeu
        • Jeux choisis
        • Réponses à vos questions
        • Module 1: créer le projet
        • Module 2: concevoir l'application
        • Module 3: vues NtroFx
        • Module 4: modèle et navigation
        • Module 5: ajouter le dorsal, modifier le modèle
        • Module 6: améliorer l'affichage
        • Module 7: jeu en 2d
        • Module 8: client/serveur
        • Module 9: plusieurs instances du même modèle
        • Guide de style 4F5
        • TP1
        • Examen 1
        • TP2
        • Examen 2
        • Projet de fin de session
        • Calendrier
        • Évaluations
        • Structure du cours
        • Contrat de classe
        • Le prof
        • 01: Windows et Word
          • Astuces et raccourcis
        • 02: Word
          • Exercice Word: insertion d'éléments spéciaux
          • Exercice Word: tableaux
        • 03: Word
          • Exercice Word: références
          • TP01: Word (15%)
        • 04: Word
        • 05: PowerPoint
          • TP02: PowerPoint (10%)
        • 06: Examen Word (20%)
        • 07: Excel
        • 08: Excel
        • 09: Excel
          • TP03: Excel (15%)
        • 10: Excel
        • 11: Examen Excel (20%)
        • 12: Access
        • 13: Access
        • 14: Access
        • 15: Examen Access
      • Sondage H2023 (dept. info)
      • Vision H2023 (dept. info)
      • P1) exercices interactifs de lecture
      • P2) transition Excel vers Python
        • Atelier 2: un exemple
      • Index
      • Point de vue sur l'IA
    Tutoriel 7: projet pong minimal
    • Tutoriel 7: projet pong minimal
      • Étape 1) créer le projet pong07 à partir de dep07
      • Étape 2) modifier le Monde2d et ses objets
        • Créer un enum Position pour différencier les palettes GAUCHE et DROITE
        • Créer un enum ActionJoueur pour les actions du joueur
        • Créer la classe Palette2d
        • Classe MondeDepart2d
        • Classe Balle2d
      • Vérifier l’état courant du projet
        • Classe Balle2d
      • Vérifier l’état courant du projet
        • Réagir aux actions des joueurs (comme dans dep07_extra01)
      • Vérifier l’état courant du projet

    Tutoriel 7: projet pong minimal #

    Étape 1) créer le projet pong07 à partir de dep07 #

    1. Dans un GitBash à la racine du dépôt Git

      $ cp -rf dep07 pong07
      
    2. Modifier settings.gradle pour ajouter l’include

      include 'pong07'
      
    3. Vérifier que pong07 s’exécute

      $ sh gradlew pong07
      
    4. Dans VSCode, faire un clean workspace pour afficher le projet pong06

    Étape 2) modifier le Monde2d et ses objets #

    Créer un enum Position pour différencier les palettes GAUCHE et DROITE #

    1. Créer le paquet commun.enums

    2. Dans le paquet commun.enums, créer l’enum Position

      public enum Position {
      
          GAUCHE, DROITE;
      }
      

    Créer un enum ActionJoueur pour les actions du joueur #

    1. Dans le paquet commun.enums, créer l’enum ActionJoueur

      public enum ActionJoueur {
      
          MONTER, DESCENDRE, ARRETER;
      }
      

    Créer la classe Palette2d #

    1. Dans le paquet commun.monde2d, créer la classe Palette2d

    2. Ajuster la signature de la classe:

      public class Palette2d extends Object2dFx {
      
          // ...
      
    3. Avec Ctrl+., ajouter l’import de Object2dFx

    4. Avec Ctrl+., créer les méthodes obligatoires

      • s’assurer de retirer l’exception ajoutée par VSCode

        public class Palette2d extends Object2dFx {
        
            @Override
            public void onAddedToWorld() {
        
            }
        
            @Override
            public void drawOnWorld(GraphicsContext gc) {
        
            }
        
            @Override
            protected boolean onMouseEvent(World2dMouseEventFx mouseEvent) {
        
                return false;
            }
        
        }
        
    5. Ajouter un constructeur où on commence à initialiser la palette

      public class Palette2d extends Object2dFx {
      
          private Position position;
      
          public Palette2d(Position position) {
              super();
      
              this.position = position;
      
              setWidth(20);
              setHeight(100);
          }
      
          // ...
      
    6. Dans la méthode onAddedToWorld, positionner la palette au bon endroit

      @Override
      public void onAddedToWorld() {
          if(position == Position.GAUCHE) {
      
              setTopLeftX(10);
      
          }else {
      
              setTopLeftX(getWorldWidth() - getWidth() - 10);
          }
      
          setTopLeftY(getWorldHeight()/2 - getHeight()/2);
      }
      
    7. Dans la méthode drawOnWorld, ajouter le code pour dessiner la palette

      @Override
      public void drawOnWorld(GraphicsContext gc) {
          gc.setFill(Color.BLACK);
      
          gc.fillRect(getTopLeftX(),
                      getTopLeftY(),
                      getWidth(),
                      getHeight());
      }
      

    Classe MondeDepart2d #

    1. Ajouter des attributs pour les palettes

      public class MondeDepart2d extends World2dFx {
      
          Palette2d paletteGauche = new Palette2d(Position.GAUCHE);
          Palette2d paletteDroite = new Palette2d(Position.DROITE);
      
          // ...
      
    2. Modifier le constructeur

      public class MondeDepart2d extends World2dFx {
      
          // ...
      
          public MondeDepart2d() {
              super();
      
              addObject2d("balle",  2, new Balle2d(paletteGauche, paletteDroite));
      
              addObject2d("gauche", 2, paletteGauche);
              addObject2d("droite", 2, paletteDroite);
      
              addObject2d("terrain",1, new Terrain2dDepart());
          }
      
          // ...
      
    3. Avec Ctrl+. créer le constructeur pour Balle2d

    Classe Balle2d #

    1. Ajouter des attributs, modifier le constructeur

      public class Balle2d extends Object2dFx {
      
          private static final double CONST_A = 900;
          private static final double CONST_B = 0.8;
      
          // ajouter les attributs
          private Palette2d paletteGauche;
          private Palette2d paletteDroite;
      
          public Balle2d(Palette2d paletteGauche, 
                         Palette2d paletteDroite) {
              super();
      
              this.paletteGauche = paletteGauche;
              this.paletteDroite = paletteDroite;
      
              setWidth(20);           
              setHeight(20);
          }
      
    2. Créer la méthode lancerBalle

      private void lancerBalle() {
          setTopLeftX(30);
          setTopLeftY(30);
      
          setSpeedX(200);
          setSpeedY(150);
      }
      
    3. Modifier la méthode onAddedToWorld

      @Override
      public void onAddedToWorld() {
          lancerBalle();
      }
      

    Vérifier l’état courant du projet #

    1. Dans un GitBash à la racine du dépôt Git

      $ sh gradlew pong07
      

    Classe Balle2d #

    1. Changer comment la balle se comporte:

      @Override
      public void onTimePasses(double secondsElapsed) {
          super.onTimePasses(secondsElapsed);
      
          if(balleFrappeMurGauche()) {
      
              lancerBalle();
      
          }else if(balleFrappeMurDroit()) {
      
              lancerBalle();
      
          }else if(balleFrappePalette(paletteGauche)) {
      
              balleRebondiSurPalette(paletteGauche);
      
          }else if(balleFrappePalette(paletteDroite)) {
      
              balleRebondiSurPalette(paletteDroite);
      
          }else if(balleFrappePlafond()) {
      
              balleRebondiSurPlafond();
      
          }else if(balleFrappePlancher()) {
      
              balleRebondiSurPlancher();
          }
      
      }
      
      private void balleRebondiSurPlancher() {
          setTopLeftY(getWorldHeight() - getHeight());
          setSpeedY(-1 * getSpeedY());
      }
      
      private boolean balleFrappePlancher() {
          return getTopLeftY() + getHeight() > getWorldHeight();
      }
      
      private void balleRebondiSurPlafond() {
          setTopLeftY(0);
          setSpeedY(-1 * getSpeedY());
      }
      
      private boolean balleFrappePlafond() {
          return getTopLeftY() < 0;
      }
      
      private void balleRebondiSurPalette(Palette2d palette) {
          if(palette == paletteGauche) {
      
              setTopLeftX(palette.getTopLeftX() + palette.getWidth());
      
          }else {
      
              setTopLeftX(palette.getTopLeftX() - getWidth());
          }
      
          setSpeedX(-1 * getSpeedX());
      }
      
      private boolean balleFrappePalette(Palette2d palette) {
          return collidesWith(palette);
      }
      
      private boolean balleFrappeMurDroit() {
          return getTopLeftX() + getWidth() > getWorldWidth();
      }
      
      private boolean balleFrappeMurGauche() {
          return getTopLeftX() < 0;
      }
      

    Vérifier l’état courant du projet #

    1. Dans un GitBash à la racine du dépôt Git

      $ sh gradlew pong07
      

    Réagir aux actions des joueurs (comme dans dep07_extra01) #

    1. Dans le paquet frontal.evenements, créer la classe EvtBougerPalette

      public class EvtBougerPalette extends Event {
      
          private Position     position;
          private ActionJoueur actionJoueur;
      
          public EvtBougerPalette setPosition(Position position) {
              this.position = position;
              return this;
          }
      
          public EvtBougerPalette setActionJoueur(ActionJoueur actionJoueur) {
              this.actionJoueur = actionJoueur;
              return this;
          }
      
          //...
      
    2. Dans VueB, ajouter le code pour gérer les touches:

      public class VueB extends ViewFx {
      
          // ...
      
          @Override
          public void initialize() {
      
              // ...
      
              rootNode().setFocusTraversable(true);
              rootNode().requestFocus();
              rootNode().addEventFilter(KeyEvent.KEY_PRESSED, evtFx -> {
      
                  if(evtFx.getCode().equals(KeyCode.W)) {
      
                      Ntro.newEvent(EvtBougerPalette.class)
                          .setPosition(Position.GAUCHE)
                          .setActionJoueur(ActionJoueur.MONTER)
                          .trigger();
      
      
                  } else if(evtFx.getCode().equals(KeyCode.S)) {
      
                      Ntro.newEvent(EvtBougerPalette.class)
                          .setPosition(Position.GAUCHE)
                          .setActionJoueur(ActionJoueur.DESCENDRE)
                          .trigger();
      
                  } else if(evtFx.getCode().equals(KeyCode.UP)) {
      
                      Ntro.newEvent(EvtBougerPalette.class)
                          .setPosition(Position.DROITE)
                          .setActionJoueur(ActionJoueur.MONTER)
                          .trigger();
      
                  } else if(evtFx.getCode().equals(KeyCode.DOWN)) {
      
                      Ntro.newEvent(EvtBougerPalette.class)
                          .setPosition(Position.DROITE)
                          .setActionJoueur(ActionJoueur.DESCENDRE)
                          .trigger();
                  }
              });
      
              rootNode().addEventFilter(KeyEvent.KEY_RELEASED, evtFx -> {
      
                      Ntro.newEvent(EvtBougerPalette.class)
                          .setPosition(Position.GAUCHE)
                          .setActionJoueur(ActionJoueur.ARRETER)
                          .trigger();
      
                      Ntro.newEvent(EvtBougerPalette.class)
                          .setPosition(Position.DROITE)
                          .setActionJoueur(ActionJoueur.ARRETER)
                          .trigger();
              });
          }
      
    3. Dans TachesE, ajouter la tache pour capter l’événement:

      public class TachesE {
      
          public static void creerTaches(FrontendTasks tasks) {
      
              creerDonneesVueB(tasks);
      
              tasks.taskGroup("TachesE")
      
                   .waitsFor(created(DonneesVueB.class))
      
                   .contains(subTasks -> {
      
                       tacheE2(subTasks);
      
                       bougerPalette(subTasks); // ajouter
      
                   });
          }
      
      
          // ...
      
          // ajouter
          private static void bougerPalette(FrontendTasks tasks) {
      
              tasks.task("bougerPalette")
      
                   .waitsFor("tacheC2")
      
                   .waitsFor(created(DonneesVueB.class))
      
                   .waitsFor(event(EvtBougerPalette.class))
      
                   .executes(inputs -> {
      
                       EvtBougerPalette evtBougerPalette = inputs.get(event(EvtBougerPalette.class));
                       DonneesVueB      donneesVueB      = inputs.get(created(DonneesVueB.class));
      
                       evtBougerPalette.bougerPalette(donneesVueB);
      
                   });
          }
      
    4. Avec Ctrl+., créer la méthode EvtBougerPalette.bougerPalette

      public class EvtBougerPalette extends Event {
      
          // ...
      
          public void bougerPalette(DonneesVueB donneesVueB) {
              donneesVueB.bougerPalette(position, actionJoueur);
      
          }
      
    5. Avec Ctrl+., créer la méthode DonneesVueB.bougerPalette

      public class DonneesVueB implements ViewData {
      
          // ...
      
          public void bougerPalette(Position position, ActionJoueur actionJoueur) {
      
              monde2d.bougerPalette(position, actionJoueur);
          }
      
    6. Avec Ctrl+., créer la méthode MondeDepart2d.bougerPalette

      public class MondeDepart2d extends World2dFx {
      
          // ...
      
          public void bougerPalette(Position position, ActionJoueur actionJoueur) {
              if(position == Position.GAUCHE) {
      
                  paletteGauche.bouger(actionJoueur);
      
              }else {
      
                  paletteDroite.bouger(actionJoueur);
              }
          }
      
    7. Avec Ctrl+., créer la méthode Palette2d.bouger

      public class Palette2d extends Object2dFx {
      
          // ...
      
          public void bouger(ActionJoueur actionJoueur) {
              if(actionJoueur == ActionJoueur.MONTER) {
      
                  setSpeedY(-200);
      
              } else if(actionJoueur == ActionJoueur.DESCENDRE) {
      
                  setSpeedY(+200);
      
              } else {
      
                  setSpeedY(0);
              }
          }
      

    Vérifier l’état courant du projet #

    1. Dans un GitBash à la racine du dépôt Git

      $ sh gradlew pong07
      
      • NOTE: voir dep07_extra02 pour une gestion améliorée des touches du clavier
    Creative Commons License Creative Commons Attribution Creative Commons ShareAlike
    • Tutoriel 7: projet pong minimal
      • Étape 1) créer le projet pong07 à partir de dep07
      • Étape 2) modifier le Monde2d et ses objets
        • Créer un enum Position pour différencier les palettes GAUCHE et DROITE
        • Créer un enum ActionJoueur pour les actions du joueur
        • Créer la classe Palette2d
        • Classe MondeDepart2d
        • Classe Balle2d
      • Vérifier l’état courant du projet
        • Classe Balle2d
      • Vérifier l’état courant du projet
        • Réagir aux actions des joueurs (comme dans dep07_extra01)
      • Vérifier l’état courant du projet