Bowling 3D dans le navigateur

EFFET
PUISSANCE
OK

Comment jouer

Une partie se joue de un à quatre joueurs, sur dix carreaux, avec les règles officielles. Trois réglages se suivent avant chaque lancer: la position de départ sur l'approche, l'angle de visée indiqué par la ligne pointillée sur la piste, puis deux jauges. La jauge de puissance monte et descend en continu; il faut la valider dans la zone claire du milieu pour obtenir un lancer franc. La jauge d'effet, elle, détermine la latéralité imprimée à la boule et donc la courbe qu'elle décrira en fin de piste.

Les commandes tiennent volontairement en six boutons: quatre directions, une validation, un retour. C'est jouable au clavier avec les flèches, au doigt avec le pavé tactile affiché sur mobile, et aussi avec une télécommande de décodeur. Cette dernière contrainte n'est pas un caprice: je travaille en intégration de décodeurs, et une interface qui survit à six boutons survit à peu près à tout. Aucune fonction du jeu ne dépend d'un pointeur.

Comment c'est construit

Le rendu utilise Three.js. La scène est volontairement simple: la piste et l'approche sont des BoxGeometry étirées, les dalots deux boîtes étroites de chaque côté, le mur du fond un plan. La texture de bois n'est pas un fichier image — elle est peinte à l'exécution par woodTexture(), qui trace des veines sur un canvas hors écran avant d'en faire une CanvasTexture. Ça évite une requête réseau et garde la page entièrement autonome.

L'éclairage combine une lumière ambiante, une directionnelle qui projette les ombres en PCFSoftShadowMap, et une lumière ponctuelle chaude au-dessus des quilles. Un Fog assombrit le fond de la piste, ce qui donne la profondeur sans avoir à modéliser quoi que ce soit de plus.

La partie qui m'a demandé le plus de travail n'est pas la 3D, c'est le pointage. La fonction computeScores() reçoit dix carreaux, chacun étant la liste de ses lancers, et aplatit le tout en une seule suite en mémorisant l'indice de départ de chaque carreau. C'est ce qui permet de gérer proprement les bonus: un abat vaut dix plus les deux lancers suivants, une réserve dix plus le lancer suivant, et ces lancers peuvent appartenir à un ou deux carreaux plus loin. Tant qu'un bonus n'est pas déterminé, le cumul du carreau reste nul et l'affichage s'arrête là, exactement comme sur une vraie feuille de pointage. Le dixième carreau a sa propre règle: trois lancers si le premier est un abat ou si les deux premiers font une réserve, deux sinon.

La détection des trous — les quilles restées debout mais séparées — se fait dans isSplit() par un parcours de graphe. On part des quilles encore debout, on relie celles dont les positions de base sont distantes de moins de 0,34 unité, et s'il reste plus d'un groupe une fois le parcours terminé, c'est un trou. La quille de tête doit être tombée, sans quoi la situation n'en est pas un.

Ce que j'en ai retenu

Je pensais que la difficulté serait la physique et le rendu. En réalité, Three.js fait le gros du travail visuel, et la boule roule de façon convaincante avec assez peu de code. Ce sont les règles du bowling qui sont retorses, parce qu'un carreau ne peut pas être pointé tant qu'on n'a pas vu ce qui vient après lui. Aplatir les lancers en une seule suite a transformé une série de cas particuliers en deux lignes lisibles.

L'autre leçon est celle des six boutons. Concevoir d'abord pour la télécommande, puis ajouter le clavier et le tactile par-dessus, donne une interface plus claire que l'inverse. La contrainte force à décider ce qui mérite vraiment une commande.