Libgdx Game

dimanche 29 juillet 2012

Manipulation des entrées 1er partie #5


Entrée commune pour les deux plateformes :

---> Introduction
---> Interaction utilisateur avec Android/desktop 
---> Texte
---> Clavier
---> Souris/tactile
---> Conclusion

Introduction

En voilà arrivé à ce stade, on va voir dans ce tutoriel l’interaction de l’utilisateur avec l’app/jeu, sachant qu’on travaille sur deux plateformes Android et Desktop, on va voir dans cette première partie  la manipulation des entrées disponibles sous les deux plateformes et comment Libgdx gère les différences entre ces deux-là, vous allez voir c’est magnifique !! (Si c’est votre premier contact avec Libgdx veuillez voir ces tutoriels ).

Interaction utilisateur avec Android/desktop  

Les utilisateurs de votre application/jeu que vous allez développer vont surement interagir avec, et cela via des périphériques, la gestion des interactions des utilisateurs va s'effectuer dans un seul code source bien qu'on travaille sur deux plateformes différentes, donc le rôle de Libgdx  est de gérer les différences entre les deux et ceci grâce à l’un des modules qu’elle possède (voir modules Libgdx ici) et parmi ces différences :

Sous Desktop,  on utilise la souris et sous Android c’est le toucher tactile, donc sous Android il n’y a pas la détection de mouvement de souris, seulement le glissement de la souris est repérable. On plus sous Android on peut gérer le multi-touch (plusieurs doigts à la foi) ce qui n’est pas possible sous Desktop puisque la souris possède un seul curseur.
Sachant aussi que Libgdx ne fait pas de différence entre les boutons de la souris, seul un bouton est considéré.

Concernant le clavier, c’est clair que pour le desktop il est considéré, mais sous Android plusieurs appareils n’adoptent pas le clavier. Pour gérer ça, Libgdx propose de manipuler un ensemble de touche clavier unique pour toutes les appareils.
Sachant aussi que sous Android il existe un ensemble de touches qui n’existent pas sous l’environnement Desktop tels que : touche de retour, de menu, de recherche…

Bien sûr il y a plein d’autres différences que Libgdx les gères en un code unifié valable pour les deux plateformes. En verra plus de détail dans ce qui suit.


Entrer du texte 
On va commencer par le plus simple, entrer du texte sur une application sous Android ou Desktop.
La procédure de saisissement du texte s’effectuera à travers une boite de dialogue.
Sous Desktop : Une boite de dialogue de type Swing sera ouverte.
Sous Android : Une boite de dialogue Standard sera ouverte.

Cela n’est possible que si on implémente l’interface TextInputListener qui lui, possède deux méthodes :

Input() : Cette méthode est appelée lorsque l’utilisateur aura entré une chaine de caractère et appuyé sur OK

Canceled() : Cette méthode est appelée lorsque l’utilisateur aura fermé la boite de dialogue (sous Desktop) ou appuyé sur le bouton retour (sous Android).

* Voici à quoi ça ressemble en code source :
public class AuditeurTexte implements TextInputListener {
               @Override
               public void input (String text) {
               }
               @Override
               public void canceled () {
               }
            }

* Maintenant pour faire apparaitre la boite de dialogue il faut d’abord instancier la classe AuditeurTexte
AuditeurTexte ecouteur =  new  AuditeurTexte();
Puis, l’indiquer à Libgdx :
Gdx.input.getTextInput(ecouteur, "Titre de la boite", "valeur texte initial");

Pour récapituler un peu les choses je vais vous présenter un code source d’une petite application qui vous demande de saisir du texte puis vous affiche un message.
Le code source est décomposé en 3 parties comme nous l’avons déjà expliqué dans un tutoriel précédant.

* La partie logique contiendra :
package my.works.TutorielBlog;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.TextInputListener;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;

public class ManipulationEntree implements ApplicationListener {
            private SpriteBatch batch ;
            private BitmapFont font ;
            private String texteInitial;
            private String titreBoiteDialogue;
            private String message;
            private boolean afficher;

            @Override
            public void create() {
                        texteInitial = "Entrer votre nom complet";
                        titreBoiteDialogue = "Bienvenu";
                        afficher = false;
                        batch = new SpriteBatch();
                        font = new BitmapFont();
                        Gdx.input.getTextInput(new TextInputListener() {
                                   @Override
                                   public void input(String texteSaisi) {
                                   message = "Bonjour Monsieur <"+texteSaisi+"> Bienvenu au monde des developpeurs";
                                   afficher =true;
                                   }
                                   @Override
                                   public void canceled() {
                                   message = "Au revoir Monsieur et tant pis pour vous";
                                   afficher =true;
                                   }
                        }, titreBoiteDialogue, texteInitial);
            }
            @Override
            public void dispose() {
            }
            @Override
            public void pause() {
            }
            @Override
            public void render() {
                         Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
                         if(afficher)
                         {
                                    batch.begin();
                                    font.draw(batch, message, 10, 200);
                                    batch.end();
                         }
            }
            @Override
            public void resize(int arg0, int arg1) {
            }
            @Override
            public void resume() {
            }
}

