Solarus Wiki

A wiki for the Solarus engine community

Outils pour utilisateurs

Outils du site


fr:tutorial:the_first_map

Chap. 1Chap. 3Sommaire

Chapitre 2 - Votre première map

Le jeu se lance, il charge bien la quête mais vous n'êtes que sur un écran titre, car votre quête est presque vide. Dans ce tutoriel, nous allons voir comment créer une map et lancer le jeu sur cette map. Nous allons beaucoup utiliser l'éditeur de quête car sa principale utilité est la création de maps.

Récupérer les ressources minimales

Vous allez devoir récupérer tout d'abord les ressources minimales nécessaires au fonctionnement du moteur. Vous pourriez créer complètement ces ressources, mais ce que l'on veut ici c'est démarrer rapidement un jeu. Nous vous fournissons donc des ressources, elles permettent de faire un jeu semblable à Zelda: A Link to the Past. Détaillons un peu ce que contiennent ces ressources.

Tiles

Tout d'abord, expliquons ce qu'est un tile, en français une tuile : ce sont des éléments de décors basiques, qui possèdent certaines propriétés (est-ce un mur ? est-ce animé ?). Une map est composée d'une multitude de tiles. En résumé, chaque fois que vous voyez un élément de décor, c'est un tile. Et ces tiles peuvent se mettre sur plusieurs “niveaux” dans la map (couche basse, intermédiaire et haute ; dans le logiciel en anglais ce sont donc les low, intermediate et high layer). Nous reviendrons sur les couches dans un prochain chapitre.

L'éditeur de quêtes permet le découpage d'un tileset, un tileset étant un ensemble de plusieurs tiles faisant partie d'un même skin, par exemple le skin d'une maison ou d'un donjon particulier. Créer un tileset est un exercice facile mais long et un peu fastidieux. Là encore, nous aborderons cela dans un prochain chapitre. Pour l'instant, vous pouvez télécharger le tileset dont nous aurons besoin ici. Désarchivez ce fichier et mettez son contenu sous data\tilesets.

Sprites

Les tiles ne sont pas les seules entités présentes sur une map. En effet, il y a aussi les ennemis, les portes, les coffres, les personnages non joueurs, les buissons, les téléporteurs, etc. Ces entités de la map peuvent pour la plupart être représentées par des sprites. Un sprite est une animation construite par une succession d'images fixes. Par exemple, lorsque le héros marche, il s'agit d'une succession d'images fixes, l'animation n'est pas “réelle”. Un peu comme un gif animé : ce sont des images qui, mises bout à bout, donnent l'illusion d'une animation. Notez que tous les sprites ne sont pas forcément animés, il y a des sprites composées d'une seule image (par exemple l'herbe).

Le moteur Solarus a besoin de deux fichiers pour définir un sprite : une fichier .png content l'ensemble des images qui composent l'animation, et un fichier .dat qui indique où se trouve chaque image composant l'animation dans le fichier .png et quel est le délai entre chaque image. Un même fichier .png peut contenir les images de plusieurs sprites, comme par exemple pour le bouclier qui a ses trois évolutions possibles dans la même image .png. L'inverse peut aussi être vrai : pour des sprites ayant de nombreuses animations différentes, les animations peuvent être séparées en plusieurs fichiers .png.

A l'heure actuelle, l'éditeur de quêtes ne permet pas de modifier des sprites facilement : il est nécessaire de modifier à la main les fichiers .dat de vos sprites. Comme cette opération est fastidieuse et que ce chapitre n'est pas consacré aux sprites, nous vous conseillons de télécharger les ressources minimales nécessaires au moteur ici. Désarchivez ce fichier et faites correspondre les sous-répertoires du dossier data. Remplacez tous les fichiers demandés, il ne sera fait aucun mal à vos fichiers tilesets (si toutefois ils ont disparu, remettez-les).

Musique et son

