尚未收集儲存庫資訊。
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
製作者的介紹僅有上面的一句話。 更多詳情請閱讀儲存庫 README。 儲存庫 README ↗
正在載入完整 README。
檢視完整 README ↗Duel de kung-fu en 1 contre 1, sur invitation. On frappe, on pare, on esquive, et on envoie son adversaire dans le lac qui entoure le dojo. Premier à 3 éjections.
Version de développement : Phaser 4, TypeScript et Vite, avec une connexion pair à pair (WebRTC via PeerJS). Le site est entièrement statique et se déploie tel quel sur Vercel.
On commence ceinture blanche avec seulement Frapper et Esquiver. Chaque ceinture, gagnée avec l'XP, débloque une technique, avec un exercice de 20 secondes contre le mannequin :
| Ceinture | XP | Technique |
|---|---|---|
| Blanche | 0 | Frapper et Esquiver |
| Jaune | 100 | Enchaînement de 2 coups |
| Orange | 250 | Parade |
| Verte | 450 | Coup chargé |
| Bleue | 700 | Finisseur (3e coup, +35 % de recul) |
| Marron | 1 000 | Élan (esquive au dernier moment) |
| Noire | 1 400 | Paume du dragon |
La Tour du temple est le mode solo : 12 gardiens, puis une tour sans fin. Chaque étage rapporte 1 à 3 étoiles (victoire, sans perdre de manche, sous le temps de référence). Le tutoriel d'une minute se lance avant le premier étage. Les gardiens utilisent les techniques de leur ceinture. En duel entre amis, les deux joueurs ont toutes les techniques.
Ce qui donne envie de rejouer :
L'accueil est un écran de jeu, pas un site à onglets : ton combattant en grand sur la plateforme du monde choisi (il salue en arrivant), un gros bouton Jouer (étage suivant de la Tour, ou le tutoriel la première fois), puis Défi du jour, Entraînement et Duel. En bas à gauche : nom, ceinture, XP, prochaine technique, Vestiaire et Étages. La roue en haut à droite ouvre les paramètres (commandes, son, plein écran, mode test). Entraînement et Duel s'ouvrent dans un panneau à droite, le décor reste visible.
On s'échauffe à l'accueil : un mannequin d'entraînement se tient à côté de ton combattant. Sur ordinateur, ZQSD ou flèches pour bouger, J frapper, K parer, Espace esquiver, 1 à 4 pour les emotes (le clavier ne marche qu'à l'accueil, pas dans les autres écrans). Au toucher ou à la souris : toucher la plateforme, le combattant y marche ; toucher le mannequin, il va le frapper ; toucher son combattant ouvre le Vestiaire. Le mannequin encaisse sans tomber et revient à sa place.
Tout ce qui change l'apparence au même endroit : combattant (gagné en battant le gardien d'un étage), arme (gagnée avec une ceinture), traînée et plouf (achetés avec les pièces). On y entre par le bouton Vestiaire ou en touchant son combattant sur la plateforme.
Les pièces se gagnent en jouant : Tour (plus avec les étoiles, la première victoire et la série), défi du jour, entraînement et duels. Rien ne s'achète en euros.
| Traînées de coup | Ploufs d'éjection |
|---|---|
| Braises, pétales de cerisier, fumée d'ombre, poussière d'étoiles, vague, shurikens, pluie d'or | Encre, tempête de pétales, cochon volant, fantôme, feu d'artifice, trésor englouti, phénix |
La traînée suit le bout de l'arme pendant le coup, au premier plan et en transparence. Le plouf est celui du joueur qui éjecte, donc l'adversaire le voit aussi. Dans le vestiaire, chaque effet se joue en situation derrière le panneau : ton combattant frappe un mannequin pour une traînée, ou l'envoie à l'eau pour un plouf.
Le Mode test, replié dans les paramètres (roue en haut à droite), permet de :
npx tsx scripts/towercheck.ts 0.45 simule un joueur moyen qui monte la Tour (pourcentage de victoires par étage).
Entraînement lance un duel contre un bot (Disciple, Adepte ou Maître) dans le monde choisi, sans réseau.
| Action | Clavier et souris | Tactile |
|---|---|---|
| Se déplacer | ZQSD, WASD ou flèches | Joystick à gauche |
| Viser | Automatique vers l'adversaire (comme sur mobile) ; souris si on désactive la visée automatique dans les réglages | Automatique vers l'adversaire |
| Frapper (coup blanc) | Clic gauche ou J, appui court | Frapper |
| Coup chargé rouge | Maintenir clic gauche ou J | Maintenir Frapper |
| Parer | Clic droit ou K | Parer |
| Esquiver | Espace ou Shift | Esquive |
| Emotes | 1 à 4 | Emote |
| Quitter | Échap | Bouton Quitter |
Le triangle : la parade bat le coup blanc, le coup rouge brise la parade, un coup blanc interrompt une charge. L'esquive évite tout mais coûte un souffle sur trois. Plus le pourcentage est haut, plus on vole loin.
npm install
npm run dev # serveur de dev Vite sur http://localhost:5173
npm run build # vérification TypeScript puis build de production dans dist/
npm run preview # sert le build de production
npm run sim # duels bot contre bot dans le terminal, pour vérifier l'équilibrage
npm test # tests Vitest (non-régression de la simulation)
Tests de non-régression : tests/sim.golden.test.ts joue des matchs à graine fixe (createSim(specs, { seed })) et compare leur résumé à tests/__snapshots__/. Si un réglage de RULES change volontairement le combat, accepter les nouveaux résumés avec npm test -- -u. Sinon, un échec signale une régression.
Tester un duel seul sur sa machine : ouvrir http://localhost:5173/?net=local, créer un duel, puis ouvrir le lien d'invitation dans un deuxième onglet du même navigateur. Les deux onglets communiquent par BroadcastChannel, sans passer par Internet.
Débogage : ajouter ?debug à l'adresse expose window.__kata (game, session) dans la console, y compris sur le build de production.
src/
sim/ simulation du duel, sans Phaser ni DOM (passera telle quelle sur un serveur)
sim.ts point d'entrée : createSim, stepSim, API publique
data.ts réglages (RULES), gardes, coups, apparences (aucune dépendance)
progression.ts ceintures, techniques débloquées, étages de la Tour, étoiles, XP
core.ts types, outils, hasard à graine, événements
fighter.ts création et remise en place d'un combattant
duel.ts manches, mort subite, points
actions.ts entrées et actions (coups, charge, parade, esquive)
hits.ts résolution des coups, bord du dojo, chute, éjection
update.ts avancée d'un combattant d'un pas, collisions
bot.ts bot d'entraînement et mannequin
snapshot.ts instantanés réseau et miroir de l'invité
net/transport.ts connexion PeerJS (production) ou BroadcastChannel (?net=local)
net/session.ts modes entraînement / Tour / tutoriel / hôte / invité, revanche, ping
game/assets.ts chargement des sprites et du décor SVG
game/render/ rendu Phaser en vue isométrique 2:1 (index.ts : le Renderer)
iso.ts projection et formes posées au sol
palette.ts couleurs, polices
themes.ts ambiances des dojos et vie de chaque dojo
arena.ts plateforme du dojo (dessinée en code) et lanternes
lake.ts poissons, objets flottants, ronds dans l'eau, reflets, particules d'ambiance
effects.ts étincelles, anneaux, lignes de vitesse, sprites d'impact, ploufs, textes flottants
fighters.ts combattants, armes, annonce du coup chargé, traînées, emotes
game/audio.ts sons et musique synthétisés en WebAudio (aucun fichier audio)
game/tutorial.ts étapes du tutoriel et exercices par technique
game/hints.ts indices affichés les premières fois
scenes/GameScene boucle de jeu, caméra, souris
scenes/HudScene interface en jeu (pourcentages, souffle, qi, score)
ui/ écrans HTML (ui.ts : branchement des boutons et des événements de la partie)
dom.ts, nav.ts utilitaires, écran affiché
profile.ts profil et progression sauvegardés dans le navigateur (sans DOM)
home.ts accueil (écran de jeu), entraînement, panneau de test
launch.ts lancement des parties locales
floors.ts liste des étages
shop.ts vestiaire : combattant, arme, traînées, ploufs
lobby.ts duel privé et retour à l'accueil
result.ts écran de fin de partie
tutobar.ts barre du tutoriel
actionbar.ts barre d'actions animée (boutons sur mobile, indicateurs sur ordinateur)
controls.ts clavier et commandes tactiles
viewstate.ts état partagé entre l'interface et la scène
tests/ tests Vitest (non-régression de la simulation)
scripts/simcheck.ts duels bot contre bot dans le terminal
scripts/towercheck.ts équilibrage de la Tour
scripts/build-assets.py assemble les sprites du pack Ninja Adventure dans public/assets
scripts/build-decor-svg.py génère le décor vectoriel (horizons, poissons, flottants) dans public/assets/decor
archive/ assets retirés du jeu, gardés pour plus tard (non déployés)
Modèle réseau : le joueur qui crée la salle est l'hôte. Son navigateur fait tourner la simulation à 60 pas par seconde et arbitre chaque coup. L'invité envoie ses entrées (déplacement, visée, boutons) et reçoit 30 instantanés par seconde avec les événements à afficher (impacts, sons, textes). La simulation (src/sim) ne dépend ni de Phaser ni du DOM : c'est le module qui passera tel quel sur un serveur dédié.
Messages échangés :
| De | Message | Contenu |
|---|---|---|
| Invité | hello | nom et apparence |
| Hôte | welcome | les deux combattants |
| Invité | in | entrées compactées, à chaque changement et au moins toutes les 100 ms |
| Hôte | s | instantané de l'état et événements depuis le dernier envoi |
| Les deux | rematch | demande de revanche ; l'hôte répond restart quand les deux l'ont demandée |
| Hôte | away | l'onglet de l'hôte est en arrière-plan, le combat est en pause |
| Les deux | ping / pong | mesure de la latence affichée en jeu |
Six ambiances en SVG vectoriel : coucher, bambou, brume, neige, neon, volcan. La Tour change de dojo tous les deux étages dans cet ordre, puis recommence ; le défi du jour en tire un d'après la date. En duel entre amis, l'hôte choisit le dojo dans le salon (ou « au hasard ») et il est transmis à l'invité. ?theme=<nom> force une ambiance.
Les éléments importants de chaque horizon sont groupés au centre (entre x=500 et x=1900 sur 2400) : c'est la zone visible sur téléphone en paysage comme sur ordinateur.
Chaque dojo a ses poissons (koï, carpes, poissons-lanternes, poissons de braise), ses objets flottants (nénuphars, glace, roches de lave, lanternes) et ses particules (pétales, feuilles, neige, lucioles, braises). Chaque poisson est un seul SVG déformé en tranches (Rope Phaser) : une onde de nage le parcourt de la tête à la queue, la queue se déporte dans les virages, et il avance par à-coups puis glisse. Ils sont petits, translucides et teintés par l'eau pour se fondre dans le décor, et ils effleurent la surface de temps en temps. Ils nagent sous le dojo, s'enfuient après un plouf ou un gros coup, et les nénuphars sont repoussés par les remous. L'eau scintille.
Tout est généré par python3 scripts/build-decor-svg.py (aucun asset externe) dans public/assets/decor/ : bg-<dojo>.svg, fish-<espèce>.svg, float-<nom>.svg. Ce sont des SVG propres, retouchables dans Inkscape ou Penpot ; pour changer un décor, modifier le script ou le fichier.
Le cône pâle des petits coups est supprimé (il brouillait le combat) : seul le coup chargé est annoncé au sol.
Arrêt sur image et tremblement d'écran à l'impact, lignes de vitesse (éclat radial et traînées dans le sens du recul, plus fortes pour le coup chargé et la paume du dragon), flashs de couleur plein écran (blanc, rouge, doré), petit coup de zoom à l'impact et zoom marqué avec trois éclats de lignes sur l'éjection décisive.
Le jeu explique ce qui arrive, sans tutoriel supplémentaire : indice la première fois que le souffle tombe à zéro (« Souffle épuisé »), message de spam (« Tu martèles l'attaque… »), et, à chaque éjection, la cause (épuisé, pourcentage élevé, ou bord du dojo). Les indices ponctuels s'arrêtent après 3 à 4 affichages (mémorisés dans le navigateur).
src/analytics.ts envoie des événements anonymes (identifiant aléatoire local, pas de donnée personnelle) à /api/e, une fonction Vercel (api/e.js) qui les écrit en JSON dans les journaux Vercel (k:"kata_e"). Désactivé en local (sauf ?analytics) et si le navigateur demande « ne pas suivre ». VITE_ANALYTICS_URL remplace l'adresse de réception.
| Événement | Contenu |
|---|---|
page_view | appareil, taille d'écran, invitation ouverte ou non |
play_clicked | tour, défi du jour, entraînement, création de duel |
tutorial_started, tutorial_completed | exercice ou tutoriel complet |
match_started | mode, étage, niveau, dojo, revanche ou non |
match_ended | résultat, score, durée, coups donnés et reçus, parades, esquives parfaites, déclenchements et blocages d'anti-spam, coups reçus en étant épuisé, éjections |
match_abandoned | où le joueur quitte : manche et score |
rematch_clicked, invite_opened, disconnect, error |
Avec ?debug, window.__kata.stats() donne les compteurs de la session.
La vue est isométrique (losange 2:1). La simulation reste à plat en (x, y) ; render.ts projette tout à l'écran et les sprites restent debout. Les touches et le joystick suivent l'écran (haut = vers le fond du dojo), la souris est reconvertie dans le monde.
Les visuels de référence sont dans art/reference/ : fiche du personnage (gi bleu, ceinture rouge), maquette de l'accueil (bois, parchemins, néon) et trois arènes. Les arènes servent de thèmes : brume (jardin sous la brume), coucher (cartoon, soleil couchant) et neon (nuit). La plateforme est dessinée en code pour pouvoir rétrécir en mort subite ; les horizons viennent des visuels (public/assets/bg/). Dans la Tour, les étages 1 à 4 sont au coucher de soleil, 5 à 8 dans la brume, 9 et plus au néon. Avec ?theme=brume|coucher|neon, on force une ambiance.
Décision : sur téléphone, le jeu se joue en paysage. En portrait, un écran « Tourne ton téléphone » prend la place. En paysage court (hauteur de 540 px ou moins), l'interface se compacte : accueil resserré, vestiaire en panneau à droite, commandes réduites, HUD en haut. Le plein écran (réglage « Plein écran », touche F, ou premier toucher sur Android) masque la barre du navigateur ; sur iPhone il faut « Sur l'écran d'accueil » (le manifeste demande plein écran et paysage).
À faire une seule fois :
Rev0li/kata-io.npm run build, dossier dist (déjà fixés dans vercel.json). Cliquer sur Deploy.main redéploie la production ; chaque branche ou pull request obtient une adresse de prévisualisation.Aucune variable d'environnement n'est nécessaire.
0.peerjs.com). Il convient au développement, pas à une mise en production à grande échelle.src/sim tel quel, hébergé hors de Vercel (Fly.io, Railway ou un VPS), car Vercel ne garde pas de connexion WebSocket ouverte.Les personnages, armes, effets, objets et le sol du dojo viennent du pack Ninja Adventure de Pixel-boy et AAA, publié sous licence CC0 1.0 (domaine public, usage commercial autorisé, attribution appréciée mais non obligatoire). Sources utilisées :
python3 scripts/build-assets.py <dossier NinjaAdventure> <dossier superpowers-asset-packs> régénère public/assets ; les commandes de clonage sont en tête du script. La version complète du pack (50 personnages, 30 monstres, sons et musiques) se télécharge sur itch.io et peut enrichir la liste.