Berloul ! - Un Party Game en Angular

L'idée derrière Berloul ! était de programmer un party game – un jeu pour soirées entre amis – qui serait accessible sur mobile, sans pour autant développer une appli native, ni même proposer l'appli sur les stores.

Berloul ! - Un Party Game en Angular
Berloul !

L'idée derrière Berloul ! était de programmer un party game – un jeu pour soirées entre amis – qui serait accessible sur mobile, sans pour autant développer une appli native, ni même proposer l'appli sur les stores. Je voulais trouver un moyen simple de pouvoir développer des petits prototypes de jeux sans avoir à m'embêter avec les vérifications nécessaires pour que l'appli soit publiée.

Le principe est simple : avec son mobile, on se rend sur l'URL suivante :

https://flusin.ovh/berloul

Le navigateur télécharge les sources du jeu, et l'appli démarre. Aussi simple que ça !

Comment c'est fait ?

L'appli repose sur le framework Angular. Je me suis inspiré des machines à état qu'on trouve souvent dans les jeux vidéos pour gérer l'affichage des vues.

En effet, chaque état est un component Angular différent composé d'une vue HTML, d'un fichier de styles CSS et d'un service.

Au plus haut niveau, un composant est chargé d'afficher le bon composant, suivant l'état dans lequel l'appli se trouve.

  <div *ngIf="currentState === GAME_STATE.NEW_GAME">
    <app-new-game-state
      (_exitState)="exitNewGameState($event)">
    </app-new-game-state>
  </div>

  <div *ngIf="currentState === GAME_STATE.PLAYER_START">
    <app-g-player-start-state
      [turnNumber]="turnNumber"
      [currentPlayer]="currentPlayer"
      (_exitState)="exitPlayerStartState()">
    </app-g-player-start-state>
  </div>

  <div *ngIf="currentState === GAME_STATE.PLAYER_TURN">
    <app-g-player-turn-state
      [currentPlayer]="currentPlayer"
      [currentChallenge]="currentChallenge"
      (_playerPass)="playerPass()"
      (_exitState)="exitPlayerTurnState($event)">
    </app-g-player-turn-state>
  </div>

app.component.html : Affichage du composant correspondant à l'état du jeu

Pour approfondir, vous pouvez jeter un œil aux sources ! Elles se trouvent sur mon Gitlab :

Jérémy Flusin / Berloul
Party Game written in Angular

Le principe du jeu

Berloul ! est la fusion de plusieurs jeux auxquels mes amis et moi aimons jouer. Après avoir saisi le nom des joueurs, on peut démarrer la partie.

Un premier joueur est tiré au sort, et l'appli invite quiconque qui a le téléphone dans les mains à le passer au joueur sélectionné.

C'est au tour du joueur Aurélien !

Quand il clique sur "Je suis prêt", le joueur se voit proposer un défi. Il devra faire deviner quelque chose, dans un thème donné, d'une façon donnée.

Les différents thèmes sont :

  • Un sportif / Une sportive
  • Un politicien / Une politicienne
  • Un acteur / Une actrice
  • Un chanteur / Une chanteuse / Un groupe de musique
  • Un film
  • Un jeu vidéo

Tout le sel du jeu repose dans les différentes façons de faire deviner les mots !

  • Mime : le joueur actif n'a le droit que de mimer, et n'a pas le droit de parler.
  • Un, deux, ou trois mots : le joueur actif commence par donner un mot, et les autres joueurs font leurs propositions. Si personne ne trouve, le joueur actif peut dire un autre mot, puis encore un. Le moins de mots ont été utilisés pour faire deviner, le plus de points seront gagnés par le joueur actif et celui qui a deviné.
    Ex : Bruce Willis = Acteur, Chauve, Action
  • Concepts proches : le joueur actif doit remplacer chaque mot de la carte à faire deviner par un autre dont le concept est proche (synonyme, antonyme, mot de la même famille...).
    Ex : Bon pied bon oeil = Mauvais orteil mauvaise bouche
    Ex 2 : Orange Mécanique = Fraise Hydrolique
Ici, Aurélien n'a plus que 51 secondes pour faire deviner VIncent Lindon en Un, Deux ou Trois mots !

Si un des autres joueurs trouve avant la fin du temps imparti, le joueur actif clique sur Trouvé. Il pourra indiquer à l'appli lequel des joueurs à trouvé le mot, et tous les deux gagneront des points.

Jérémy a trouvé "Vincent Lindon" en 3 mots. Aurélien et lui gagneront des points.

Un nouveau joueur est sélectionné, et ainsi de suite, jusqu'à ce que tous les joueurs aient joué 5 tours.

À la fin, le joueur ayant cumulé le plus de points gagne la partie !

Post-mortem

Cette façon de coder des jeux propose des avantages certains :

  • Rapidité du développement et choix libre des technos JS employées. J'ai utilisé ici Angular pour profiter des *ngIf, et de la notion de components qui collent bien au principe de machine à état, mais tout aurait pu être fait en VanillaJS sans beaucoup plus d'effort.
  • Compatibilité avec tous les smartphones implémentant des navigateurs corrects.
  • Pas de gestion d'appli sur les stores.

Par contre, plusieurs problèmes me sont apparus en jouant, et leur résolution n'est pas triviale, voire impossible :

  • Puisqu'on exécute du code dans un navigateur, on ne peut pas empêcher le téléphone de se verrouiller pendant le tour du joueur. Ça peut poser des problèmes, notamment lorsqu'il reste peu de temps au joueur pour valider le tour et que le téléphone se verrouille à ce moment-là. En plus, le propriétaire du téléphone doit le déverrouiller sans arrêt avec son code ou son empreinte digitale, ce qui peut être vite pénible :)
  • Si un joueur a le malheur d'actualiser la page (swipe down sur la page), la partie est remise à zéro ! Ça nous est arrivé un bon nombre de fois, et c'est très très énervant ! Pour résoudre ça, on pourrait imaginer un data-store qui stocke dans le local storage du navigateur l'état du jeu, les joueurs et leurs score actuel et qui rechargerait la partie en cas de rafraîchissement de la page. Peut-être pour une v2 ?

Pour tout cela, il me semble qu'il faut dédier cette méthode pour l'implémentation de prototypes de jeux / de preuves de concepts exclusivement.

Un mot sur le nom

Berloul signifie "idiot" en Arabe. C'est une petite insulte que mes amis et moi avions l'habitude de nous lancer étant plus jeunes. Une sorte d'hommage, en somme !