L'archive contient notamment la musique de Game Over, imposée par le moteur dans la version 1.0 car le menu de game-over est codé en dur. (Avec la version 1.1, le menu de game-over sera entièrement personnalisé.) Les musiques peuvent être au format SPC (déconseillé), au format IT (conseillé) ou au format OGG. Les deux premiers formats sont des formats très spécifiques aux jeux, consultez les liens Wikipedia pour en savoir plus. Le dernier format est très simple d'utilisation mais ne permet pas des boucles avancées ou complexes : il va juste boucler sur toute la musique (intro comprise s'il yen a une). Des convertisseurs vers OGG sont faciles à trouver, alors que SPC et IT nécessitent des logiciels spécifiques.

Le moteur requiert également la présence d'un certain nombre de fichiers de sons. Ils sont également dans l'archive.

Construire sa map

Créer le tileset

Dans l'éditeur de quête, nous allons faire un clic droit sur le dossier Tileset et faire New tileset. En effet, nous avons téléchargé les tilesets du monde de la lumière (light_world), mais le moteur et l'éditeur ne savent pas encore qu'ils existent, car il faut les indiquer dans la liste des ressources. La première boîte de dialogue vous demande l'id du tileset. Comme indiqué sur le screen, mettez “light_world”. Vous l'aurez remarqué, l'id est le nom des fichiers de tileset sans extension. Il faut donc que les noms des fichiers et de l'id concordent. Les fichiers étant light_world.dat, light_world.entities.png et light_world.tiles.png, le tronc commun à ces trois fichiers est light_world. Ceci est donc l'id tout indiqué.

La seconde boîte de dialogue vous demande un nom “user-friendly”. C'est un nom plus facile à retenir pour un utilisateur final. C'est le nom qui apparaîtra dans toutes vos options d'utilisations de ce tileset dans l'éditeur, l'id n'étant que le nom du fichier. Toutes les ressources de l'arbre à gauche de l'éditeur de quête fonctionnent sur ce principe : vous verrez juste après qu'en faisant une nouvelle map, il vous demandera l'id et le nom user-friendly. Mettez ce que vous voulez comme nom user-friendly pour ce tileset, nous nous y référerons à l'avenir en tant que “Monde Extérieur”.

Si vous double-cliquez sur le tileset nouvellement créé, vous verrez comment est agencé tout le tileset : il est composé d'une multitude d'éléments, parfois minuscules (le plus petit est de 8*8 pixels), tantôt énormes. En faisant un clic-droit sur un des éléments, vous verrez ses propriétés de terrain (ground) avec leur description.

Créer sa première map

Maintenant que le tileset est renseigné, vous pouvez créer une map. Comme pour le tileset, faites un clic droit sur Map et faites New Map. L'id cette fois-ci, c'est vous qui le décidez, le fichier créé aura ce nom-là avec une extension .dat. Mettez ce que vous voulez, par exemple “test_map”. Il est conseillé de faire des noms de fichiers sans accents et sans espaces pour permettre à votre jeu de fonctionner sur n'importe quel système de fichiers. Le nom de la map est demandé dans la seconde boîte de dialogue, comme pour le tileset, vous pouvez mettre ce que vous voulez, ici ce sera “Map de test”. Notez que, comme pour les tilesets, vous pouvez “renseigner” une map déjà existante. Votre map existante sera bien détectée.

Par défaut, les maps font une taille 320×240 pixels, ne possèdent pas de tileset et sont entièrement vides. Nous allons voir comment se découpe l'interface et à quoi sert chaque élément.

Explication de l'interface

Interface

  1. Map id : Identifiant de la map, comme nous l'avons mis dans la première boîte de dialogue, il s'agit du nom du fichier sans extension.
  2. Map name : Nom visible dans l'éditeur de quête, que vous avez indiqué dans la seconde boîte de dialogue à la création de la map. Il peut être changé ici facilement.
  3. Size : la taille de la map. Par défaut, elle fait 320×240, mais vous pouvez l'agrandir ou la réduire à volonté. Vous ne pouvez la modifier que de 8 en 8 pixels, c'est à dire qu'une taille de 324 n'est pas valable, c'est 328 ou 320.
  4. World : obligatoire en version 1.0, optionnel dans une future version, il permet de “lier” plusieurs maps ensemble. Par exemple, lorsque vous faites un donjon composé de plusieurs étages, si vous mettez les maps de tous vos étages dans le même world (par exemple “donjon_1”), alors en sauvegardant dans ce donjon, la partie recommencera à l'entrée du donjon et non au dernier étage que vous avez visité. Nous verrons cela dans un futur tutoriel.
  5. Location in its world : Permet de définir la position de la map par rapport à ses voisines s'il y en a. C'est utilisé dans le cas d'une map de monde extérieure composé de plusieurs morceaux : mettons un monde composé de 3×3 cases, toutes faisant 800×800 pixels (plus simple pour les calculs de l'exemple). La troisième map de la première ligne aura une position de 0,1600 (dans sa globalité, elle sera à ces coordonnées). La seconde map de la deuxième ligne sera aux coordonnés 800,800 et celle juste en dessous sera en 1600,800. La dernière du carré sera en 1600,1600. Vous l'aurez compris, c'est la somme des tailles des maps au-dessus et à gauche de la map actuelle. Si vous créez une mini-map dans votre menu de pause, vous aurez besoin de cette information pour afficher la position correcte du joueur sur la carte du monde.
  6. Tileset : le tileset (skin) qu'utilise la map.
  7. Music : La musique qui sera jouée sur cette map. Si vous laissez “<same as before>”, il n'y aura pas de changement de musique au démarrage de la map, et la musique précédente continuera sans coupure à être jouée. De même, si vous mettez une musique particulière et que cette musique était déjà jouée dans la map précédente, elle se poursuivra sans coupure.
  8. Zoom : permet de zoomer sur la carte, très utile pour avoir une vue d'ensemble (zoom minimal) ou gérer des cas particuliers précis (zoom maximal).
  9. Affichages généraux de la map : les couches à afficher ou non, la transparence et la grille d'aide au placement.
  10. La map elle-même, sur laquelle vous placerez les éléments.
  11. Bouton de création rapide d'entités de map. De gauche à droite dans la version 1.0 : destination, téléporteur, objet ramassable, destructible (herbe), destructible (buisson), destructible (jarre), destructible (pot), coffre, jumper, ennemi, PNJ généralisé, PNJ classique, bloc, interrupteur, mur, senseur, interrupteur de cristal, bloc de cristal (orange), bloc de cristal (bleu), objet achetable, tapis roulant, porte, escalier inter-étage, escalier intra-étage. Vous remarquerez la redondance de certains types d'entités : à partir de la la version 1.1, par souci de simplification il n'y a plus qu'une icône par type d'entité. Le sous-type peut de toute manière être facilement changé ensuite dans les propriétés de l'entité (nous verrons cela). La version 1.1 contient donc : destination, téléportateur, objet ramassable, destructible, coffre, jumper, ennemi, PNJ, bloc, interrupteur, mur, senseur, interrupteur de cristal, bloc de cristal, objet achetable, porte, escalier et une nouveauté de la 1.1 : les séparateurs. Dans tous les cas, ces éléments sont expliqués dans la documentation si vous voulez en savoir plus sur leurs utilisations respectives. Les prochains chapitres de ce tutoriel vous expliqueront progressivement l'utilisation de chaque type d'entité avec de nombreux exemples.
  12. Affichages spécifiques de la map : si vous voulez afficher certains types d'entités ou pas, ces types d'entités étant exactement ceux énumérés dans le point précédent. Notez qu'il y a en plus “tiles” (les tuiles basiques statiques), et dynamic tiles qui sont des tuiles spéciales que nous ne verrons pas de suite (ce sont des tuiles que l'on peut programmer, par exemple les trous qui apparaissent quand un certain évènement se produit).