* La partie Desktop : elle contient le code lanceur de l’application sous Desktop
package my.works.TutorielBlog;

import com.badlogic.gdx.backends.jogl.JoglApplication;

public class Lanceur {
            public static void main(String[] args) {
                        new JoglApplication (new ManipulationEntree(),"La manipulation des entrées",480,320,false);
            }
}

* La partie Android : elle contient le code lanceur de l’application sous Android
package my.works.LibgdxTutorielAndroid;

import my.works.TutorielBlog.ManipulationEntree;
import com.badlogic.gdx.backends.android.AndroidApplication;
import android.os.Bundle;

public class main extends AndroidApplication {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initialize(new ManipulationEntree(), false);
    }
}

La partie logique se trouve dans le projet desktop avec le lanceur de l’application, contrairement au lanceur Android qui se trouve dans un projet appart. Nous avons déjà parlé de ça en détail dans un tutoriel précédant.

* Voici le résultat sur desktop :

Si vous appuyez sur OK :


Si vous appuyez sur Annuler :


* Maintenant voici le résultat sous Android :


Remarque : cette application n’est fonctionnelle que sur le mode paysage contentez-vous de ça pour l’instant. Pour rendre l’émulateur sous le mode paysage (car par défaut il est en mode portrait), il faut faire : 
Ctrl (qui se trouve à gauche) + F11
KEYPAD_7 : appuyer sur le numéro 7 tout en assurant que la lampe des numéros est éteinte.


Si j’entre mon nom et j’appuie sur OK :

Si j’appuie sur la touche Retour :




Entrées avec Clavier

Comme nous l’avons dit un peu plus haut Libgdx tente de réduire la différence entre les deux plateformes. Elle est caractérisée par l’utilisation de ces deux mécanismes le polling (l’attente active) et la gestion des évènements.

Le polling(l’attente active) :
Un évènement clavier déclenché par un utilisateur (en appuyant ou en relâchant une touche du clavier) génère un code qui identifie la clé (touche) concernée.
Android et Desktop ne possède pas les mêmes code pour les touches du clavier, pour cela Libgdx offre sa propre table de code des touches clavier, voir la classe Keys de Libgdx. Le mécanisme de polling ou de l’attente active consiste à vérifier de façon répété si une touche a été entrée. Le polling est un moyen rapide et facile pour traiter les entrées des utilisateurs.

* Voici comment interroger une touche du clavier :
boolean isAPressed = Gdx.input.isKeyPressed(Keys.A);

Gestion des évènements :
La  table de code toute seule, ne suffit pas pour gérer les touches appuyées simultanément. Par exemple : pour écrire en majuscule il faut appuyer sur le shift et la touche du caractère. Pour cela un écouteur d’évènement est branché et qui non seulement détecte le code de la touche appuyée/relâchée mais aussi son caractère qui va avec. C’est le mécanisme de gestion des évènements, il permet d’avoir plus d’information sur une entrée utilisateur.

* Pour la gestion des évènements il faut implémenter l’interface InputProcessor et redéfinir toutes ses méthodes.
public class ProcesseurDentree implements InputProcessor {
//****** Les trois méthodes de la gestion des évènements reliés au clavier *******//
            @Override
            public boolean keyDown(int codeCle) {
                        return false;
            }
            @Override
            public boolean keyTyped(char caractere) {
                        return false;
            }
            @Override
            public boolean keyUp(int codeCle) {
                        return false;
            }
//**********************************************************************************//
//*** Méthodes qui assurent la Gestion des évènements souris/écran tactile ***//
//on va les voir juste après les évènements claviers
            @Override
            public boolean scrolled(int arg0) {
                        return false;
            }
            @Override
            public boolean touchDown(int arg0, int arg1, int arg2, int arg3) {
                        return false;
            }
            @Override
            public boolean touchDragged(int arg0, int arg1, int arg2) {
                        return false;
            }
            @Override
            public boolean touchMoved(int arg0, int arg1) {
                        return false;
            }
            @Override
            public boolean touchUp(int arg0, int arg1, int arg2, int arg3) {
                        return false;
            }
}

On va s’intéresser aux trois premières méthodes liées au clavier, on va voir les autres dans la partie Souris/tactile qui vient juste après.
Ces trois premières méthodes permettent d’écouter des évènements clavier.
  • keyDown () : Appelé quand une touche a été appuyé, prend en paramètre le code de la clé appuyée.
  • keyUp () : Appelé quand une touche a été relâché, prend en paramètre le code de la clé relâchée.
  • keyTyped () : Appelée quand un caractère Unicode a été généré par une entrée  du clavier, prend en paramètre le caractère généré.
