Sommaire
Projet réalisé par Buguel Maxime, Cartiaux Charles, Douillard Thomas et Roeland Quentin en Novembre 2016.
Introduction
Nous sommes quatre étudiants en Master 2 à l’ISEN Lille. Nous nous sommes récemment découverts une passion pour les fléchettes, surement lié à la présence d’une cible dans le bar que nous fréquentons (avec modération) après les cours.
La découverte de cette nouvelle passion nous a poussé à ressortir du placard les cibles avec lesquelles nous avons pu jouer étant plus jeunes. Mais le plaisir de jouer aux fléchettes n’était pas le même. C’est vrai que l’écran LCD de 2cm par 4cm et le haut parleur 8-bit n’offre pas la même ambiance que celle que nous pouvons avoir sur une borne de bistrot.
Il existe de nombreux tutoriel pour se créer une borne d’arcade chez soi pour les fans de rétro-gaming mais nous n’avons rien trouvé pour “pimper” notre jeu de fléchettes, mis à part un article de blog qui sans expliquer les détails de la transformation nous a servie de “Preuve de faisabilité”.
Mais nous avons décidé d’aller un peu plus loin que de simplement améliorer l’expérience utilisateur en optimisant l’affichage ainsi que les effets sonores. Afin d’intégrer la cible comme un objet connecté à part entière, Constellation a été utilisé
Connecter la cible
Côté matériel la première étape est de faire l’acquisition d’une cible électronique (bas de gammes afin de limiter les coûts), nous avons choisis le jeu de fléchette le moins chère que l’on ai pu trouver : 19,99 euros.
La détection d’une fléchette par la cible se fait à l’aide de 2 nappes en plastiques séparées par une épaisseur en mousse trouée.
On remarque que le jeu est divisé en 2 moitiés (Par l’axe qui passe entre la zone 9 et 14) l’une des 2 nappes en plastique contient 7 pistes conductrices:
- une pour toutes les zones “Simple” de la moitié de la cible
- une pour toutes les zones “Simple” de l’autre moitié de la cible
- une pour toutes les zones “Double” de la moitié de la cible
- une pour toutes les zones “Double” de l’autre moitié de la cible
- une pour toutes les zones “Triple” de la moitié de la cible
- une pour toutes les zones “Triple” de l’autre moitié de la cible
- une pour le “Bull” Simple et Double
L’autre nappe contient 10 pistes, 8 des pistes correspondent chacune à une paire de zone numérotée, chacune des zones appartenant à une moitié différente ((9, 14) par exemple). Les 2 pistes restantes ont, en plus de la paire de zone, une zone du “Bull”.
On se retrouve donc avec ce tableau qui permet de déterminer quelle zone a été touchée. Il suffit d’alimenter les 7 pistes “OUT” une par une et de lire l’état des 10 pistes “IN”. Si on voit que l’une des pistes IN est alimenté alors on peut en déduire la zone touchée.
OUT \ IN | 9
14 DB |
12
11 SB |
5
8 – |
20
16 – |
10
15 – |
2
6 – |
17
13 – |
3
4 – |
19
18 – |
7
1 – |
TRIPLE | T9 | T12 | T5 | T20 | T10 | T2 | T17 | T3 | T19 | T7 |
DOUBLE | D9 | D12 | D5 | D20 | D10 | D2 | D17 | D3 | D19 | D7 |
SINGLE | S9 | S12 | S5 | S20 | S10 | S2 | S17 | S3 | S19 | S7 |
BULL | DB | SB | – | – | – | – | – | – | – | – |
SINGLE | S14 | S11 | S8 | S16 | S15 | S6 | S13 | S4 | S18 | S1 |
DOUBLE | D14 | D11 | D8 | D16 | D15 | D6 | D13 | D4 | D18 | D1 |
TRIPLE | T14 | T11 | T8 | T16 | T15 | T6 | T13 | T4 | T18 | T1 |
Maintenant que l’on sait comment ça marche, il ne reste plus qu’à le connecter aux GPIO du microcontrôleur de son choix.
Dans ce tutoriel nous avons choisi de connecter la cible à un Raspberry Pi B+ mais il est tout à fait possible de le faire avec un Arduino, un ESP8226 ou encore un autre type de Pi. La seule contrainte est qu’il faut au moins 17 GPIO, il faudra donc augmenter le nombre de GPIO à l’aide d’un MCP23017-E/SP 16 I/O Expander.
Il faudra aussi que soit installé sur le device une sentinelle constellation.
Les nappes étant en plastique on ne peut venir souder dessus, on choisit donc de venir souder les fils sur le circuit imprimé directement, ensuite on peut remonter le tout. Et pour tester on les relies au Pi à l’aide d’une plaque de test (BreadBoard).
On peut maintenant déployer un package sur le pi pour connecter notre cible a constellation. Sur Le raspberry Pi, le plus simple est de faire un package python en utilisant la librairie GPIO.
Cette petite fonction va permettre de transformer un couple de GPIOs (entré, sortie), en un message pour constellation contenant une zone de la cible.
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 |
def dartTouch(pinin,pinout): outputDictionary = {} outputDictionary[PIN_TRIPPLE_1] = [3,1] outputDictionary[PIN_DOUBLE_1] = [2,1] outputDictionary[PIN_SINGLE_1] = [1,1] outputDictionary[PIN_BULL] = [0,2] outputDictionary[PIN_SINGLE_0] = [1,0] outputDictionary[PIN_DOUBLE_0] = [2,0] outputDictionary[PIN_TRIPPLE_0] = [3,0] inputDictionary = {} inputDictionary[PIN_9_14_B] = [9,14,50] inputDictionary[PIN_20_16_1] = [20,16,1] inputDictionary[PIN_12_11_B] = [12,11,25] inputDictionary[PIN_5_8_2] = [5,8,2] inputDictionary[PIN_6_2_3] = [6,2,3] inputDictionary[PIN_10_15_4] = [10,15,4] inputDictionary[PIN_13_17_5] = [13,17,5] inputDictionary[PIN_4_3_6] = [4,3,6] inputDictionary[PIN_18_19_7] = [18,19,7] inputDictionary[PIN_1_7_8] = [1,7,8] isButton = False value = inputDictionary[pinin][outputDictionary[pinout][1]] multiple = outputDictionary[pinout][0] if(multiple == 0): isButton = True multiple = 1 if(value == 50): multiple = 2 value = 25 isButton = False if(value == 25): multiple = 1 isButton = False if isButton : Constellation.SendMessage("DartManager", "ButtonPressed",[ value ]) else: Constellation.SendMessage("DartManager", "onDartTargetTouch",[ multiple, value ]) time.sleep(0.8) |
Il ne reste plus qu’à alimenter les pins de sorties une à une et de lire l’état des pins en entrée.
1 2 3 4 5 6 7 |
while True: for pinout in outs: GPIO.output(pinout,GPIO.HIGH) for pinin in ins: if(GPIO.input(pinin)): dartTouch(pinin,pinout) GPIO.output(pinout,GPIO.LOW) |
Une fois notre prototype avec la BreadBoard testé et approuvé nous avons pus réaliser un deuxième prototype sur lequel nous avons juste à venir brancher les pins de notre pi et de notre cible.
Ce prototype moins encombrant, apporte également plus de robustesse à notre jeu dans l’optique d’une utilisation plus fréquente.
Constellation
Afin de pouvoir envoyer l’information qu’une fléchette a touché la cible, de pouvoir traiter l’information pour par exemple savoir si l’utilisateur en a déjà lancé trois et ainsi que cette dernière ne compte pas, puis afficher cette information sur les différentes interfaces graphiques, nous devions créer un bus de données.
Pour cela, nous avons utilisé le principe des “StateObject” et ”MessageCallBack” de Constellation afin de communiquer entre chacune des différentes parties.
Deux packages Constellation ont donc été créé, l’un en Python, pour la détection des fléchettes et l’autre en C# pour la gestion de parties.
Ainsi lorsque qu’une fléchette touche la cible, le package en Python va envoyer cette information au package C# en appelant la méthode “onDartTargetTouch”,
1 |
Constellation.SendMessage("DartManager", "onDartTargetTouch",[ multiple, value ]) |
qui va, après avoir effectué les modifications engendrées par ce coup sur la partie, mettre à jour le StateObject ‘’DartGame’’ afin que, l’UI qui s’y est abonné, soit informé.
1 2 3 4 5 6 7 8 9 10 11 12 |
[MessageCallback] void onDartTargetTouch(short multiple,short value) { PackageHost.WriteInfo(multiple + " "+ value); if(game.applyShoot(new Shoot(multiple, value), this)){} update(); } private void update() { PackageHost.PushStateObject<AbstractDartGame>("DartGame", game); } |
Le StateObject “DartGame” représentant la partie actuelle (joueurs, tours, tirs, etc..) sous forme d’un objet JSON.
Le but étant, une fois les paquets installés sur chacune des machines respectives (“sentinelle” pour Constellation), de pouvoir tout contrôler depuis l’UI. Des MessageCallBack sont donc mis à la disposition de cette dernière, représentant ainsi l’ensemble des fonctions nécessaires à la gestion d’une partie.
User Experience
Le gros point noir de notre cible, comme nous l’avons décrit en introduction, était l’interaction avec les utilisateurs et comme vous pouvez vous en douter après les modifications que nous avons apportés à notre cible l’afficheur de score d’origine n’est plus fonctionnel. Pour le remplacer nous avons donc réalisé un Dashboard sous la forme d’une application web.
Le Dashboard
Le Dashboard comme nous l’avons évoqué ci-dessus est une application qui nous permet d’afficher les scores provenant de notre Constellation simplement en s’abonnant au StateObject du manager de jeu. L’interface de ce Dashboard a été réalisé avec AngularJS et Angular Material pour le design. En effet en nous abonnant à un StateObject via Constellation, le Dashboard est notifié de chaque modification apportées à la partie de fléchette en cours et de modifier l’affichage dynamiquement grâce à l’objet JSON fournis par Constellation tout cela en simplement quelques lignes de codes :
1 2 3 4 5 |
constellation.registerStateObjectLink("*", "*", "DartGame", "*", function (so) { $scope.$apply(function() { $scope.constelationGame = so.Value; }); }); |
La connection du Dahboard à Constellation permet également d’exposer des méthodes afin de déclencher des effets sonores sur certains lancers afin de dynamiser la partie.
1 2 3 4 5 6 7 8 9 10 |
constellation.subscribeMessages("DartsDashboard"); constellation.registerMessageCallback("Triple", function (msg) { var audio = new Audio('sounds/Triple.wav'); audio.play(); }); constellation.registerMessageCallback("Double", function (msg) { var audio = new Audio('sounds/Double.wav'); audio.play(); }); |
Pour le design, Angular Material nous a permis de développer rapidement et simplement une interface esthétique.
L’application mobile
Toujours dans le but d’améliorer les fonctionnalités offertes par notre jeu customisé, une application mobile accompagne notre nouvel objet connecté pour y ajouter une dimension sociale ! Baptisé My Dart Compagnon, elle se destine aux joueurs les plus passionnés.
L’application est réalisée avec Ionic, un Framework open source qui permet de développer des applications mobiles hybrides rapidement et facilement. Il s’appuie sur AngularJS pour la partie application web du framework et sur Cordova pour la partie construction des applications natives. On peut donc très facilement se connecter à Constellation via le SDK JavaScript. Ionic framework permet de développer une seule application et de la déployer sur tous les supports, web ou mobile, que ce soit Android, iOS ou bien Windows Mobile.
De plus, l’application intègre les services Firebase, la plateforme d’outils mobile de Google qui permet d’implémenter un espace de stockage synchronisé et personnel pour l’utilisateur en toute simplicité, en mode cloud. Cet espace peut être accessible par d’autres clients, comme par exemple le Dashboard.
En utilisant l’authentification Facebook, l’application permet de voir ses amis qui l’utilisent également et de les inviter à jouer. Au début de chaque partie, le joueur peut charger son profil sur le Dashboard présenté ci-dessus en flashant un QR Code. Cela lui permet de suivre son score personnel durant la partie sur son smartphone, de consulter l’historique de ses parties disputées et ses statistiques personnelles. Les joueurs les plus compétiteurs chercheront eux à débloquer l’intégralité des succès : des récompenses débloquées lors de la réalisation de certaines actions ou performances.
Bonjour,
Je suis intéressé par votre travail sur votre jeu de fléchettes.
Est-ce toujours réalisable ? (Notamment l’application mobile que je trouve pas sur le store).
J’avoue être aussi perdu dans les connexions entre la matrice et le raspberry. Auriez-vous un schéma de connexion précis entre les 2 ?
Merci d’avance.