Avec toutes ces informations, vous devez vous douter de ce qu'il vous reste à faire en tout premier : définir quel tileset vous voulez utiliser pour cette map. Vu que nous n'avons pas beaucoup de choix pour l'instant, prenez le tileset “Monde Extérieur”. N'oubliez pas aussi d'indiquer un world, ici nous pouvons mettre “outside” par exemple. Une fois cela fait, vous pouvez ajouter les tiles que vous voulez sur la map, pour cela il vous suffit de cliquer sur le tile que vous voulez, et de le placer où vous voulez en recliquant une fois à l'endroit désiré sur la map. Voici quelques astuces :

  • Un clic droit pour placer la tile permet de garder cette tile sélectionnée, afin d'en placer plusieurs à la suite. Le clic gauche déselectionne la tile une fois celle-ci positionnée.
  • Un clic maintenu (droit ou gauche selon le comportement que vous souhaitez) permet d'étendre le tile horizontalement et/ou verticalement en répétant son motif. Si parfois cela donne un effet bizarre, cela est très utile pour faire de longues rangées d'arbres ou des falaises par exemple.
  • Une fois une tile placée, si vous voulez la redimensionner, sélectionnez-la et utilisez la touche “R” (pour Resize) de votre clavier : la taille se redimensionnera directement de son vers votre souris. Très pratique.
  • Une fois une tile placée, si vous voulez la ramener au-dessus des autres tiles qui la chevauchent, appuyez sur “T” (pour Top). Si au contraire vous voulez la mettre tout en bas, appuyez sur B (pour Bottom).
  • Vous pouvez faire de la sélection multiple en restant appuyé sur le bouton gauche souris sans élément sélectionné au départ.
  • Vous pouvez utiliser les touches Ctrl ou Maj pour sélectionner (ou déselectionner) un à un plusieurs éléments.
  • Le copier-coller d'élément est supporté: Ctrl+X, Ctrl+C, Ctrl+V.
  • Pour ne plus poser d'élément, cliquez sur un endroit vide du tileset.