* Une fois l’interface implémentée et ces méthodes définies, on doit instancier la classe implémentant cette interface, et l’indiquer à Libgdx :
ProcesseurDentree monProcesseurEntree = new ProcesseurDentree ();
   Gdx.input.setInputProcessor(monProcesseurEntree);
Une fois l’objet indiqué à Libgdx, chaque évènement pourra être détecté.

Pour récapituler la gestion des évènements clavier voici un code source d’une petite application, qui vous demande d’insérer n’importe quel caractère, et une fois le caractère inséré elle l’affiche ainsi que  tous les codes des clés générées.
Le code source est décomposé en 3 parties comme nous l’avons déjà expliqué dans un tutoriel précédant.

* La partie logique contiendra :
ppackage my.works.TutorielBlog;
import java.util.Iterator;
import java.util.Stack;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.InputProcessor;

public class ManipulationEntree implements ApplicationListener {
            private SpriteBatch batch ;
            private BitmapFont fontmessage1 ;
            private BitmapFont fontmessage2 ;
            private BitmapFont fontcaractere ;
            private BitmapFont fontCode1 ;
            private BitmapFont fontCode2 ;
            private String message1;
            private String message2;
            private String caractereAffiche;
            private String codeCle1;
            private String codeCle2;
            private Stack<Integer> pile;
            private boolean afficherCode1,afficherCode2;
            @Override
            public void create() {
                        // Initialisation des données
                        batch            = new SpriteBatch();
                        fontmessage1     = new BitmapFont();   // Image contient: police du 1er msg
                        fontmessage2     = new BitmapFont();   // Image contient: police du 2eme msg
                        fontcaractere    = new BitmapFont();   // Image contient: police du caractère
                        fontCode1        = new BitmapFont();   // Image contient: police du code généré
                        fontCode2        = new BitmapFont();   // Image contient: police du code généré
                        message1         = "Entrez un caratere SVP";        // 1er message
                        message2         = "Codes des cles apuyees";   // 2eme message
                        caractereAffiche = "---";
                        pile           = new Stack<Integer>();//Une pile pour gérer l'action appuyer/relâcher
                        afficherCode1    = false;                // Permettre l'affichage code 1
                        afficherCode2    = false;                // Permettre l'affichage code 2
            }
            @Override
            public void dispose() {
            }
            @Override
            public void pause() {
            }
            @Override
            public void render() {
                         Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);          
                         Gdx.input.setInputProcessor(new InputProcessor() {
//*** Méthodes assurent la Gestion des évènements pour souris/écran tactile **//
      //********** Voir la partie souris/écran du tutoriel **********//
                                   @Override
                                   public boolean touchUp(int a, int arg1, int arg2, int arg3) {
                                               return false;
                                   }
                                   @Override
                                   public boolean touchMoved(int arg0, int arg1) {
                                               return false;
                                   }
                                   @Override
                                   public boolean touchDragged(int arg0, int arg1, int arg2) {
                                               return false;
                                   }
                                   @Override
                                   public boolean touchDown(int arg0, int arg1, int arg2, int arg3) {
                                               return false;
                                   }
                                   @Override
                                   public boolean scrolled(int arg0) {
                                               return false;
                                   }
//*********************************************************************************//                          
         //****** Les trois méthodes de la gestion des évènements reliés au clavier *******//
                         // Appelée à chaque fois qu'on relâche une clé du clavier             
                                   @Override
                                   public boolean keyUp(int codeCle) {
                                               System.out.println("chekpnt "+pile.size());
                                               if(pile.size() >= 2)  // le contenu de la pile > 2 éléments i.e.
                                               {                           // deux touches sont maintenues simultanément
                                                           afficherCode2 = true;
                                                           codeCle2=Integer.toString(codeCle); // Récupérer le code 
                                               }                                                              // de la clé appuyée en String
                                               else
                                               {
                                                           afficherCode1 =true ;
                                                           codeCle1=Integer.toString(codeCle); // Récupérer le code 
                                               }                                         // de la clé appuyée en String
                                               pile.pop();    // Dépiler
                                              
                                               return false;
                                   }
                                   @Override
        // Appelée à chaque fois qu'un caractère est généré
                                   public boolean keyTyped(char caractere) {
                                     caractereAffiche =Character.toString(caractere); //récupérer le caractère
                                                                                                                         //et le convertir en String
                                               return false;
                                   }

        // Appelée à chaque fois qu'on appuie sur une clé du clavier 
        // Si on maintient une clé, cette méthode sera appelé en permanence
                                   @Override
                                   public boolean keyDown(int codeCle) {
                                               if(pile.empty())  // re-initialise à chaque fois que la pile se vide
                                               {                          // une pile vide signifie qu'aucune touche n'est
                                                                          // appuyée
                                                           afficherCode1=false;   
                                                           afficherCode2=false;
                                               }
                                               if(!pile.contains(codeCle))   // cette condition gérer le cas
                                                                                              // d'une touche enfoncée
                                                           pile.push(codeCle); // empiler
                                               return false;
                                   }
                        });
                         
