Underground 2 Revived
Play Need for Speed: Underground 2 (2004) in Chrome and Firefox with WebGPU graphics, Web Audio, up to 120 fps widescreen, controller support, free roam and Online races with friends. Fan project, not
翻譯準備中
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證1st year project online adaptation
翻譯準備中
取自儲存庫 README
正在載入完整 README。 以下為已儲存的摘錄。
Un projet de première année en Java, réécrit dix ans plus tard en jeu de combat au tour par tour jouable dans un navigateur : solo contre l'IA, classé en ligne, matchs privés entre amis, construction d'équipe et progression. Les sources d'origine sont conservées telles quelles dans legacy/ — c'est de là que viennent les dés, les sorts et l'humour de vie étudiante. Tu diriges une équipe de 3 personnages. Un seul combat à la fois sur le terrain, comme dans un Pokémon : tu peux changer de combattant, mais ça coûte un tour.檢視完整 README ↗
Un projet de première année en Java, réécrit dix ans plus tard en jeu de combat au tour par tour jouable dans un navigateur : solo contre l'IA, classé en ligne, matchs privés entre amis, construction d'équipe et progression.
Les sources d'origine sont conservées telles quelles dans legacy/ —
c'est de là que viennent les dés, les sorts et l'humour de vie étudiante.
Tu diriges une équipe de 3 personnages. Un seul combat à la fois sur le terrain, comme dans un Pokémon : tu peux changer de combattant, mais ça coûte un tour.
Un personnage n'a pas de type. Ni élément, ni faiblesse écrite d'avance : ce sont les cartes qu'on lui équipe qui décident de ce qu'il encaisse et de ce qu'il fait passer. La teinte d'un sort ne sert qu'à choisir sa couleur et son animation.
Le dé, hérité de la V1, est le cœur du système. Chaque sort a un nombre de faces. Peu de faces = résultat fiable ; beaucoup de faces = loterie. Le jet module les dégâts entre 55 % et 100 %… et tomber sur la face maximale déclenche un coup critique. Le « Balayage de l'Enfer » a un dé à 66 faces : quand il passe, il efface.
À cela s'ajoutent :
Chaque personnage et chaque sort possède ses propres gènes tirés à l'obtention, de 0 à 31 par caractéristique. Deux « Boule de Feu » ne se valent pas. S'ajoutent les natures (+10 % sur une stat, −10 % sur une autre) et les niveaux (1 à 50).
On peut retirer tous les gènes d'un personnage contre des crédits, ou en perfectionner un seul contre de l'essence.
Aux niveaux 25 et 50, chaque personnage ouvre un choix entre deux talents. Ils dépendent du rôle — un tank arbitre entre renvoyer les dégâts et entrer avec un bouclier, un mage entre le critique et un plancher sur son dé — et les deux options d'un palier tirent dans des directions opposées. Vingt-quatre talents en tout, calibrés par simulation : aucune paire ne dépasse 63 / 37.
Un doublon dont on ne fera rien se dissout en essence. L'essence perfectionne un gène, change un talent déjà choisi, et alimente la Forge : le sort qu'on désigne, sans passer par le hasard. Ses gènes sortent avec un plancher de 14/31 — corrects, jamais parfaits, pour qu'un exemplaire forgé ne remplace pas un coup de chance en booster.
Chaque espèce a sa liste thématique de sorts, et tout sort ouvert à son rôle s'y ajoute. La liste garde l'identité du personnage, le rôle garantit qu'aucune carte tirée en booster ne reste inutilisable par personne.
Combattre → gagner des crédits, des éclats et de l'XP → acheter des personnages, des sorts et des objets à la boutique du jour ou les invoquer → dissoudre les doublons en essence → affiner son équipe dans l'Atelier → remonter le classement de la saison.
La défaite rapporte aussi : environ 40 % des gains. Une partie n'est jamais perdue pour rien.
ELO avec facteur K dégressif, huit divisions (Bois → Légende), saisons de quatre semaines. Quand personne n'est en file après 18 secondes, tu affrontes l'équipe réelle d'un autre joueur, pilotée par l'IA : le ladder reste jouable même à trois joueurs connectés, et les points comptent.
packages/
engine/ moteur de jeu en TypeScript, déterministe, sans dépendance
server/ API REST (Express) + persistance SQL
client/ interface React + Vite
legacy/ le projet Java de 2016, intact
api/ point d'entrée serverless (Vercel)
Le moteur est partagé. Le serveur l'utilise pour arbitrer les combats, le client pour afficher les mêmes données (noms, puissances, table des éléments) sans les dupliquer. Il est déterministe : à graine égale, un combat se rejoue à l'identique, ce qui rend l'IA simulable et les bugs reproductibles.
Le serveur fait autorité. Le client n'envoie que des intentions
({type:'SORT', index:2}) ; toute la résolution a lieu côté serveur, qui
renvoie un flux d'événements horodatés. Le client se contente de rejouer ce
flux en animations.
Aucun WebSocket. Le jeu est au tour par tour : les combats en ligne fonctionnent par interrogation périodique (1,6 s). C'est suffisant, et ça permet un hébergement serverless gratuit.
Deux pilotes SQL interchangeables derrière la même interface : SQLite en local, Postgres en déploiement. Le SQL est écrit une seule fois.
Presque aucun asset. Les bruitages sont synthétisés par la Web Audio API,
et chaque personnage possède un avatar SVG généré depuis sa fiche d'art
(couleurs, silhouette, accessoire). Les cartes peuvent afficher à la place une
illustration peinte, quand elle existe : outils/art/generer.mjs les produit
hors ligne via un endpoint compatible OpenAI, les ramène en WebP 512² — la
plus grande carte fait 268 px de large — et les recense dans un manifeste. Un
personnage sans illustration retombe sur son avatar SVG, donc le jeu reste
complet avec zéro image commitée et la direction artistique reste réversible.
La génération lit ARENE_IMAGE_URL, ARENE_IMAGE_KEY et ARENE_IMAGE_MODEL.
La production, elle, ne connaît ni clé ni latence : elle ne sert que le
résultat.
npm install
npm run build # construit le moteur, le client et le serveur
npm start # http://localhost:3000
En développement, avec rechargement à chaud :
npm run dev # client sur :5173, API sur :3000
La base SQLite est créée automatiquement dans donnees/. Crée un compte : tu
reçois 4 personnages, 16 sorts, 2 500 crédits et 60 éclats.
| Commande | Effet |
|---|---|
npm run typecheck | vérifie les trois paquets |
npm run build:engine | reconstruit uniquement le moteur |
| Variable | Défaut | Rôle |
|---|---|---|
PORT | 3000 | port d'écoute |
ARENE_SECRET | généré et gardé dans donnees/.secret | signature des jetons de session |
DATABASE_URL / POSTGRES_URL | — | bascule sur Postgres si défini |
ARENE_DATA_DIR | ./donnees | emplacement de la base SQLite |
ARENE_ORIGINE | * | origine autorisée (CORS) |
ARENE_DEBUT_SAISON | 5 janvier 2026 | date de référence des saisons |
Voir DEPLOIEMENT.md pour la mise en ligne sur Vercel
(offre gratuite) et pour l'auto-hébergement.
MIT — voir LICENSE.