Jouer à 2

Durée estimée: 90 minutes

Attention : Cette version est beaucoup plus difficile que les précédentes pour la partie Bluetooth, mais vous pouvez la copier/coller sans avoir à la réaliser vous-même.

Pour l'instant, le joueur pilote la balle rouge et part à la chasse de la balle jaune.
Avec un 2° smartphone, un 2° joueur va maintenant déplacer de cette balle jaune, pour tenter d'échapper à la rouge.

Pour que les 2 joueurs voient les 2 balles au même endroit, les 2 smartphones doivent s'échanger en permancence la position de la balle qu'ils déplacent.

Pour communiquer par radio entre 2 appareils, nous utiliserons 'Bluetooth', que vous connaissez peut-être déjà si vous avez des écouteurs ou une enceinte sans fil. Le protocole de communication est de type client/serveur, c'est à dire qu'un des appareils (le serveur), se met en attente de la demande d'un autre appareil (le client), et une fois la communication établie, chacun peut envoyer des messages à l'autre et en recevoir.

Analyse

Les deux smartphones, jouent un rôle différent, aussi bien pour la balle que pour la communication (client ou serveur). Par facilité on va convenir :

  • que la balle 2, la rouge sera le client bluetooth,
  • et que la balle 1, la jaune, sera le serveur bluetooth.
Du coup on va renommer la balle 2 en 'BalleClient' et la balle 1 en 'BalleServeur'. Le programme sera plus facile à lire avec cette règle.

On peut décrire l'application de la manière suivante :

  1. le joueur choisit son rôle : serveur ou client (en cochant une case ou une autre),
  2. puis clique sur un bouton (BoutonConnecteDeconnecte) pour mettre en route un canal de communication qui permettra d'envoyer des messages et d'en recevoir,
  3. ensuite, à chaque évènement de l'horloge associée à l'accéléromètre, on va
    • déplacer une balle, mais cette fois-ci, selon le rôle choisi, ce sera la 'BalleClient' ou la 'BalleServeur', donc 2 cas à traiter au lieu d'un.
    • et envoyer un message à l'autre smartphone avec en paramètres le nom de la balle (C ou S) et ses nouvelles coordonnées (x,y),
  4. En cas de collision (à traiter sur un seul des smartphones) la balle serveur saute à un endroit aléatoire, et on envoie le message de déplacement, en ajoutant V pour dire de vibrer.
    Donc on a 3 messages possibles (C,x,y), (S,x,y) et (SV,x,y).
  5. Enfin chaque smartphone doit traiter en continu les messages qu'il reçoit. On va les lire à intervalle régulier, défini dans une Horloge (HorlogeBTLecture), en veillant à ce que cet intervalle de lecture soit plus court que l'intervalle de déplacement et d'envoi, défini dans 'HorlogeAccelero'. La cadence de lecture doit être plus rapide que la cadence d'envoi.

Design (ajouts)

Nom du projet : ballesBluetooth (dans project properties)

on va ajouter :

  • un arrangement horizontal avec
    • une case à cocher pour choisir le rôle "client",
    • une case à cocher pour choisir le rôle "serveur",
    • un bouton pour lancer la connection Bluetooth,
  • un composant serveur Bluetooth,
  • un composant client Bluetooth,
  • un composant horloge (pour le Bluetooth) qui va définir la cadence de lecture,
  • un label (LabelStatus) pour afficher l'état de la connection entre les smartphones,
  • un label (LabelRecu) que l'on utilisera temporairement pour afficher les messages reçus,
  • un viewer de liste pour afficher la liste des serveurs connus du client.

type catégorie Nom rôle propriété valeur
argt. horizontal Capteurs ArgtH_choixClientServeur alignt Hor.
alignt Vert.
couleur_fond
hauteur
largeur
visible
centrer
centrer
gris clair
automatique
remplir_parent
non coché
case à cocher Interface case_a_cocher_client couleur_fond
taille police
hauteur
largeur
Vérifié
Texte
aucune
14
automatique
automatique
coché
Serveur
Bouton Interface BoutonConnecte connection couleur fond
taille police
hauteur
largeur
Texte
defaut
14
automatique
35%
Connecte
Label Interface LabelStatus status connection couleur fond
taille police
hauteur
largeur
Texte
aucune
32
automatique
automatique
Client Bluetooth Connectivité ClientBT1 codage
sécurisé
utf-8
coché
Serveur Bluetooth Connectivité ServeurBT1 codage
sécurisé
utf-8
coché
Horloge Capteurs HorlogeBTLecture cadence de lecture always fires
chrono_activé
intervalle
non
oui
20

Les horloges jouent un rôle assez important.

  • l'horlogeAccelero détermine la cadence à laquelle les déplacements sont effectués,
  • L'horlogeBTLecture détermine la cadence à laquelle les messages sont lus.
Pour ne pas laisser les messages s'accumuler, l'intervalle de lecture 20ms, est sensiblement inférieur à l'intervalle entre déplacements 50ms, mais on ne peut pas empêcher l'envoi de 2 messages entre 2 lectures : les collisions ne sont pas prévisibles.