        batch.begin();
        fontmessage1.draw(batch, message1, 10, 300);           // dessiner 1er msg
        fontmessage2.draw(batch, message2, 10, 200);           // dessiner 1er msg
        fontcaractere.draw(batch, caractereAffiche, 10, 150);   // dessiner caractère généré
           
        if(afficherCode1)
        fontCode1.draw(batch,codeCle1, 200, 200);      // afficher code de la 1er clé appuyée
          
        if(afficherCode2)
        fontCode2.draw(batch,codeCle2, 200 + 30, 200); // afficher code de la 2eme clé appuyée
    
        batch.end();
            }
            @Override
            public void resize(int arg0, int arg1) {
            }
            @Override
            public void resume() {
            }
}

* La partie Desktop : elle contient le code lanceur de l’application sous Desktop
package my.works.TutorielBlog;
import com.badlogic.gdx.backends.jogl.JoglApplication;
public class Lanceur {
            public static void main(String[] args) {
                        new JoglApplication (new ManipulationEntree(),"La manipulation des entrées",480,320,false);
            }
}

* La partie Android : elle contient le code lanceur de l’application sous Android
package my.works.LibgdxTutorielAndroid;
import my.works.TutorielBlog.ManipulationEntree;
import com.badlogic.gdx.backends.android.AndroidApplication;
import android.os.Bundle;
public class main extends AndroidApplication {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initialize(new ManipulationEntree(), false);
    }
}

La partie logique se trouve dans le projet desktop avec le lanceur de l’application, contrairement au lanceur Android qui se trouve dans un projet appart. Nous avons déjà parlé de ça en détail dans un tutoriel précédant.

* Voici le résultat sous desktop :

Si je tape h  minuscule :

Si je veux écrire C (majuscule) :

Le code de la clé shift = 59 et de la clé c = 31

* Maintenant le résultat sous Android (sous l’émulateur) :
Remarque : cette application n’est fonctionnelle que sur le mode paysage contentez-vous de ça pour l’instant. Pour rendre l’émulateur sous le mode paysage (car par défaut il est en mode portrait), il faut faire : 
Ctrl (qui se trouve à gauche) + F11
KEYPAD_7 : appuyer sur le numéro 7 tout en assurant que la lampe des numéros est éteinte.
On appuie sur la lettre h et obtient :

Par exemple si j’appuie sur le bouton menu :



Entrées avec Souris/Ecran tactile 

On a cité un peu plus haut quelques différences entre les deux plateformes au niveau de la souris (pour Desktop) et le toucher tactile (pour Android). Pour réduire l’écart entre Android et Desktop Libgdx utilise les mêmes mécanismes vus pour le clavier : le polling (ou l’attente active) et la gestion des évènements.

le polling (l’attente active) :
Le polling sous Libgdx fournis un ensemble de méthodes qui permettent de vérifier l’état actuel du périphérique d’entrée par exemple si  l’écran est touché par un ou plusieurs doigts concernant Android ou si on a effectué un clic avec la souris concernant Desktop.
Mécanisme de polling ou de l’attente active consiste à vérifier de façon répété si une entrée avec Souris/Ecran tactile a été effectuée. Le polling est un moyen rapide et facile pour traiter les entrées des utilisateurs.

* Voici comment vérifier si un ou plusieurs doigts est sur l’écran tactile (Sous Android).
boolean estTouche = Gdx.input.isTouched();
Sous Desktop : estTouche est à vrai si on clique sur l’écran.

* Pour obtenir les coordonnées d’un clic avec la souris / doigt sur l’écran :
float X = Gdx.input.getX();
float Y = Gdx.input.getY();

* On peut aussi obtenir la distance qui sépare un premier clic et un deuxième :
float deltaX =  Gdx.input.getDeltaX();
float deltaY =  Gdx.input.getDeltaY();

* Maintenant pour gérer le multi-touch sous Android
boolean premierDoigt = Gdx.input.isTouched(0);
boolean deuxiemeDoigt = Gdx.input.isTouched(1);
boolean troisiemeDoigt = Gdx.input.isTouched(2);

