[#_lesson_1_hello] == Leçon 1 : Bonjour image::learn/01-hello.png[La leçon terminée, 480] Voilà ce que vous aurez à la fin de cette leçon. Ça ne paie pas de mine. C'est aussi un programme que vous avez écrit, qui tourne sur un vrai moteur de jeu, et tout le reste de ce livre repose sur les cinq lignes qui l'ont produit. [#_set_up_your_work_folder] === Préparez votre dossier de travail Créez un dossier pour tout y ranger, appelé `singe` ou comme il vous plaira, et mettez-y votre copie de Singe. C'est votre *dossier de travail*, et chaque leçon de ce livre y ajoute un nouveau dossier. Vous le créerez une fois et n'y penserez plus jamais. Dans le dossier de travail, créez un dossier appelé `hello`, et dans celui-ci un fichier appelé `hello.singe`. [literal] ---- singe/ <- votre dossier de travail, avec Singe dedans hello/ hello.singe ---- Cette imbrication n'est pas une lubie. Singe considère le dossier depuis lequel vous le lancez comme l'endroit où vivent les jeux, un dossier par jeu, et il y range aussi ses propres fichiers. Votre jeu va dans son propre dossier, un niveau plus bas. À partir de la leçon deux, chaque leçon est un autre dossier à côté de `hello`. Deux choses à propos des noms. La partie après le point, `.singe`, est ce qui indique à Singe qu'il s'agit d'un script. Et sur la plupart des ordinateurs qui ne sont pas sous Windows, les majuscules comptent : `Hello.singe` et `hello.singe` sont deux fichiers différents. Prenez dès maintenant l'habitude de taper les noms exactement. Donner le même nom au dossier et au script compte aussi, et vous allez voir pourquoi dans un instant. Ouvrez `hello.singe` dans votre éditeur de texte. Il est vide. C'est bien comme ça. [#_type_this_in] === Tapez ceci [source,lua] ---- function onOverlayUpdate() overlayClear() overlayPrint(2, 2, "Hello!") return OVERLAY_UPDATED end ---- Enregistrez-le. Ne vous souciez pas encore de ce que tout cela veut dire. Deux choses méritent d'être remarquées avant de le lancer, parce qu'elles seront vraies de chaque programme que vous écrirez. La première, c'est que les espaces au début des trois lignes du milieu sont là exprès. Ils ne changent rien du tout au programme -- Singe le lancerait exactement pareil sans eux -- mais ils vous montrent d'un coup d'œil que ces trois lignes sont *à l'intérieur* de ce qui commence par `function` et finit par `end`. Tous les programmeurs font ça. Faites-le dès le premier jour et vous n'aurez jamais à l'apprendre plus tard. La seconde, c'est l'ordre des lignes. Elles s'exécutent de haut en bas, l'une après l'autre, comme les étapes d'une recette. C'est la chose la plus importante à savoir sur un programme, et presque tout ce qui embrouille un débutant vient de ce qu'il l'oublie. [#_run_it] === Lancez-le Ouvrez un terminal, allez dans votre *dossier de travail* -- pas dans le dossier `hello` qu'il contient -- et donnez le nom du dossier que vous voulez lancer : ---- Singe hello ---- Sous Windows, c'est `Singe.exe hello`. Si votre copie de Singe se trouve ailleurs, tapez le chemin qui y mène, par exemple `../Singe hello`. Voilà pourquoi le dossier et le script portent le même nom. Quand on lui donne un dossier, Singe y cherche un script qui s'appelle pareil. Nommez-les différemment et vous obtenez `Error: Unable to locate the game.`, c'est-à-dire le moteur qui vous dit qu'il a cherché et n'a rien trouvé qu'il reconnaisse. Vous pouvez toujours être explicite à la place et écrire `Singe hello/hello.singe`, qui fait la même chose. Une fenêtre noire s'ouvre avec le mot `Hello!` près du coin supérieur gauche. Appuyez sur *Échap* ou *Q* pour quitter. Deux choses se seront produites sans que vous les ayez demandées, et elles sont toutes les deux normales. Des dossiers appelés `Singe` et `data` sont apparus dans votre dossier de travail, à côté de `hello` : le premier, c'est le moteur qui extrait les fichiers dont il a besoin, le second, c'est là qu'ira tout ce que vos jeux sauvegardent. Laissez-les tous les deux tranquilles. Et la fenêtre est presque entièrement noire, parce que vous n'avez rien dessiné à part six caractères. [#_what_just_happened] === Ce qui vient de se passer Maintenant, les cinq lignes, une par une. [source,lua] ---- function onOverlayUpdate() ---- `function` commence un groupe d'instructions et lui donne un nom. Tout ce qui se trouve d'ici jusqu'au `end` correspondant en fait partie. Cette fonction s'appelle `onOverlayUpdate`, et les parenthèses vides après le nom prendront leur sens à la leçon cinq. Ce nom, ce n'est pas à vous de le choisir. Singe cherche une fonction qui porte exactement ce nom et l'appelle une soixantaine de fois par seconde, sans fin, pour vous donner l'occasion de dessiner. Si vous l'écrivez `onoverlayupdate` ou `onOverlayUpdated`, Singe ne la trouvera pas, votre fenêtre restera noire, et rien ne vous dira que vous vous êtes trompé. C'est la première vraie leçon : l'ordinateur fait ce que vous avez écrit, pas ce que vous vouliez dire. Une fonction que vous écrivez et que le moteur appelle est un *callback* (une fonction de rappel). Vous ne l'appelez pas vous-même, et vous ne pouvez pas dire quand elle s'exécute ; vous l'écrivez, et Singe vous rappelle quand il y a quelque chose à faire. Chaque nom de ce livre qui commence par `on` est un callback, et il y en a un pour presque tout ce qui peut arriver : un bouton enfoncé, une touche tapée, un son qui se termine, le disque qui atteint une image. `onOverlayUpdate` est celui du dessin, et c'est le seul endroit où dessiner est permis. [source,lua] ---- overlayClear() ---- C'est aussi une fonction, mais pas une que vous devez écrire : Singe la fournit, avec plusieurs centaines d'autres, et vous êtes en train de *l'appeler*. Appeler une fonction, c'est dire son nom suivi de parenthèses. Celle-ci efface l'écran. Elle vient en premier parce que dessiner ne remplace pas ce qui était là avant, ça dessine par-dessus. Effacer, puis dessiner, à chaque fois. [source,lua] ---- overlayPrint(2, 2, "Hello!") ---- Un autre appel, et celui-ci a besoin qu'on lui dise trois choses, qui vont entre les parenthèses, séparées par des virgules. Les choses que vous passez ainsi à une fonction s'appellent des *arguments*. Les deux premières sont des nombres : à quelle distance vers la droite et à quelle distance vers le bas. La troisième est le texte à afficher, et il est entre guillemets doubles parce que c'est ainsi qu'on indique à l'ordinateur que `Hello!` est un morceau de texte et non le nom de quelque chose. Un texte entre guillemets s'appelle une *chaîne* (de caractères), et vous vous servirez de chaînes sans arrêt. Tôt ou tard, vous voudrez mettre un guillemet double à l'intérieur d'une chaîne, et la manière évidente ne marche pas : le deuxième guillemet termine la chaîne trop tôt, et vous obtenez la même erreur `unfinished string` que celle que vous rencontrerez à la fin de cette leçon. Il y a deux façons de la contourner, et elles valent toutes les deux d'être connues. [source,lua] ---- overlayPrint(2, 2, "She said \"hello\" to me.") overlayPrint(2, 4, 'She said "hello" to me.') ---- La première met une barre oblique inverse devant chaque guillemet qui fait partie du texte. La barre oblique inverse dit « le caractère suivant fait partie de la chaîne, ce n'est pas sa fin », et la paire s'appelle une *séquence d'échappement*. La seconde utilise des guillemets simples pour marquer les bouts de la chaîne, ce qui laisse les guillemets doubles libres d'être du texte ordinaire. Lua accepte les deux sortes de guillemets, du moment que la chaîne finit par la même sorte que celle par laquelle elle a commencé. Ces deux lignes affichent exactement la même chose. Utilisez celle qui se lit le plus facilement, et c'est en général celle aux guillemets simples quand le texte est plein de guillemets doubles. Les deux nombres ne sont pas des pixels. `overlayPrint` est le texte simple propre au moteur, et il compte en cellules de caractère : `(0, 0)` est le coin tout en haut à gauche, `(1, 0)` est une lettre plus à droite, et `(0, 1)` une ligne plus bas. Donc `(2, 2)`, c'est deux lettres vers la droite et deux lignes vers le bas. D'autres manières de dessiner du texte comptent bien en pixels, et vous les rencontrerez à la leçon dix-neuf. [source,lua] ---- return OVERLAY_UPDATED ---- `return` renvoie une réponse à celui qui a appelé la fonction. Singe pose une seule question à votre `onOverlayUpdate` chaque fois qu'il l'appelle : avez-vous changé quelque chose ? `OVERLAY_UPDATED` veut dire oui, il faut donc l'afficher. `OVERLAY_UPDATED` n'a pas de guillemets autour parce que ce n'est pas du texte. C'est un nom que Singe a déjà donné à une valeur, pour que vous puissiez écrire quelque chose que vous savez lire au lieu d'un nombre qu'il vous faudrait retenir. [source,lua] ---- end ---- La fin qui va avec le `function`. Chaque `function` en a exactement une, et l'oublier est l'erreur la plus courante qui soit. [#_try_it] === Essayez Changez une chose à la fois, enregistrez, et relancez. Cette boucle -- changer, lancer, regarder -- c'est tout le métier. . *Déplacez le texte.* Changez `overlayPrint(2, 2, "Hello!")` en `overlayPrint(10, 5, "Hello!")`. Puis essayez `(0, 0)`. Puis essayez `(200, 2)`, et trouvez pourquoi il a disparu. . *Dites autre chose.* Mettez votre propre nom entre les guillemets. . *Dites deux choses.* Ajoutez une deuxième ligne `overlayPrint` sous la première, avec un autre numéro de ligne et un autre texte. Rien ne vous empêche d'en avoir autant que vous voulez. . *Retirez l'effacement.* Supprimez la ligne `overlayClear()` et lancez. Rien ne change, parce que rien ne bouge encore sur votre écran. Remettez-la quand même. À la leçon deux, elle comptera énormément, et c'est le bon moment pour voir que certaines erreurs attendent avant de mordre. [#_break_it_on_purpose] === Cassez-le exprès Les débutants passent plus de temps à lire des messages d'erreur que des livres de programmation, alors débarrassons-nous du premier tout de suite. Supprimez le guillemet fermant après `Hello!`, pour que la ligne devienne `overlayPrint(2, 2, "Hello!)`, et lancez. Singe refuse de démarrer et dit : ---- Error running script: hello/hello.singe:3: unfinished string near '"Hello!)' ---- Lisez-le à partir de la gauche. `hello/hello.singe`, c'est le fichier : le dossier, puis le script qu'il contient. `3`, c'est la ligne. Le reste, c'est ce qui n'a pas marché, ici un morceau de texte qui a été ouvert et jamais fermé. Allez à la ligne trois, remettez le guillemet, et ça tourne. Presque toutes les erreurs que vous verrez ont cette forme : un fichier, une ligne et une plainte. La plainte est parfois écrite pour quelqu'un qui connaît déjà Lua, mais le fichier et la ligne sont toujours justes, et neuf fois sur dix la ligne suffit. [#_stop_restarting_it] === Arrêtez de le relancer Vous avez maintenant démarré Singe à la main cinq ou six fois. Arrêtez. Lancez-le plutôt comme ceci : ---- Singe -R hello ---- `-R` dit à Singe de surveiller votre script. Enregistrez une modification dans votre éditeur, et le jeu redémarre de lui-même un instant plus tard avec votre modification, sans fermer la fenêtre. Si vous enregistrez une erreur, l'erreur est affichée et la fenêtre reste vide jusqu'à ce que vous enregistriez une correction. Utilisez `-R` pour tout le reste de ce livre. [#_what_you_learned] === Ce que vous avez appris * Un programme est un fichier d'instructions qui s'exécutent dans l'ordre, de haut en bas. * Une `function` regroupe des instructions sous un nom et s'arrête à son `end`. * `onOverlayUpdate` est un nom que Singe cherche et appelle de nombreuses fois par seconde, et c'est là que va tout votre dessin. * Appeler une fonction, c'est écrire son nom et des parenthèses. Tout ce qui est entre les parenthèses est un argument. * Une fonction que le moteur appelle pour vous, plutôt qu'une que vous appelez vous-même, est un callback. `onOverlayUpdate` en est un. * Un texte entre guillemets doubles est une chaîne. * Effacez l'écran avant de dessiner dessus. * Une erreur vous donne le fichier et la ligne. Commencez par là. [#_next_time] === La prochaine fois Votre `Hello!` reste là où vous l'avez mis et ne bouge jamais. Pour le faire bouger, il vous faut un endroit où garder un nombre qui change -- une *variable* -- et c'est tout le sujet de la leçon deux.