Codage

Pour le codage on va distinguer 2 sujets très différents :

  1. La mise en place d'un canal de communication, qui va mettre à notre disposition une procédure et une fonction :
    1. la procédure envoyer(message) qui envoie le contenu de la variable message
    2. et la fonction message=recevoir qui met dans message le contenu reçu
  2. La modification du programme précédent pour deux téléphones, donc avec
    1. la modification de l'existant pour traiter les 2 rôles possibles,
    2. l'envoi d'un message à chaque déplacement d'une balle,
    3. la lecture et le traitement continu des messages reçus.

Codage : choix du rôle et mise en place d'une connection Bluetooth

La mise en place d'une connection Bluetooth entre 2 smartphones est un sujet commun à beaucoup d'applications, mais c'est un peu compliqué, et ça sort du périmètre de ce cours donc, vous pouvez passer cette partie si vous voulez et récupérer le code tout fait. Nous aurons seulement besoin :

  • de la procedure envoyer(message) et la fonction message = recevoir
  • des propriétés Client_Bluetooth1.Estconnecté et Serveur_Bluetooth1.Estconnecté.
Essayez quand même de le lire pour comprendre comment ça marche

Dans le design, on a défini 2 cases à cocher : une pour le client (cochée par défaut) et une pour le serveur (décochée par défaut).

  • Choix du rôle :

    Quand l'utilisateur modifie le rôle en cochant sur une case
    Quand case_a_cocher_serveur.changé ou Quand case_a_cocher_client.changé
    on assigne la valeur contraire à l'autre case et on réinitialise en appelant reset.

    Cette procédure déconnecte le serveur et le client, puis appelle la fonction display qui met à jour l'affichage pour refléter la déconnection. On verra display plus loin. balleJouerA2/assets/img/blocsChoixRole.png

  • lancement de la connection :

    Quand l'utilisateur clique sur le bouton "connecte-deconnecte",

    • si le smartphone est connecté ou en attente d'un client, on le déconnecte,
    • et sinon on appelle la procédure de connection serveur ou client.
    si le client est déjà connecté
          déconnecter le client
    sinon si le serveur est déjà connecté
          déconnecter le serveur
    sinon si le serveur en train d'attendre un client
          cesser d'attendre
    sinon
          si case serveur cochée
             appeler connnectServeur
          sinon
             appeler connnectClient
    appeler display pour rafraichir l'écran
    balleJouerA2/assets/img/blocsBoutonConnecte.png

  • Procédure de connection en tant que serveur
    Dans la procédure connectServeur
           demander l'autorisation de connection
           et se mettre en attente d'une demande client

    Quand une connection a été acceptée
           afficher "connecté" dans le labelStatus
           activer l'horloge pour la lecture
           appeler display pour rafraichir l'écran
    balleJouerA2/assets/img/blocsConnectServeur.png

    balleJouerA2/assets/img/blocsServeurConnectAcc.png

  • Procédure de connection en tant que client

    C'est le client qui choisit le serveur avec qui se connecter, dans la liste des appareils qu'il connait déjà ou avec lequel il a déjà été connecté : ClientBT1.Adresses et noms.
    On va donner cette liste au composant VueListe Serveurs, comme liste à afficher dans la propriété VueListeServeurs.Elements, pui on rend cette liste visible pour que l'utilisateur choisisse.
    balleJouerA2/assets/img/blocsConnectViewlist.png
    Puis quand il a choisi, quand vueListeServeurs.apres prise

    • on efface la liste
    • on demande la connection au serveur : ClientBT.seConnecter
      qui renvoie vrai ou faux selon que ça a marché ou pas,
    • Si oui
            on affiche la réussite de la connection dan sle labelStatus
            et on active l'horloge pour la réception des messages
    • Si non,
            on affiche l'échec de la connection dans le labelMessagesStatus
    balleJouerA2/assets/img/blocsConnectClient.png

  • Procédure envoyer
    Une fois les smartphones connectés, ils peuvent envoyer des messages avec les blocs client et serveur suivants :
    balleJouerA2/assets/img/blocsEnvoyerBTClient.png balleJouerA2/assets/img/blocsEnvoyerBTServeur.png Mais pour que le reste du programme, puisse envoyer des messages sans avoir à s'occuper de la distinction entre client et serveur, on va définir une fonction envoyer(message) qui s'occupe de la différence, selon que la connection est une connection de type 'client' ou 'serveur'. balleJouerA2/assets/img/ProcedureEnvoyer.png

  • Procédure ou fonction recevoir
    Une fois les smartphones connectés, ils peuvent aussi recevoir des messages.
    Les blocs suivants renvoient le nombre d'octets reçus (pour le client et le serveur): balleJouerA2/assets/img/blocsClientOctetsDispos.png balleJouerA2/assets/img/blocsServeurOctetsDispos.png et on lit l'inégralité du message avec les blocs : balleJouerA2/assets/img/blocsClientRecevoir.png balleJouerA2/assets/img/blocsServeurRecevoir.png
    Et comme pour l'envoi, pour que le reste du programme, puisse recevoir des messages s'occuper de la distinction entre client et serveur, on va définir la fonction recevoir qui renvoie le contenu reçu. balleJouerA2/assets/img/ProcedureRecevoir.png

  • Procédure Display
    Elle modifie l'affichage pour que l'utilisateur sache si les smartphones sont connectés :
    si le smartphone est connecté comme client
          l'arrangt horizontal de connection passe à vert
          le bouton 'connect-disconnect' passe à rouge
          le texte du bouton passe à 'DisConnect'
    sinon s'il est connecté comme Serveur
          l'arrangt horizontal de connection passe à vert
          le bouton 'connect-disconnect' passe à jaune
          le texte du bouton passe à 'DisConnect'
    sinon s'il est en mode serveur et en attente client
          l'arrangthorizontal de connection passe à gris
          le bouton passe à jaune foncé
          le texte du bouton passe à 'en attente'
    sinon
          l'arrangt horizontal de connection passe à gris
          le bouton 'connect-disconnect' passe à gris
          le texte du bouton passe à 'Connect'
    balleJouerA2/assets/img/procedureDisplay.png
  • Gestion des erreurs
    Les erreurs sont possibles pour les composants Serveur BT, Client BT et l'écran principal. Lorsque des erreurs se produisent, on uinterrompt la connection. balleJouerA2/assets/img/erreurBTClient.png balleJouerA2/assets/img/erreurBTServeur.png balleJouerA2/assets/img/erreurScreen1.png
  • Gestion des autorisations de l'application

    En général, la gestion des autorisations dont doit disposer votre application est faite de façon transparente, masi apr sécurité nous suggérones l'ajout des demandes d'autorisations suivantes dans une procédure à appeler au démmarge Quand Screen1.Initialize balleJouerA2/assets/img/autorisations.png

  • Au final, on arrive aux blocs suivants pour la connection et les procédures envoyer et recevoir balleJouerA2/assets/img/blocsDeconnection.png