C’est évident que le toucher multiple n’est considéré que par Android, Libgdx gère cela par l’attribution d’un pointeur à chaque doigt qui touche l’écran tactile i.e. si un doigt touche l’écran tactile il obtient le plus petit indice disponible parmi [ 0, 1, 2 ]. Un l’indice se libère quand le doigt qu’il le point se lève de l’écran. Voici comment se passent les choses :
Premier doigt touche l’écran                         ----> il obtient l’indice 0
Deuxième doigt touche l’écran                     ----> il obtient l’indice 1
Troisième doigt touche l’écran                     ----> il obtient l’indice 2
Troisième doigt quitte (se lève de) l’écran  ----> l’indice 2 se libère.
Deuxième doigt quitte (se lève de) l’écran  ----> l’indice 1 se libère.
Un nouveau doigt touche l’écran                   ----> il obtient l’indice 1 (Le plus petit indice libre).

* Pour savoir si l’écran a été toucher puis relâché par l’un des trois doigts :
boolean touche = Gdx.input.justTouched();

* Pour obtenir les coordonnées des doigts posés sur l’écran
int premierDoigtX = Gdx.input.getX();
int premierDoigtY = Gdx.input.getY();
int deuxiemeDoigtX = Gdx.input.getX(1);
int deuxiemeDoigtY = Gdx.input.getY(1);
int troisiemeDoigtX = Gdx.input.getX(2);
int troisiemeDoigtY = Gdx.input.getY(2);
Vous avez surement remarquez que par défaut l’indice de pointeur est 0, c’est l’indice qui pointe la souris sous Desktop.

* On peut aussi obtenir la distance qui sépare la première position d’un doigt et une deuxième
float premierDoigtDeltaX   =  Gdx.input.getDeltaX();
float premierDoigtDeltaY   =  Gdx.input.getDeltaY();
float deuxiemeDoigtDeltaX  =  Gdx.input.getDeltaX(1);
float deuxiemeDoigtDeltaY  =  Gdx.input.getDeltaY(1);
float troisiemeDoigtDeltaX =  Gdx.input.getDeltaX(2);
float troisiemeDoigtDeltaY =  Gdx.input.getDeltaY(2);

* Pour savoir quelle est le bouton de la souris que l’utilisateur vient de cliquer :
boolean boutonGauche = Gdx.input.isButtonPressed(Input.Buttons.LEFT);
boolean boutonDroit  = Gdx.input.isButtonPressed(Input.Buttons.RIGHT);
boolean boutonMilieu = Gdx.input.isButtonPressed(Input.Buttons.MIDDLE);

Gestion des évènements :
Le mécanisme de gestion des évènements permet d’avoir plus d’information sur une entrée utilisateur. Il fournit un moyen de mettre en œuvre des interactions avec l’interface utilisateur qui sont difficiles de mettre en œuvre en utilisant seulement le polling.

* Pour la gestion des évènements il faut implémenter l’interface InputProcessor et redéfinir toutes ses méthodes.
public class ProcesseurDentree implements InputProcessor {

//****** Les trois méthodes de la gestion des évènements reliés au clavier *******//
// Vu précédemment
            @Override
            public boolean keyDown(int codeCle) {
                        return false;
            }
            @Override
            public boolean keyTyped(char caractere) {
                        return false;
            }
            @Override
            public boolean keyUp(int codeCle) {
                        return false;
            }
//**********************************************************************************//

//*** Méthodes qui assurent la Gestion des évènements pour souris/écran tactile **//

            @Override
            public boolean scrolled(int arg0) {
                        return false;
            }
            @Override
            public boolean touchDown(int arg0, int arg1, int arg2, int arg3) {
                        return false;
            }
            @Override
            public boolean touchDragged(int arg0, int arg1, int arg2) {
                        return false;
            }
            @Override
            public boolean touchMoved(int arg0, int arg1) {
                        return false;
            }
            @Override
            public boolean touchUp(int arg0, int arg1, int arg2, int arg3) {
                        return false;
            }
}
Voici les méthodes assurant la gestion des évènements souris/écran tactile
  • TouchDown () : Appelée quand un doigt se pose sur l'écran (Android) / un bouton la souris a été pressé (desktop). Elle nous informe sur les coordonnées ainsi que l'indice de pointeur et le bouton de la souris. Sachant que pour Android seul le bouton droit est considéré.
  • touchUp(): Appelée quand un doigt a été levée de l'écran( Android) / un bouton de la souris a été relâché (Desktop). Elle nous informe sur les coordonnées, l'indice de pointeur(Android) et le bouton de la souris(Desktop)
  • touchDragged () : Appelée quand un doigt glisse sur l'écran tactile (Android) / déplacer la souris tout en pressant sur un bouton de la souris (Desktop). Nous informe les coordonnées et l'indice de pointeur, mais pour savoir quel est le bouton de la souris concerné il faut utiliser le polling.
  • touchMoved () : appelée lorsque la souris est déplacée sur l'écran sans que l’un de ses boutons soit cliqué. Cette méthode n’est appelée que sur l’environnement Desktop, elle ne sera jamais appelée en Android  car l’écran tactile ne possède pas de curseur comme est le cas de la souris.
  • scrolled () : appelée lorsque la roulette de la souris est tournée. Nous informe sur le sens qu’est tournée la roulette de la souris. Elle n’est jamais appelée sous Android.