Avec ces astuces, vous avez de quoi placer quelques petits arbres pour vous faire la main, comme ceux-là :

Petits arbres

Une dernière chose avant d'entamer la partie suivante : mettez une destination (la premier icône dans la barre d'outil de création d'entités) sur la map. Les destinations servent à indiquer au moteur où il doit envoyer le héros lors d'une téléportation mais aussi au démarrage du jeu. Le système de destination permet d'être plus flexible que d'indiquer des coordonnées, car il évite de devoir retoucher des coordonnées lorsque vous déplacez vos décors. La contrepartie, c'est que le nom de la destination ne doit pas changer, sinon quelqu'un qui a une sauvegarde sur l'ancien nom de cette destination ne pourra plus démarrer correctement la partie, soyez-en conscient quand vous renommez des maps ou des destinations !

Une fois la destination mise, double-cliquez dessus ou appuyez sur la touche Entrée pour afficher ses propriétés. Saisissez un identifiant dans “Name”, par exemple “start”, puis faites OK. Maintenant, nous avons une belle map. Exemple de ce que vous pouvez faire :

Mais si on lance le jeu maintenant, nous restons sur notre écran titre, car nous n'avons pas lancé de partie. Nous allons donc faire un peu (très peu) de programmation.

Programmer le lancement de la partie

Rappel du tutoriel précédent : dans main.lua, vous aviez deux fonctions mises par défaut par le moteur. Vous pouvez les supprimer désormais car elles ne nous servent pas (voici le contenu à effacer, ligne 4 à 16) :

-- Below is just an example of quest that does almost nothing.
-- Feel free to change this!
function sol.main.on_started()
  -- This function is called when Solarus starts.
  print("Welcome to my quest.")
end
 
function sol.main.on_finished()
  -- This function is called when Solarus stops or is reset.
  print("See you!")
end

Ce que nous allons faire ici à la place, c'est que lorsque la touche Espace est appuyée, nous lancerons la partie. Voici le code correspondant :