Codage : modification du programme précédent pour deux téléphones :

On va apporter les 3 modifications suivantes :
  1. modification des actions actuelles pour traiter les 2 rôles possibles,
  2. envoi d'un message à chaque déplacement d'une balle,
  3. lecture et le traitement continu des messages reçus.

Les blocs précédents sont rappelés à gauche, les bocs modifiiés à droite.

Dans l'évènement screen.initialize on ajoute l'appel aux autorisations pour bluetooth

balleJouerA2/assets/img/screenInit1.png balleJouerA2/assets/img/screenInit2.png

Dans l'évènement HorlogeAccelero.chronomètre
On ajoute un test

  • si ClientBT1.Estconnecté
        envoyer un message à l'autre smartphone : balle C (client) avec nouvelles coordonnées
        et déplacer localement la balle Client aux nouvelles coordonnées
  • sinon si ServeurBT1.Estconnecté, on ajoute la même chose pour la balle serveur :
        envoyer un message à l'autre smartphone : balle S (client) avec nouvelles coordonnées
        et déplacer localement la balle Serveur aux nouvelles coordonnées
balleJouerA2/assets/img/horlogeAccelero1.png balleJouerA2/assets/img/horlogeAccelero2.png

Dans l'évènement Quand BalleClient.collision avec
On ajoute un test

  • si ClientBT1.Estconnecté
        envoyer un message à l'autre smartphone : balle SV (client) et nouvelles coordonnées aléatoires
        et déplacer localement la balle Serveur aux nouvelles coordonnées aléatoires
  • sinon si ServeurBT1.Estconnecté, on ajoute la même chose pour la balle serveur :
        envoyer un message à l'autre smartphone : balle S (client) et nouvelles coordonnées
        et déplacer localement la balle Serveur aux nouvelles coordonnées
balleJouerA2/assets/img/QuandCollision1.png balleJouerA2/assets/img/QuandCollision2.png

Enfin pour la lecture à chaque déclenchement d'horloge, on ajoute l'évènement HorlogeBTLecture.chronomètre dans lequel on va lire et traiter le message de la forme "C,356,723,". Mais on prévoit le cas où plusieurs messages de 3 parmaètres peuvent avoir été envoyés

mettre message au résultat de lecture avec recevoir
découper le message en liste
Tant que sa taille est suérieure ou égale à 3
  • mettre dans balle le 1° élément de la liste
  • mettre dans x le 2° élément de la liste
  • mettre dans y le 2° élément de la liste
  • appeler deplacerBalle (balle,x,y)
  • supprimer les 3 premiers éléments de la liste (3 fois le premier)
balleJouerA2/assets/img/HorlogeBTLecture.png
procedure deplacerBalle
  • si balle = C
        déplacer la balleClient à x,y
  • si balle = S
        déplacer la balleServeur à x,y
  • si balle = SV
        déplacer la balleServeur à x,y
        et faire vibre le smartphone
balleJouerA2/assets/img/deplacerBalle.png

Transférez cette version sur le smartphone et testez

balleJouerA2/assets/img/blocsBallesV4.png

Envoyer un commentaire