
Mountain Fighters
Beat’em up satirique : sept nains contre Elon Musk pour sauver Blanche-Neige
Jeu webaoût 2026TypeScriptCanvas 2DWeb AudioWebRTC (PeerJS)Vite
Beat’em up satirique dans le navigateur : sept nains en blouson de cuir affrontent les sbires d’Elon Musk sur 70 cartes. Coopération jusqu’à quatre joueurs en local, jeu en ligne par simple lien, avec une simulation déterministe et des graphismes entièrement vectoriels générés par le code.
But du projet
Elon Musk a enlevé Blanche-Neige pour la disséquer et en construire un clone robot. Les sept nains posent leurs pioches et partent la délivrer. Le jeu revendique la profondeur de combat d’un Street Fighter (données de frames, annulations, jongles, parades, jauge) dans la structure d’un Final Fight : défilement horizontal, vagues d’ennemis, armes à ramasser, coopération.
Fonctionnalités
- 70 cartes, avec un boss toutes les cinq cartes, jusqu’à Elon Musk lui-même.
- 7 nains jouables, chacun avec ses coups, son arme et son ultime.
- Ennemis variés : gardes, agents armés de taser, boucliers anti-émeute, robots de sécurité, aspirateurs autonomes, réfrigérateurs connectés, drones de livraison, stagiaires, lobbyistes.
- Armes à ramasser et échanger (chaînes, battes, barres de fer, boucliers, portière de Cybertruck) et véhicules sur onze cartes (moto, Cybertruck, capsule Hyperloop, fusée).
- Cinématique d’ouverture, passable, jouée une seule fois.
- Multijoueur local jusqu’à quatre sur un clavier ou avec des manettes, et en ligne en envoyant un lien, depuis l’accueil ou le menu pause.
- Commandes tactiles qui s’effacent dès qu’un clavier ou une manette est utilisé ; toutes les touches sont reconfigurables, y compris en pleine partie.
Fonctionnement
- TypeScript et Vite, sans framework ; rendu Canvas 2D dans un espace virtuel de 640×360 adapté à la fenêtre. Seules dépendances à l’exécution : PeerJS et deux polices libres (Barlow, Barlow Condensed).
- Aucune image ni fichier audio : personnages, décors et effets sont de la géométrie vectorielle animée par squelette, sons et musique sont synthétisés en WebAudio. Le jeu pèse environ 420 Ko compressés, polices comprises.
- Simulation déterministe à 60 Hz : pas de
Math.randomni d’horloge, un générateur à graine uniquement. Les cinq premières cartes sont écrites à la main, les suivantes générées à partir d’une graine fixe. - Netcode lockstep à délai d’entrée avec somme de contrôle : avant le combat, l’hôte mesure la latence et la gigue puis fixe un tampon d’entrées commun. Les entrées passent sur un canal non ordonné, l’état du salon sur un canal ordonné.
- Mise en relation et relais : la signalisation passe par le serveur public de PeerJS, puis les pairs communiquent directement. Pour les réseaux qui bloquent la connexion directe, le jeu récupère des identifiants TURN temporaires sur
https://lp177.fr/ice(modifiable avecVITE_ICE_ENDPOINT) ; sans relais joignable, il se rabat sur STUN et l’indique. Le salon affiche la route choisie (directe ou relayée, UDP ou TCP), la latence et le tampon retenu. - Le build vérifie les types et lance deux validations (contenu et netcode) avant de produire
docs/pour GitHub Pages.
Capture d’écran
Jouer
Le jeu se joue dans le navigateur : lp177.github.io/MountainFighters. Pour jouer en ligne, il suffit d’envoyer le lien du salon : l’ami clique, choisit un nain et rejoint le combat.
En local :
npm install
npm run dev # http://localhost:5173
npm run build # build dans docs/Un relais TURN fixe peut aussi être déclaré dans un fichier .env (voir .env.example) ; ces valeurs sont intégrées au moment du build.
Contrôles
| Action | Joueur 1 | Joueur 2 | Manette |
|---|---|---|---|
| Se déplacer | ZQSD (WASD en QWERTY) | Flèches | Stick gauche / croix |
| Attaque légère | F | Pavé num. 1 | A / ✕ |
| Attaque lourde | G | Pavé num. 2 | B / ○ |
| Sauter | Espace | Pavé num. 0 | X / □ |
| Spécial | H | Pavé num. 3 | Y / △ |
| Garde | Maj | Pavé num. . | RB / R1 |
| Saisir | R | Pavé num. 5 | LB / L1 |
| Ramasser / utiliser | E | Pavé num. 4 | LT / L2 |
| Super | T | Pavé num. + | RT / R2 |
| Pause | Échap | Échap | Start |
Double appui sur une direction pour un sprint ; garde au moment de l’impact pour parer. Saut + attaque légère donne un coup de genou volant, saut + attaque lourde un coup de pied qui met l’adversaire au sol.