* Une fois l’interface implémentée et ces méthodes définies, on doit instancier la classe implémentant cette interface, et l’indiquer à Libgdx.
ProcesseurDentree monProcesseurEntree = new ProcesseurDentree ();
Gdx.input.setInputProcessor(monProcesseurEntree);
Une fois l’objet indiqué à Libgdx chaque évènement pourra être détecté.

Pour récapituler un peu les choses je vous propose ce code source qui implémente une petite application qui vous permettra de voir encore plus le fonctionnement des gestions des évènements et du polling.
Le code source est décomposé en 3 parties comme nous l’avons déjà expliqué dans un tutoriel précédant.

* La partie logique contiendra :
package my.works.TutorielBlog;

import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Buttons;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;

public class ManipulationEntree implements ApplicationListener {
           
            public static int longueur = 320;
            public static int largeur = 480 ;
            public static int deltaTemps = 3;
            private SpriteBatch batch;
            private BitmapFont fontTexte ;
            private BitmapFont fontCadre ;
            private String message1;
            private String message2;
            private String message3;
            private String message4;
            private String msgActionDesktop;
            private String msgActionAndroid;
            private String coordonneesDesktop;
            private String coordonneesAndroid;
            private String android ;
            private String desktop ;
            private String cadre1;
            private String cadre2;
            private float tempsEcouler ;
            private boolean afficheMsg ;
            private boolean afficheContenu ;
            @Override
            public void create() {
                        batch = new SpriteBatch();
                        fontTexte= new BitmapFont();
                        fontCadre= new BitmapFont();
                        message1 ="Ceci est une application qui vous aidra a mieux voir";
                        message2 ="la gestion des evenements de la souris sous Desktop";
                        message3 ="et ecran tactile sous Android.";
                        message4 ="cliquer/toucher l'ecran pour commencer !";
                        msgActionDesktop = "Action : -----";
                        msgActionAndroid = "Action : -----";
                        afficheContenu = false ;
                        afficheMsg = true;
                        android = "Plateforme Android";
                        desktop = "Plateforme Desktop";
                        cadre1 = "|";
                        cadre2 = "_";
            }
            @Override
            public void dispose() {
            }
            @Override
            public void pause() {
            }
//**************** Méthode qui dessine le cadre ************************//
            public void dessinerCadre()
            {
                        int distance = 0;
                        for(int i =0 ; i <= 18 ; i++)
                                   {
                                         fontCadre.setColor(Color.GREEN);
                                         fontCadre.draw(batch, cadre1, largeur /2 , distance);
                                         distance +=20 ;
                                   }
                        distance = 0;
                        for(int i = 0; i<= 25 ; i++)
                        {
                              fontCadre.setColor(Color.GREEN);
                              fontCadre.draw(batch, cadre2, distance , longueur - 50);
                              distance +=20 ;
                        }
            }
//***********************************************************************//
            @Override
            public void render() {
                         Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);          
                         Gdx.input.setInputProcessor(new InputProcessor() {
                                   @Override
                                   public boolean touchUp(int x, int y, int pointeur, int bouton) {
                                               tempsEcouler = 0 ;  // Initialiser le temps depuis
                                              // la dernier entrée
                                               if(bouton == Buttons.LEFT)
                                                   msgActionDesktop = "relache bouton G";
                                               if(bouton == Buttons.RIGHT)
                                                   msgActionDesktop = "relache bouton D";
                                               if(bouton == Buttons.MIDDLE)
                                               msgActionDesktop = "relache bouton M";
                                               if(pointeur == 0)
                                                   msgActionAndroid = "premier doigt leve";
                                               if(pointeur == 1)
                                                           msgActionAndroid = "deuxieme doigt leve";
                                               if(pointeur == 2)
                                                           msgActionAndroid = "troisieme doigt leve";
                                               // Recuperer coordonnées et les convertir en String
                                               coordonneesDesktop ="x="+ Integer.toString(x) +" y="+ Integer.toString(y);
                                               coordonneesAndroid ="x="+ Integer.toString(x) +" y="+ Integer.toString(y);
                                               coordonneesAndroid = "coordonnees : "+coordonneesAndroid ;
                                               coordonneesDesktop = "coordonnees : "+coordonneesDesktop;
                                               return false;
                                   }
                                   @Override
                                   public boolean touchMoved(int x, int y) {
                                               // Cette méthode n'est jamais appelée sous Android
                                               tempsEcouler = 0 ;
                                               msgActionDesktop = "Action : mouvement du curseur";
                                               // Récupérer les coordonnées et les convertir en String
                                               coordonneesDesktop ="x="+ Integer.toString(x) +" y="+ Integer.toString(y);
                                               coordonneesDesktop = "coordonnees : "+coordonneesDesktop;
                       
                                               return false;
                                   }
                                  
                                   @Override
                                   public boolean touchDragged(int x, int y, int pointeur) {
                                               tempsEcouler = 0 ; // Initialiser le temps depuis
                                                                  // la dernier entree
                                               // Cette méthode ne nous informe pas sur le bouton de
                                               // la souris il faut utiliser le polling
                                                if(Gdx.input.isButtonPressed(Buttons.LEFT))
                                               msgActionDesktop = "Action : Glissement avec bouton G";
                                               if(Gdx.input.isButtonPressed(Buttons.RIGHT))
                                               msgActionDesktop = "Action : Glissement avec bouton D";
                                               if(Gdx.input.isButtonPressed(Buttons.MIDDLE))
                                               msgActionDesktop = "Action : Glissement avec bouton M";
                                              
                                               if(pointeur == 0) // si c'est le premier doigt
                                               msgActionAndroid = "Action : Glissement du 1er doigt";
                                               if(pointeur == 1) // si c'est le deuxième doigt
                                               msgActionAndroid = "Action : Glissement du 2eme doigt";
                                               if(pointeur == 2) // si c'est le troisième doigt
                                               msgActionAndroid = "Action : Glissement du 3eme doigt";
                                              
                                               // Récupérer coordonnées et les convertir en String
                                               coordonneesDesktop ="x="+ Integer.toString(x) +" y="+ Integer.toString(y);
                                               coordonneesAndroid ="x="+ Integer.toString(x) +" y="+ Integer.toString(y);
                                               coordonneesAndroid = "coordonnees : "+coordonneesAndroid ;
                                               coordonneesDesktop = "coordonnees : "+coordonneesDesktop;

                                               return false;
                                   }
                                  
                                   @Override
                                   public boolean touchDown(int x, int y, int pointeur, int bouton) {
                                               tempsEcouler = 0 ; // Initialiser le temps depuis
                                                                                // la dernier entrée
                                               // Cette méthode nous informe sur le bouton de la souris
                                               // Ce n’est pas la peine d'utiliser le polling
                                       if(bouton ==Buttons.LEFT)
                                               msgActionDesktop = "Action : clic bouton gauche souris";
                                       if(bouton ==Buttons.RIGHT)
                                               msgActionDesktop = "Action : clic bouton droit souris ";
                                       if(bouton ==Buttons.MIDDLE)
                                               msgActionDesktop = "Action : clic bouton milieu souris";
                                      
                                       // Pour distinguer quel doit a effectué l'action
                                       if(pointeur == 0)
                                                   msgActionAndroid = "premier doigt pose";
                                       if(pointeur == 1)
                                                   msgActionAndroid = "deuxieme doigt pose";
                                       if(pointeur == 2)
                                                   msgActionAndroid = "troisieme doigt pose";
                                              
                                               // Récupérer coordonnées et les convertir en String
                                               coordonneesDesktop ="x="+ Integer.toString(x) +" y="+ Integer.toString(y);
                                               coordonneesAndroid ="x="+ Integer.toString(x) +" y="+ Integer.toString(y);
                                              coordonneesAndroid = "coordonnees : "+coordonneesAndroid ;
                                               coordonneesDesktop = "coordonnees : "+coordonneesDesktop;
                            
                                               return false;
                                   }
                                   @Override
                                   public boolean scrolled(int direction) {
                                              
                                               if(direction == 1) // roule vers le bas
                                               msgActionDesktop = "roulette vers bas";
                                               if(direction == -1)// roule vers le haut
                                               msgActionDesktop = "roulette vers haut";
                                               return false;
                                   }
//*********************Entrée clavier********************************************//
// On est obligé de les redéfinir puisqu’on a implémenté l’interface
                                   @Override
                                   public boolean keyUp(int arg0) {
                                               return false;
                                   }
                                   @Override
                                   public boolean keyTyped(char arg0) {
                                               return false;
                                   }
                                   @Override
                                   public boolean keyDown(int arg0) {
                                               return false;
                                   }
//*******************************************************************************//
                        });
            if(Gdx.input.justTouched()) // si cliquer/toucher puis relâcher
            {
                        afficheMsg     = false; // Masquer la 1er page
                        afficheContenu = true// Afficher la 2eme page
            }
                       
