Travailler dans l'App¶
Une fois connecté, l'App s'ouvre sur son atelier : une seule fenêtre, où un jeu se dessine, se code, se joue et se publie sans jamais recharger de page. Les mots qu'il emploie, projet, modèle, carte, niveau, attache, groupe, release, sont définis dans Projets, cartes, niveaux, releases. L'atelier est en anglais : ses libellés sont cités tels quels.
Le chemin d'un jeu : envoyer ses sprites et en faire des modèles ; dessiner une carte ; faire dessus un niveau, y poser les modèles et compiler le niveau dans le projet ; écrire main.lua, ▶ Play, corriger, rejouer ; publier.
La fenêtre¶
| Où | Panneaux |
|---|---|
| à gauche | Project (l'arbre du projet ouvert), Library (tout ce que possède votre compte) |
| au centre | les onglets : cartes, niveaux, fichiers, sprites, sons, le jeu en cours, la bibliothèque publique |
| à droite | Inspector : la fiche de ce qui est sélectionné, avec ses champs et ses boutons |
| en bas | Output, Budget, Tiles, Decors |
La barre du haut porte le choix du projet et son + (nouveau projet), ▶ Play, Public library, Reset layout, et les liens vers le simulateur, votre compte et, pour les administrateurs, l'administration.
Un clic sélectionne : l'inspecteur montre la fiche, et si la chose est déjà ouverte son onglet passe devant. Un double-clic ouvre un onglet au centre : une carte, un niveau ou un fichier dans l'arbre, un sprite ou un son dans la bibliothèque. Fermer un onglet modifié demande d'abord : Save, Discard ou Cancel. Rien ne se sauve tout seul ; quitter la page avec des changements en cours demande aussi.
Deux raccourcis valent partout, éditeur de code compris : Ctrl+S (⌘+S) sauve le dernier onglet regardé au centre, Ctrl+Entrée (⌘+Entrée) lance le projet.
Les panneaux se tirent, s'ancrent ailleurs et se redimensionnent ; la disposition est retenue par le navigateur, et Reset layout la remet en place. Les sections de la bibliothèque se replient et se déplient, retenues aussi. L'adresse suit le projet ouvert et le nœud sélectionné : elle se met en favori.
Projets¶
+ dans la barre du haut crée un projet à partir d'un titre (le slug en est tiré : minuscules, chiffres, - et _). Il naît avec un main.lua, _update() et _draw(), les deux fonctions que la console appelle à chaque trame.
Le panneau Project ne montre que le projet ouvert :
- Files :
main.luad'abord, puis les autres.luaet.mask. La fiche du dossier crée un fichier (sans extension, c'est un.lua) et envoie des fichiers :.lua,.mask,.son,.sfx, ou.wav, converti en effet ; un nom que vous avez déjà est remplacé. La fiche d'un fichier le supprime, jamaismain.lua. Les<niveau>.luaet<niveau>.maskqu'écrit la compilation sont marqués generated : ils s'ouvrent en lecture seule, et la compilation suivante les réécrit. - Levels : les niveaux attachés au projet, chacun avec sa carte (Map: …), ses objets et sa fiche Compile ; un niveau dont la carte a changé depuis sa compilation porte un badge recompile. Un niveau s'attache en se compilant, projet coché ; il n'y a rien à « lier ». Un niveau non attaché le dit sur sa fiche, avec Compile into <projet>… ; un niveau attaché propose Detach from this project, qui retire aussi le
<niveau>.luaet le<niveau>.maskque sa compilation a écrits (un.luade ce nom écrit à la main reste). - Maps : les cartes de ces niveaux, chacune une fois, avec ses tuiles, ses calques, sa collision, ses terrains, ses décors et ses sources.
- Audio : les sons du projet, et sur la fiche du dossier les bundles audio qui lui sont attachés.
- Versions : ce qui a été publié, et la publication elle-même.
La fiche du projet donne sa taille et, sous What the console allows, le compte des bornes de la console : palettes sur 12, fonds sur 16, kilo-octets sur 2 048. La compilation d'un niveau refuse de l'attacher à un projet qu'il ferait déborder. Export .zip télécharge tous les fichiers du projet ; Delete this project demande de retaper son slug : ses versions publiées restent en ligne.
Jouer¶
▶ Play ouvre le jeu dans un onglet du centre et le lance avec les fichiers tels qu'ils sont dans l'éditeur, sauvés ou non : on joue ce qu'on voit. Les niveaux jouent tels qu'ils ont été compilés en dernier. ▶ Restart et ■ Stop sont au-dessus de l'écran, avec le bouton du son et ↻ Auto-restart (retenus tous deux). Le jeu a le clavier tant qu'il a le focus ; ailleurs, un voile dit Click to play, et Files changed — click to restart quand un onglet a changé depuis le lancement.
Auto-restart, actif par défaut, relance le jeu tout seul quand un fichier sauvé change ou qu'un niveau est écrit dans le projet (sauvé ou compilé) : sauvez, et le jeu joue le nouveau code. Taper dans un onglet ne relance rien ; le voile reste. Éteignez-le pour garder une partie en cours pendant que vous éditez ; le rallumer applique ce qui attend.
Changements en direct. Pendant que le jeu tourne, un niveau ouvert dans un onglet y pousse deux choses aussitôt, sans relance : les comportements que vous enregistrez (celui d'un modèle, la copie propre d'un objet : les objets concernés repartent de leur premier état) et la position d'un objet que vous déplacez. Essayez une vitesse, regardez, essayez-en une autre. Tout le reste des objets (un de plus ou de moins, un autre modèle, la visibilité, une propriété) attend le prochain enregistrement, qui relance le jeu.
Touches : les flèches sont la croix, Espace ou Z le bouton A, X le bouton B ; les manettes marchent aussi. La ligne sous l'écran est la barre d'état du simulateur : la scanline la plus chargée, la display list, le pool, les sprites manquants, le tas Lua, les lignes en retard.
La première erreur fige le jeu et part dans Output avec un bouton fichier:ligne qui ouvre le fichier à cette ligne, y compris un module chargé par require.
La fiche Game du projet (son bouton Game) écrit main.lua depuis une courte configuration — les niveaux dans l'ordre, ce que le pot vaut au départ, les règles qui passent d'un niveau au suivant, le HUD — et le panneau Pot, à côté d'Output, montre pendant que le jeu tourne ce que les comportements partagent ; voir Les comportements. Un comportement enregistré pendant que le jeu tourne y entre sans relance.
Publier une version¶
La fiche Versions publie le jeu : quelques notes, la licence, la case à cocher, et Publish vN. Une version est figée : elle ne bouge plus quand vous continuez à travailler, et chacun peut la jouer et la cloner. La fiche dit si le projet a changé depuis la dernière version ; un fichier non sauvé n'est pas publié.
Publier un jeu le publie avec ses sources. Si le jeu emploie des niveaux (attachés, ou dont il porte le <niveau>.lua généré), la fiche les nomme et demande une catégorie : publier le jeu publie aussi chacun de ses niveaux dans les niveaux publics, avec sa carte, les modèles qu'il place et leurs sprites. Les sprites encore privés entrent dans la bibliothèque publique d'assets, en catégorie misc (divers), avec le slug du projet pour tag ; leur auteur les reclasse ensuite depuis leur fiche. C'est tout ou rien : un niveau introuvable, un niveau périmé (sa carte a changé depuis sa compilation : recompilez-le), un modèle ou un sprite disparu, ou quelque chose de non déclaré font refuser la publication, et rien n'est publié. Un jeu sans niveau (du Lua et des fichiers) se publie sans ces questions.
La licence suit ce que le jeu contient : CC BY dès qu'un élément l'est (un sprite, un son, une source de carte, ou le clone d'un jeu CC BY), sinon CC0 ou CC BY au choix. Une version CC BY porte un credits.txt à côté de ses fichiers, votre pseudo en tête, puis chaque crédit qu'elle doit. Voir Licences et crédits.
Quiconque clone le jeu reçoit donc ses sources : ses niveaux, leurs cartes, modèles et sprites arrivent dans sa bibliothèque, prêts à être modifiés et recompilés. Withdraw the game supprime toutes ses versions publiées : le jeu quitte la galerie et ne se joue ni ne se clone plus. Le projet reste, et les clones déjà faits aussi, qui n'y renvoient plus ; ses niveaux publics peuvent ensuite se retirer.
La bibliothèque¶
Le panneau Library, c'est tout le compte, partagé par tous ses projets. Chaque section a son +.
- Models : ce qu'un niveau place. Un modèle a un nom (une clé Lua :
joueur,torche), une boîte de collision en pixels (phy.new), une ancre du coin de la boîte au coin du bitmap (phy.anchor), un état par défaut, et des états : chacun un sprite de la bibliothèque, sa cadence en trames par image, sa boucle et ses effets (alpha, contour, derrière). Le joueur est un modèle à plusieurs états (repos,av_gauche,av_droite) ; une torche, un modèle à un seul. Un modèle placé dans un niveau ne se supprime pas. - Sprites : un sprite seul, ou une bande animée dont le nom dit le nombre de frames (
torche_4.png). On les envoie par +, ou en déposant des PNG sur la section ; l'atelier demande d'où ils viennent. Envoyer un nom que vous avez déjà le remplace. Un double-clic montre le sprite et joue son animation, en lecture seule. Les tuiles et le fond se dessinent dans l'éditeur de cartes, pas ici. - Maps : toutes les cartes du compte, avec le nombre de niveaux qui les emploient ; + en crée une, vide (un nom, une taille de 80×60 à 256×128 tuiles) ou depuis une grille (voir le format grille), et l'ouvre.
- Levels : tous les niveaux du compte, attachés ou non, avec leur carte ; + en crée un sur la carte choisie (la fiche d'une carte propose aussi New level on this map).
- Sounds et Audio bundles : les effets (
.wavconverti, ou.sfx) et les musiques (.son, éditées en texte dans leur onglet et écoutées là), regroupés en bundles qu'un projet attache. Voir snd.
La bibliothèque publique¶
Public library, dans la barre du haut, ouvre un onglet à trois rayons : Sprites, Levels et Games. Sprites et niveaux se parcourent par catégorie, chacune avec son compte, et se cherchent par nom, tag ou auteur ; un clic sur un tag montre tout ce qui le porte. Cliquer une vignette montre sa fiche dans l'inspecteur.
Les catégories des sprites sont characters, enemies, objects, scenery, effects, interface et misc (personnages, ennemis, objets, décor, effets, interface, divers) ; celles des niveaux platformer, maze, shooter, puzzle, arcade et misc.
Copier un sprite. Sa fiche montre son auteur, sa version, sa licence et son crédit ; Copy to my library en fait un sprite à vous, indépendant : il reste si l'original est retiré, et il s'emploie dans un modèle comme n'importe quel autre. Il garde la licence et le crédit de sa publication. Si le nom est déjà pris, la copie prend -2, -3… avant le nombre de frames (torche-2_4).
Copier un niveau. Sa fiche montre son image, son auteur, sa carte, sa version, sa licence, ses crédits, ses modèles et ses sprites. Copy to my levels crée chez vous le niveau, sa carte, les modèles de ses objets et leurs sprites : un pack indépendant, qui reste si l'original est retiré. Rien n'est écrasé : un modèle ou un sprite identique à l'un des vôtres est réutilisé, et un nom déjà pris devient niveau1_2, joueur_2 ou torche-2_4, avec les références réécrites ; le message après la copie liste ces renommages. La carte copiée compte parmi ses Sources le niveau d'où elle vient, avec le crédit de son auteur, pour que la republier le crédite. La copie n'est pas compilée : compilez-la pour l'attacher à un projet. Un niveau ou un modèle renommés gardent pour le jeu leur nom d'origine : la compilation attache niveau1_2 sous le nom niveau1, écrit niveau1.lua et garde la clé M.modeles.joueur, si bien que le code écrit pour l'original (require("niveau1")) marche sans retouche.
Games. Les jeux publiés. La fiche d'un jeu donne son auteur, ses versions, sa licence, ses crédits et sa lignée ; ▶ Play in the simulator ↗ l'ouvre dans le simulateur, Clone into my projects fait de ses sources un nouveau projet à vous, y compile ses niveaux copiés et l'ouvre. Deux niveaux sur une même carte n'en apportent qu'une copie. Le dossier Levels d'un projet montre exactement ce que le jeu joue : un niveau qui n'est pas compilé dans le projet n'est pas dans le jeu. Si un niveau du clone n'a pas pu être compilé, le message le dit : ouvrez-le et compilez-le dans le projet.
Publier un sprite. Sur sa fiche, choisissez une catégorie, ajoutez jusqu'à 8 tags (minuscules, chiffres, - et _), choisissez la licence que son origine permet, cochez la case et Publish. Votre propre sprite peut sortir en CC0 (domaine public : chacun l'emploie sans vous citer) ou en CC BY (votre pseudo est crédité) ; un sprite venu d'ailleurs garde la licence avec laquelle il est venu.
Ce qui est publié est un instantané : retoucher ou supprimer votre sprite ne change pas la version publique. La fiche signale qu'il a changé ; Publish again en fait une nouvelle version, et les copies déjà faites gardent la leur. Changer seulement la catégorie ou les tags ne crée pas de version.
Retirer. L'auteur retire sa publication à tout moment ; les administrateurs peuvent retirer un contenu qui n'a rien à faire là, ou dont le crédit est faux. Les copies déjà faites restent chez leurs propriétaires. Un sprite qu'emploie un niveau public ne se retire pas : on retire d'abord le niveau.
L'éditeur de cartes¶
Un mini Tiled : on y dessine des tuiles de 8×8 (RGBA, la tuile 0 est le trou) et on les peint sur un monde aux bornes de la console (de 80×60 à 256×128 tuiles, 704 tuiles au plus). La carte est la source des niveaux qui y sont posés, éditable à volonté. Elle s'ouvre dans un onglet du centre ; ses parties sont dans l'arbre, leurs fiches dans l'inspecteur, et les onglets Tiles et Decors du bas suivent la carte active.
| Outil | Touche | |
|---|---|---|
| pinceau | B | peint le pinceau ; Shift efface, Alt-clic prélève, Alt-tirer prend un pinceau flottant |
| seau | G | remplit la zone de tuiles identiques |
| rectangle | R | Alt : le contour seul |
| ligne | L | |
| terrain | T | peint le terrain choisi |
| sélection | S | Ctrl+C, Ctrl+X, Suppr, Ctrl+D en fait un décor |
| décor | D | pose, choisit, tire les décors posés |
X et Y retournent le pinceau (gratuit sur la console : un bit par case), Ctrl+Z et Ctrl+Y annulent et refont, la molette zoome autour du curseur, un glisser du bouton droit ou du milieu déplace la vue. Shift efface, avec tous les outils. Save (Ctrl+S) écrit la carte ; si elle a changé ailleurs depuis que vous l'avez ouverte, l'éditeur le dit et propose de la recharger. Sauver une carte dont des niveaux sont compilés les marque recompile.
Tuiles. L'onglet Tiles porte quatre barres, le 8×8 puis les tampons 16, 24 et 32 : des grilles d'ids de tuiles de base, le modèle des métatuiles. Le monde reste une grille d'ids 8×8, toute la chaîne aval ignore les tampons. Un clic prend une tuile ou un tampon comme pinceau, un double-clic l'ouvre dans l'atelier pixel. Un tampon s'y compose en peignant sa grille avec un pinceau plus petit, posé au pas de 8 px (et rogné aux bords) ; le même moteur de peinture sert le monde, où le pinceau est une tuile ou un tampon de n'importe quel côté. La peinture au pixel est réservée au 8×8, la source de vérité : retoucher une tuile de base se répercute dans tous les tampons et toute la carte. Chaque tuile porte un tag solide (un coin rouge) qui préremplit la collision.
Import tileset (_T.png, T ∈ {8, 16, 24, 32}) demande d'où vient la planche, puis la décompose en tuiles de base dédupliquées, miroirs compris (importer du 24 remplit aussi la barre 8×8), et en un tampon par tuile au-delà de 8 ; ses tuiles sont solides, décochez les exceptions. Une tuile porte une étiquette au plus : solid (coin rouge), climbable (coin bleu-vert, un barreau d'échelle) ou platform (coin ambre, une case où l'on se pose et qu'on traverse par le bas) ; cocher l'une décoche les autres. Un import qui déborderait les 704 est refusé avec le compte, avant d'écrire quoi que ce soit ; Ctrl+Z l'annule. Export grid et Import grid écrivent et relisent la carte en planche de tuiles et en texte, le format grille.
Calques. Une carte est une pile de 8 calques au plus, sous Background layers dans l'arbre : l'œil en montre ou en cache un, sa fiche le renomme, le verrouille, l'avance ou le recule, en ajoute un devant, le supprime. Le calque actif, celui qu'on a sélectionné dans l'arbre, reçoit la peinture, avec tous les outils, tampons et pinceaux de décor ; PageUp / PageDown en changent. Un calque caché ou verrouillé refuse la peinture. L'œil et le verrou ne concernent que l'éditeur : compiler aplatit tous les calques, cachés compris, du bas vers le haut, chacun suivi de ses décors posés dans leur ordre. L'onglet Budget estime les tuiles après aplatissement : une superposition nouvelle (une plante sur un mur) fait une tuile de plus sur la console, sur 704.
Collision. Le .mask est le calque de collision OU les masques des décors posés (retournés comme ils sont posés). Sélectionnez Collision layer dans l'arbre et peignez avec n'importe quel outil (Shift efface, Entrée remplit une sélection). Une case a des faces, et une face ne bloque que ce qui la franchit : la brosse de la fiche du calque propose solid (rouge, les quatre faces, # dans le .mask), platform (la face du haut seule, = : on s'y pose, on la traverse en sautant par le bas, ↓ + A la traverse), ladder (bleu-vert, H : de l'air avec des barreaux, et sa case du sommet est un sol) ou faces…, quatre cases pour n'importe quelle combinaison (a..o dans le .mask ; haut + gauche fait un mur qu'on traverse par la droite mais pas par la gauche). Un solide remplit la case de rouge, une face se dessine en trait rouge sur son côté. Les masques des décors posés s'affichent en orange et sont solides : un décor posé sur n'importe quelle autre case la rend solide dans le .mask. Une case du masque = une tuile (8×8). Décor et collision sont indépendants : une plante peut couvrir un mur sans être solide, une corniche invisible peut l'être. Fill from tagged tiles marque toutes les cases où une tuile solide, grimpable ou plateforme est posée, sur n'importe quel calque (solide gagne, puis grimpable), et la case follows tagged tiles le fait pendant la peinture ; cochée, effacer une tuile vide aussi sa case de collision, sauf si une tuile étiquetée y reste sur un autre calque. Supprimer une tuile de la barre laisse la collision telle quelle.
Terrains. Un terrain peint de la matière (outil T) : chaque case choisit sa tuile d'après ses quatre voisines du même terrain, et bords, coins et bouts viennent tout seuls. Sa fiche tient son gabarit de 16 tuiles, généré depuis deux tuiles du pinceau ou pris sur lui. Les terrains sont partagés par les calques, chaque calque garde sa matière.
Décors. L'onglet Decors tient la bibliothèque de la carte : un décor est une grille nommée de tuiles de la carte et son propre masque de collision. Import PNG demande d'où vient l'image et la fait entrer, annulable (Ctrl+Z) : elle est découpée en tuiles de base 8×8, dédupliquées contre la barre miroirs compris (une case égale à une tuile retournée la reprend avec les bits de miroir H/V de la console, qui ne coûtent rien) ; les cases entièrement transparentes sont des trous, une taille qui n'est pas multiple de 8 est complétée en transparent à droite et en bas, les nouvelles tuiles ne sont pas solides, et un import qui déborderait les 704 est refusé avec le compte. Le masque part du tag solide de ses tuiles et s'édite sur la fiche du décor (cliquer ou tirer bascule les cases). Cliquer un décor prend l'outil décor (D) : un clic le pose sur le calque actif, au pas de 8 px ; un décor posé n'est pas peint dans le calque, il reste un objet qu'on choisit, tire, duplique (Alt-tirer), retourne (X / Y), ordonne dans son calque ([ / ]) et supprime (Suppr), avec une fiche pour sa position et son calque. Les décors posés sont des références : retoucher une tuile, renommer le décor ou éditer son masque met à jour toutes les copies, et un décor encore posé ne se retire pas de la bibliothèque. Une sélection du calque actif devient un décor avec Ctrl+D (Selection → decor) : ses tuiles et sa collision quittent le calque, le décor est posé au même endroit, et rien ne bouge à l'écran ni dans le .mask (les bords d'autotiling voisins restent tels quels). F aplatit le décor choisi sur son calque : ses tuiles y sont écrites (ses trous n'effacent rien), son masque s'ajoute à la collision, et les tuiles s'éditent à nouveau. Pour peindre directement les tuiles d'un décor, gardez-le comme pinceau et prenez l'outil pinceau (B).
Sources. Ce que les imports de la carte ont apporté d'ailleurs, avec leur licence et leur crédit ; votre propre travail n'a pas besoin de source. La fiche ajoute et retire des sources, et une carte faite avant le suivi des sources s'y revoit. Les niveaux posés sur la carte se publient sous la plus stricte d'entre elles.
Une carte qu'emploient des niveaux ne se supprime pas : sa fiche les nomme.
L'éditeur de niveaux¶
Un niveau s'ouvre dans son propre onglet. Sa carte y est montrée en lecture et en direct : la carte ouverte dans son onglet, un trait pas encore sauvé se voit aussitôt dans le niveau. Dans un niveau, on n'édite que les objets ; les onglets Tiles et Decors le disent et attendent un onglet de carte.
Les objets¶
L'outil objet pose le modèle choisi au pixel, pieds sur le point cliqué ; Alt aimante à la grille de 8. Le modèle à poser se choisit sur la fiche Objects, ou en cliquant un modèle dans la bibliothèque. Cliquer un objet le choisit, tirer le déplace, Suppr le retire, Ctrl+Z et Ctrl+Y annulent et refont ; sa fiche donne sa position, visible, et des propriétés libres, une par ligne, cle=valeur, que le jeu relira dans o.props.cle. La grille et l'œil de la collision aident à placer ; l'œil d'un niveau est le sien, indépendant de celui de la carte.
Un objet non visible est compilé mais pas créé au lancement : son modèle est dans le niveau (un projectile, une réserve pour creer() en cours de jeu), instancier() le saute. Un objet resté hors de la carte après qu'elle a rétréci est signalé par l'onglet du niveau et refusé à l'enregistrement comme à la compilation : déplacez-le ou retirez-le.
L'ordre de dessin. Les objets d'un niveau se dessinent dans l'ordre d'une liste, le dernier devant, exactement comme la console peint les appels gfx.sprite(). La fiche Objects et la fiche de chaque objet montrent cette liste, le devant en haut comme les calques dans l'arbre : tirez une ligne pour réordonner, cliquez-en une pour choisir l'objet, Ctrl+Z annule. Un objet neuf se pose juste sous le joueur : le joueur reste devant tant que vous ne tirez rien au-dessus de lui, une torche de premier plan par exemple. Réordonner change les index M.objets[i] du .lua du niveau.
La fiche de l'objet porte aussi les effets des états de son modèle (alpha, contour, derrière). Ils s'enregistrent sur le modèle, valent donc pour tous les niveaux, et se jugent l'aperçu console sous les yeux.
Le joueur, et tout comportement. Ce qu'un objet fait — le joueur à sa manette, un ennemi en patrouille, une pièce qui compte — s'écrit sur son modèle, comme un comportement : un texte court, une règle par ligne, compilé dans le .lua du niveau. Sur la fiche d'un modèle, Make this the player y pose le préréglage platformer (manette, marche, saut, gravité, échelles, caméra) ; l'objet marqué P dans un niveau est celui dont le comportement est family player. Un objet peut prendre sa propre copie du comportement de son modèle depuis sa fiche. Les props du joueur (pad, speed, jump) se règlent comme toute propriété, clé=valeur sur l'objet.
Les plateformes. Une case plateforme ne bloque que des pieds qui descendent dessus : le joueur du préréglage la traverse en sautant par le bas et s'y pose. Debout dessus, ↓ + A la traverse, jusqu'au sol suivant. Le sommet d'une échelle est aussi une plateforme.
Les échelles. Le préréglage grimpe les cases grimpables de la carte. La case qui compte est celle sous le milieu de ses pieds : ↑ accroche l'échelle quand cette case est grimpable, ↓ quand la case juste dessous l'est (descendre d'un rebord, ou par le sommet d'une échelle) ; un saut qui monte n'accroche jamais. Sur l'échelle la gravité est coupée, ↑ et ↓ déplacent à la vitesse de marche, ← → font glisser le joueur et lâchent dès que les pieds quittent les cases grimpables, A saute, et relâcher ↑ et ↓ au sol ou au-dessus du dernier barreau lâche : le joueur est alors debout sur le sommet de l'échelle, qui est un sol. Deux choses à savoir en dessinant une échelle : elle doit être au moins aussi large que la boîte du joueur là où elle traverse un sol (un joueur de 16 pixels ne passe pas dans un trou d'une case : ses côtés butent sur les cases solides), et seul le sommet d'une échelle est un sol — une échelle qui traverse un plancher et continue au-dessus laisse un trou dans ce plancher. Une échelle qui part du niveau du sol se marche ; ↓ la prend. Un comportement interroge ladder_here, ladder_below, platform_below ; le jeu niveau.grimpable(x, y) et phy.cell(x, y), en pixels monde.
Compiler le niveau¶
La fiche Compile du niveau porte les rangées de palette par effet (opaques, translucides, additifs, ombres, derrière, rampe du ciel ; 255 rangées au plus, la rangée 0 est transparente), les deux couleurs du ciel (des index réservés en queue de palette, du haut vers le bas), les variantes, et les projets à cocher ; le projet ouvert est déjà coché.
Enregistrer le niveau (Ctrl+S) suffit pour tout ce qui n'est pas de l'art : cela écrit <niveau>.lua et <niveau>.mask dans chaque projet qui a le niveau, en quelques millisecondes, et dit lesquels. Les objets, leurs propriétés, leurs comportements : enregistrez, le jeu les a. Une exception : quand un modèle posé a gagné un état dont le sprite n'est pas encore dans le bundle, le .lua nommerait de l'art que le jeu ne peut pas charger, il n'est donc pas écrit ; le niveau le dit, passe en recompile, et Compile remet les deux d'accord.
Compile sert à l'art. Il enregistre la carte si elle a des modifications, puis le niveau ; aplatit tous les calques de la carte en fond, pousse les sprites des modèles placés avec l'effet de leurs états, calcule la palette, l'atlas et les pages indexées dans le navigateur, avec le moteur du simulateur, puis envoie le tout. Si la carte a été sauvée ailleurs entre-temps, la compilation est refusée et le dit : recompilez. Le résultat est le bundle du niveau, sous son nom ; et dans chaque projet coché : l'attache, <niveau>.mask et <niveau>.lua. Un .lua de ce nom écrit à la main est gardé, et Output le dit ; le .mask, lui, est réécrit à chaque compilation.
Quand rien de graphique n'a changé depuis la dernière construction (la carte, un sprite, un effet, les rangées de palette, le ciel, les variantes), Compile ne reconstruit rien : il garde l'art, écrit les deux fichiers et l'aperçu, et le dit. Compile peut donc toujours s'appuyer sans crainte.
Output montre le fond tel que la console le recomposera (tuiles regroupées comprises), les images, le nombre de sprites, d'index, le pool, ce que chaque projet a reçu, et la durée de chaque étape (save, build, preview, upload, reload).
L'aperçu console¶
Console preview, dans la barre d'outils du niveau ou sur sa fiche Compile, recompose la fenêtre visible du monde par le moteur du simulateur : le vrai fond tuilé, le ciel, les objets visibles animés, à travers la table de mélange de la console. Changer un effet, les rangées ou le ciel le recalcule ; un effet changé s'écrit dans le modèle. C'est là qu'on juge un « derrière le fond » ou un contour.
Publier un niveau¶
La fiche du niveau a une section Public levels ; le niveau doit être ouvert, puisque son aperçu est dessiné par l'éditeur. Elle demande une catégorie, jusqu'à 8 tags, la licence (CC BY dès que les sources de sa carte, ses sprites ou sa propre origine l'exigent, sinon CC0 ou CC BY), la case à cocher, et une catégorie pour chaque sprite jamais publié ; elle liste les crédits que le niveau porte. Tout part ensemble : le niveau, sa carte (tuiles, calques, décors, collision, sources), les modèles qu'il place et leurs sprites. Un niveau sans objet partage juste sa carte. Les sprites encore privés sont publiés aussi dans la bibliothèque publique d'assets, chacun avec sa catégorie ; un sprite copié d'un asset public et resté identique ne l'est pas, l'original suffit. Publier enregistre d'abord la carte et le niveau. Un niveau dont un objet place un modèle disparu, dont un modèle emploie un sprite disparu, ou où quelque chose n'est pas déclaré, ne se publie pas.
Ce qui est publié est un instantané : la fiche signale quand le niveau a changé depuis, et Publish again crée une nouvelle version ; changer seulement la catégorie ou les tags n'en crée pas. L'auteur retire son niveau à tout moment, les administrateurs aussi, sauf si un jeu publié l'emploie : un jeu publié ne se copie jamais sans ses sources, on retire donc d'abord le jeu. Ses sprites restent dans la bibliothèque publique d'assets et les copies déjà faites chez leurs propriétaires.
Le fichier <niveau>.lua¶
Généré par la compilation, jamais à éditer. Il s'ouvre sur un mode d'emploi en commentaire, écrit avec les noms de ce niveau : comment le charger, ce que rend instancier(), les modèles qu'il pose et leurs états, leurs comportements et leurs familles, et les gestes courants (lire une propriété, lire le pot, changer une animation, créer un acteur en jeu). Il requiert papyrun.lua, le runtime des comportements écrit dans le projet avec lui (en lecture seule aussi). Puis il porte les dimensions (M.largeur, M.hauteur en tuiles, M.px_largeur, M.px_hauteur en pixels), le fond (M.fond), la gravité du niveau (M.gravite, en 1/256 px/trame²), les modèles posés (M.modeles, avec anim, cadence, boucle par état — les modèles qu'un comportement invoque compris), les objets (M.objets, avec props, et script quand l'objet a son propre comportement), les comportements compilés (M.comportements, un par modèle et par objet qui a le sien : drapeaux, couche, masque de contact, premier état, les règles en fonctions), et six fonctions :
M.charger():gfx.background,phy.map,phy.gravity, et les animations chargées une fois (M.anims[modele][etat]) ; rend la taille en pixels.M.grimpable(x, y): vrai quand le pixel monde est sur une case grimpable (une échelle) :phy.cell(x, y) & phy.LADDER.M.creer(modele, x, y): un acteur du modèle, boîte, ancre, position, état par défaut ; rend l'acteur.M.instancier(fabriques): les objets visibles, par modèle, leurs comportements démarrés :objs.torche[1].aest l'acteur,.ol'objet (avec.props),.animsses animations,.etatl'état de son comportement.fabriques[modele](o, x, y), si donnée, remplaceM.creerpour ce modèle.M.acteursgarde chaque record dans l'ordre de dessin.M.update(), depuis_update(): une trame de tous les comportements — chaque objet lit sa manette et ce que le dernierphy.step()a produit, tire ses règles — puisphy.step()et les contacts.M.joueur_updateest son ancien nom, gardé. N'appelez pasphy.step()vous-même en plus.M.dessiner(), depuis_draw(): tous les objets en coordonnées écran (monde moins caméra), dans l'ordre de dessin du niveau, en miroir vers la gauche ; la caméra suit l'objet dont le comportement ditcamera follow.M.decharger(): libère les animations du niveau (phy.anim_free). La console en tient 64 à la fois : un jeu à plusieurs niveaux appelleancien.decharger()avantnouveau.charger(); les acteurs de l'ancien partent avec lui (lephy.mapdu nouveau les efface).
Tout un niveau jouable, dans un main.lua écrit à la main (la fiche Game en écrit un plus complet) :
gfx.bundle()
local niveau = require("niveau2")
niveau.charger()
local objs = niveau.instancier()
function _update() niveau.update() end
function _draw() niveau.dessiner() end
Les comportements partagent la table globale pot : main.lua la lit (pot.exit, pot.score) pour passer d'un niveau au suivant, et niveau.acteurs[i].etat dit où en est chaque objet. Rien dans le fichier n'est tiré au sort (les phases d'animation sont l'affaire du jeu, voir phy.anim).
Le fond¶
Le fond d'un niveau, c'est le monde de sa carte. Il est quantifié avec les sprites (une seule palette, c'est toute la raison de sa présence) puis tuilé : tuiles 8×8 distinctes par fréquence décroissante, la tuile 0 = le trou, 704 au plus ; au-delà, regroupement par similarité (k-moyennes en couleur, moyenne de groupe reprojetée sur les index employés) : une image continue devient une mosaïque douce au lieu d'un remplacement brutal, et la perte est comptée. Hors atlas, hors pool.
Il sort en deux pièces, <niveau>-fond.map et <niveau>-fond-tiles.png, parce que gfx.bundle() rattache un fond à son groupe par ce préfixe. M.charger() écrit gfx.background("<niveau>-fond").
Les variantes¶
Une variante, <niveau>.<variante>.pal, c'est les mêmes index, d'autres couleurs : jour/nuit, flash ; aucune image, et gfx.palette("<niveau>.<nom>") bascule en temps réel.
Une variante se définit sur la fiche Compile par ses réglages (teinte, saturation, luminosité appliqués à la palette du niveau) et le .pal dérivé ; l'atelier redérive les couleurs à chaque compilation, donc une recompilation ne désynchronise jamais ses variantes. Les modes de mélange restent ceux du niveau : une variante ne change jamais les rangées, c'est sa définition, et l'App le refuse. Chaque variante compte une palette dans les 12 du projet.