CréerExplicationPour auteursS'applique de 4.3.0
Code sur mesure
This page in EnglishCette page sur le wiki GitHub
Quand le DSL ne suffit pas, un jeu définit ses propres commandes en TypeScript. Cette page explique comment elles restent compatibles avec le validateur, le solveur et la sauvegarde, et comment en écrire une.
Les commandes sur mesure
Un jeu exporte ses propres commandes depuis son index.ts (game/index.ts dans un projet créé,
games/<id>/index.ts dans le dépôt du moteur) ; une règle ou un script en appelle une par son nom :
import type { CustomCommands } from 'quest-n-click/content';
export const commands: CustomCommands = {
sparkle: { pure: true, run: async ({ scene, args }) => { /* dessiner des étoiles sur `scene` pendant args.ms */ } },
explode: { effects: [{ set: 'chicken_exploded' }, { lose: 'chicken' }, { sfx: 'boom' }], run: ({ scene }) => { /* l'explosion */ } },
};
// dans une règle ou un script : { custom: 'sparkle', args: { ms: 1200 } }Une commande sur mesure a deux parties (src/engine/core/custom.ts) :
effectsdit ce que la commande fait au jeu, en commandes ordinaires. Elles s'exécutent en premier, dans le navigateur et dans le solveur : une commande sur mesure ne casse donc jamaisnpm run solveni la sauvegarde.runest la partie visuelle, navigateur seulement. Elle reçoit le jeu, l'état à lire, la salle, les arguments (args), le présentateur (ui), l'élément de la scène (scene, peintre DOM seulement) etfast(vrai pendant qu'on passe une cinématique : finir tout de suite). Elle ne tourne ni dans node, ni pendant qu'on passe une cinématique.
Une commande qui ne change rien dit pure: true. Le validateur refuse un { custom } qui nomme une commande que le jeu
n'exporte pas, et une commande qui ne déclare ni effects ni pure ; il vérifie les commandes de effects comme
toutes les autres.
En écrire une
- Dans le
index.tsdu jeu, ajoutez la commande auxcommandsexportées (le modèle en exporte un objet vide). Mettez danseffectschaque changement du jeu, en commandes du DSL ; s'il n'y en a aucun, écrivezpure: true.
- Écrivez
run: dessinez dansscene, attendez votre animation, rangez derrière vous, et rendez la main tout de suite quandfastest vrai.
- Appelez-la depuis une règle, un sujet ou un script :
{ custom: 'explode', args: { … } }.
-
Vérifiez-la :
# dans le dépôt du moteur npm run validate npm run solve# dans le projet créé npx quest-n-click validate npx quest-n-click solvePuis jouez-la sur le serveur de développement (
npm run dev), console du navigateur ouverte : unrunqui change l'état y est signalé.
Un mini-jeu est l'autre sorte de code de jeu : un mini-jeu sur mesure.
Pourquoi les effets sont déclarés
Le contenu est une donnée pour que chaque outil puisse le lire (principes). Une fonction ne se lit pas sans l'exécuter, et le solveur et le validateur tournent dans node, sans navigateur. Déclarer les effets en commandes du DSL permet au solveur de les appliquer sans le code, à la sauvegarde de les retenir, et au rejeu de les reproduire ; le code garde ce que seul un navigateur sait faire, dessiner.
Le code est de confiance : il est livré avec le jeu et haché dans son empreinte (trustedExtensions, si bien qu'un
changement du code d'une commande sur mesure est vu comme tel). Sur un Studio hébergé, le code du jeu, commandes sur
mesure comprises, tourne dans un worker séparé qui ne détient aucun secret de la plateforme
(ADR 0028).
Solutions écartées
- Des fonctions dans le contenu : le solveur devrait exécuter le code du navigateur, ou l'ignorer et prouver un autre jeu.
- Un greffon qui change l'état librement : sauvegardes et rejeux ne reproduiraient plus une partie.
Compromis
Une commande dont l'effet dépend de ce qui se passe dans son run (un jeu de réflexe dont l'issue change l'histoire)
ne s'exprime pas en effects fixes : c'est un mini-jeu, dont le moteur enregistre le résultat et que le solveur
explore. Certaines idées demandent une commande sur mesure là où trois lignes de code auraient suffi.