function sol.main:on_key_pressed(key)
  -- We want to start the game if space is pressed.
  if key == "space" then
    -- Load or create the game from file save1.dat.
    local game = sol.game.load("save1.dat")
    -- Not necessary in solarus 1.1: set the hero's location when the game starts.
    game:set_starting_location("test_map", "start")
 
    -- Start the game.
    game:start()
  end
end

Voici l'usuel décryptage de cette fonction, bien qu'elle soit correctement commentée. Première ligne : c'est la fonction appelée par le moteur lorsqu'une touche du clavier est appuyée, avec en paramètre le nom de la touche (pour la touche Espace, le nom est space). Donc, on vérifie que le nom de la touche est bien space, si c'est le cas on crée la partie. La fonction sol.game.load permet d'initialiser ou de charger une sauvegarde. Comprenez que si le fichier que vous indiquez n'existe pas, le moteur crée une nouvelle partie. La ligne juste après n'est nécessaire qu'avec Solarus 1.0, car il ne devine pas dans quelle map et à quelle destination lancer la partie. Dans Solarus 1.1, la map par défaut est la première map de la liste des maps, et dans chaque map, on peut préciser une destination par défaut. Ici, la fonction game:set_starting_location prend deux paramètres : l'id de la map (donc “test_map”) et la destination dans cette map (la seule que l'on ait créée, “start”). Une fois ces formalités accomplies, on demande de lancer le jeu via game:start.

Si vous essayez de lancer le jeu en appuyant sur la barre espace, vous allez avoir une déconvenue. En effet, la fonction on_draw de sol.main est toujours appelée par le moteur, constamment, et donc l'écran-titre ne disparaît pas ! Pour remédier à cela, nous allons modifier légèrement le code que nous avions écrit lors du tutoriel précédent. Nous allons en effet mettre la variable game de ce fichier au même niveau que la variable title_img, et nous allons afficher l'écran-titre uniquement lorsque cette variable est vide. Voici le contenu du fichier après ces modifications :

-- This is the main Lua script of your project.
-- You will probably make a title screen and then start a game.
-- See the Lua API! http://www.solarus-games.org/solarus/documentation/
 
local game  -- Variable containing the game
local title_img = sol.surface.create("title_img.png")
 
-- Draw the title screen only if there is no game set.
function sol.main:on_draw(screen)
    if game == nil then
      -- Draw the title_img on the center of the screen
      title_img:draw(screen, (320-120)/2, (240-120)/2)
    end
end
 
-- Function to load the game when Space is pressed.
function sol.main:on_key_pressed(key)
  if key == "space" then
    -- Set the variable game (declared above).
    game = sol.game.load("save1.dat")
    -- Not necessary in solarus 1.1: set the hero's location when the game starts.
    game:set_starting_location("test_map", "start")
 
    -- Start the game.
    game:start()
  end
end

Informations sur ce qu'on vient de faire : nous avons rajouté juste un if dans la fonction d'affichage de l'écran-titre, dans ce if il y a le mot clé nil, qui signifie une valeur vide. Il s'agit de l'équivalent de null en PHP, Java, C, et dans de nombreux langages de programmation. Le seul changement que nous avons fait dans la fonction que l'on a ajouté dans ce chapitre, c'est qu'il n'y a plus le mot-clé local devant game = sol.main.load(“save1.dat”) car nous ne voulons pas déclarer une une nouvelle variable, mais utiliser celle déclarée plus haut dans le fichier.

Pas d'exercice sur ce chapitre ! Nous en ferons sur le prochain mais pour l'instant amusez-vous avec les tiles sur une map : vous avez les bases pour créer des maps un minimum intéressantes à parcourir. Vous pouvez malgré tout récupérer le résultat si vous le désirez.

Chap. 1 : Mise en routeChap. 3 : Maisons et ForêtsSommaire

fr/tutorial/the_first_map.txt · Dernière modification: 2018/12/22 14:14 (modification externe)