            batch.begin();
            if(afficheMsg)     // 1ere page
            {
                        fontTexte.draw(batch, message1, 80, 300); //insérer du texte
                        fontTexte.draw(batch, message2, 80, 280);
                        fontTexte.draw(batch, message3, 80, 260);
                        fontTexte.draw(batch, message4, 80, 240);
            }
            if(afficheContenu) // 2eme page
            {
                        tempsEcouler += Gdx.graphics.getDeltaTime();
                        // Compter le temps depuis la dernière entrée
                        if(tempsEcouler > deltaTemps) // Aucune entrée n'a été
                        {                             // éffectuée durant un temps
                                                      // delta
                         msgActionDesktop = "Action : -----"; // aucune action
                         msgActionAndroid = "Action : -----"; // aucune action
                         coordonneesAndroid = " ";
                         coordonneesDesktop = " ";
                        }
                        dessinerCadre();
                        // Partie Android 
                        // insertion titre + action +coordonnées
                        fontTexte.draw(batch,android, 50,longueur-25);       
                        fontTexte.draw(batch,msgActionAndroid,10,longueur-70);
                        fontTexte.draw(batch,coordonneesAndroid,10, longueur-90);
                        // Parite Desktop
                        // insertion titre + action +coordonnées
                        fontTexte.draw(batch,desktop,largeur/2 +50,longueur-25);        
                        fontTexte.draw(batch,msgActionDesktop,largeur/2 +10,longueur-70);
                        fontTexte.draw(batch,coordonneesDesktop,largeur/2+10,longueur-90);
            }
            batch.end();
            }
            @Override
            public void resize(int arg0, int arg1) {
            }
            @Override
            public void resume() {
      }
}

* La partie Desktop : elle contient le code lanceur de l’application sous Desktop
package my.works.TutorielBlog;
import com.badlogic.gdx.backends.jogl.JoglApplication;
public class Lanceur {
            public static void main(String[] args) {
                        new JoglApplication (new ManipulationEntree(),"La manipulation des entrées",480,320,false);
            }
}

* La partie Android : elle contient le code lanceur de l’application sous Android
package my.works.LibgdxTutorielAndroid;
import my.works.TutorielBlog.ManipulationEntree;
import com.badlogic.gdx.backends.android.AndroidApplication;
import android.os.Bundle;
public class main extends AndroidApplication {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initialize(new ManipulationEntree(), false);
    }
}

La partie logique se trouve dans le projet desktop avec le lanceur de l’application, contrairement au lanceur Android qui se trouve dans un projet appart. Nous avons déjà parlé de ça en détail dans un tutoriel précédant.

* Voici le résultat sur desktop :

Cliquer sur l’écran et vous obtiendrai :

Glisser le curseur de votre souris sur l’écran et vous obtiendrai :

Faite seulement bouger le curseur de la souris et vous obtiendrai :

Bien sûr, il y en a d’autres actions qui peuvent être détecté je vous laisse le soin de les tester

* Maintenant le résultat sous Android (sous l’émulateur) :

Remarque : cette application n’est fonctionnelle que sur le mode paysage contentez-vous de ça pour l’instant. Pour rendre l’émulateur sous le mode paysage (car par défaut il est en mode portrait), il faut faire : 
Ctrl (qui se trouve à gauche) + F11
KEYPAD_7 : appuyer sur le numéro 7 toute en assurant que la lampe des numéros est éteinte.

On touche l’écran et obtient :


Si on fait une action, par exemple glisser un doigt on aura :

Bien sûr, il y en a d’autres actions je vous laisse le soin de les découvrir.



Conclusion
Nous avons vu dans ce tutoriel les entrées disponibles pour les deux plateformes et que Libgdx doit les  gérer en tenant compte des différences qui existent entre eux. Dans un prochain tutoriel on va voir les entrées propre a Android tel que acétomètre. Si vous avez des remarques ou des questions n’hésitez pas à les poster en commentaire. Merci pour votre lecture.



3 commentaires:

  1. Salut,
    Très bien tes Tuto. Depuis six mois je passe pas mal de temps sur libgdx et c'est le premier site que je vois en français.
    Tu récapitule bien ce qu'il faut savoir pour commencer, c'est propre et clair. Merci à toi.
    En ce moment je suis sur la partie Box2D de libgdx. LibGdx est vraiment très bien.

    à plus

    RépondreSupprimer
  2. Salut Kurlip,
    c'est vrai qu'on trouve pas de tuto de Libgdx sur le net ce qui m'a poussé a en faire un , et je suis au début du chemin.
    Bonne continuation a toi aussi. en fait,tu a raison Libgdx est magnifique !

    RépondreSupprimer
  3. bonjour monsieur,
    merci pour ce tutoriel il m'a vraiment expliquer des grands concepts et j'aimerais bien que vous nous donnez des booking que vous avez essayez et que vous sont utiles.

    RépondreSupprimer