Solarus Wiki

A wiki for the Solarus engine community

User Tools

Site Tools


tutorial:the_first_map

Chap. 1Chap. 3Table of Contents

Chapter 2 - Your First Map

The game starts and loads the quest well enough, but you are only on a title screen, because your quest is almost empty. In this tutorial, we will see how to create a map and launch the game on this map. We will use the quest editor a lot because its main purpose is the creation of maps.

Getting the Basic Resources

You will first need to get the basic resources you'll need to run the engine. You could create these resources completely on your own, but what you want here is to start a game quickly, so we'll provide you with resources to make a game similar to Zelda: A Link to the Past. Let's look at what these resources contain.

Tiles

First, let's explain what a tile is , in French a tile : they are elements of basic decors, which possess certain properties (is it a wall? Is it animated?). A map is composed of a multitude of tiles. In summary, each time you see a decorative element, it is a tile. And these tiles can be placed on several “levels” in the map (low, intermediate and high layer, in the software in English these are the low, intermediate and high layer). We will return to the diapers in a forthcoming chapter.

The quest editor allows the cutting of a tileset, a tileset being a set of several tiles forming part of the same skin, for example the skin of a particular house or dungeon. Creating a tileset is an easy but long and somewhat tedious exercise. Again, we will address this in a forthcoming chapter. For now, you can download the tileset we need here. Unzip this file and put its contents under data\tilesets.

Sprites

Tiles are not the only entities present on a map. There are also enemies, doors, chests, npcs, bushes, teleporters, etc. These entities can, for the most part, be represented on the map by sprites. A sprite is an animation constructed by a succession of still images. For example, when the hero walks, it is a succession of still images, the animation is not “real”. A bit like an animated gif, these are images that, put together end to end, give the illusion of animation. Note that not all sprites are necessarily animated, there are sprites composed of a single image (eg grass).

The Solarus engine needs two files to define a sprite: a .png file that contains all the images that make up the animation, and a .dat file that shows where each image in the .png file is located And what is the delay between each image. The same .png file can contain the images of several sprites, such as the shield that has its three possible evolutions in the same .png image. The inverse can also be true: for sprites with many different animations, the animations can be separated into several .png files.

Although the quest editor now allows the editing of sprites, this chapter is not devoted to sprites, and we advise you to download the minimum resources needed by the engine here. Unpack this file and match the subdirectories of the data folder . Replace all the requested files, it will not hurt your tilesets files (if they have disappeared, put them back).

Music and Sound

The archive contains Game Over music, imposed by the engine in version 1.0 because the game-over menu is hard-coded. (With version 1.1, the game-over menu is fully customized, but this tutorial is still only covering 1.0.) Music can be in SPC format (not recommended), IT format (recommended) or OGG format. The first two formats are very specific to the games, see the Wikipedia links for more information. The last format is very simple to use but does not allow advanced or complex loops: it will just loop on all the music (intro included if there is one). Converters to OGG are easy to find, while SPC and IT require specific software.

The engine also requires the presence of a number of sound files. They are also in the archive.

Building Your Map

Create the Tileset

In the quest editor, we will right click on the Tileset folder and make New tileset. We have downloaded tilesets from the world of light (light_world), but the engine and the editor do not yet know that they exist, because they must be indicated in the list of resources. The first dialog box asks you for the id of the tileset. As shown on the screen, set “light_world”. As you will have noticed, the id is the name of the files of tileset without extension. Therefore, the filenames and the id must match. The files being light_world.dat, light_world.entities.png and light_world.tiles.png , The common core of these three files is light_world. This is the ideal id.

The second dialog box prompts for a user-friendly name. This is an easier name to remember for an end user. This is the name that will appear in all your options for using this tileset in the editor, where the id is only the name of the file. All the resources in the tree to the left of the quest editor work on this principle: you will see just after that by doing a new map, it will ask for the id and the user-friendly name. Put what you want as a user-friendly name for this tileset, we will refer to it in future as the “outer world”.

If the editor says it can't open the .dat file, search for and manually edit the ground setting for water_bottom_right to wall_bottom_right_water. Do the same for the entries water_top_left, water_top_right, and water_bottom_left, but make sure the new entries match the directions of the old directions. In newer versions of the editor, these specific tile types were changed

If you double-click on the newly created tileset, you will see how the whole tileset is arranged: it is composed of a multitude of elements, sometimes tiny (the smallest is 8 * 8 pixels), sometimes enormous. By right-clicking on one of the elements, you will see its ground properties with their description.

Create Your First Map

Now that the tileset is filled in, you can create a map. Right click on maps and select New Map. This time, you get to pick the id. The file created will have this name with a extension .dat. This can be anything you want, for example “test_map”. It is advisable to make file names without accents and without spaces to allow your game to work on any file system. The name of the map is requested in the second dialog, and it can be whatever you want, but we'll refer to this later as “test map”. In the latest editor, the new map will automatically select your first available tileset in your list of tilesets, but you can choose whichever tileset you'd like. For now though, we should only be using the “World Outside” tileset we set up earlier. Note that, like tilesets, you can “fill in” an already existing map,meaning that your existing map.dat file will be detected.

By default, maps are 320 × 240 pixels in size and are completely empty. Next we'll see how the interface works and what each element is used for.

Explanation of the Interface

Interface

  1. Map id: The identifier of the map, as we put it in the first dialog, it is the name of the file without extension.
  2. Map name: Name visible in the quest editor, which you specified in the second dialog box when creating the map. It can be changed here easily.
  3. Size: the size of the map. By default, it is 320 × 240, but you can enlarge or reduce it at will. You can only modify it by 8 in 8 pixels, that is to say that a size of 324 is not valid, it is 328 or 320.
  4. World: compulsory in version 1.0, optional in a future version, it allows to “link” several maps together. For example, when you make a dungeon of several floors, if you put the maps of all your floors in the same world (eg “dungeon_1”), then by saving to that dungeon, the game will start again at the dungeon entry And not the last floor you visited. We will see this in a future tutorial.
  5. Location in its world: Allows you to set the position of the map relative to its neighbors if there are any. It is used in the case of an outer world map made up of several pieces: let's put a world composed of 3 × 3 boxes, all making 800 × 800 pixels (simpler for the calculations in the example). The third map of the first row will have a position of 0.1600 (in its entirety, it will be at these coordinates). The second map of the second line will be at coordinates 800,800 and the one below it will be in 1,600,800. The last of the square will be in 1600, 1600. You will understand, it is the sum of the sizes of the maps above and to the left of the current map. If you create a mini map in your pause menu, you will need this information to display the correct player position on the world map.
  6. Tileset: the tileset (skin) used by the map.
  7. Music: The music that will be played on this map. If you leave “<same as before>”, there will be no change of music at the start of the map, and the previous music will continue uninterruptedly to be played. Similarly, if you put a particular music and this music was already played in the previous map, it will continue without cut.
  8. Zoom: allows you to zoom in on the map, very useful to have an overview (minimum zoom) or to manage specific cases (maximum zoom).
  9. General displays of the map: the layers to be displayed or not, the transparency and the placement aid grid.
  10. The map itself, on which you will place the elements.
  11. Quick map creation button. Items can easily be created straight from this bar, and many have subtypes. The subtype can be easily changed in the properties of the entity (we will see that). Version 1.1 therefore contains: destination, teleporter, pick-up object, Destructible, chest, jumper, enemy, NPC, block, switch, wall, sensor, crystal switch, crystal block, buyable object, door, staircase and a novelty 1.1. In all cases, these elements are explained in the documentation if you want to know more about their respective uses. The next chapters of this tutorial will show you how to use each type of entity with many examples.
  12. Specific map views: if you want to display some feature types or not, these entity types are exactly those listed in the previous point. Note that there are also “tiles” (static basic tiles), and dynamic tiles that are special tiles that we will not see in a row (these are tiles that can be programmed, for example the holes that Appear when a certain event occurs).

With all this information, you must know what you have to do first, if it's not already set: define what tileset you want to use for this map. Since we do not have many choices for now, use the tileset “World Outside”. Do not forget also to indicate a world, here we can put “outside” for example. Once this is done, you can add the tiles you want on the map, simply click on the tile you want, and place it where you want by clicking once on the map on the map . Here are some tips:

  • A right click to place the tile will keep the tile selected so that you can place several tiles in succession. The left click deselects the tile once it is positioned.
  • A left click (right or left depending on the behavior you want) allows you to extend the tile horizontally and / or vertically by repeating its pattern. If sometimes it gives a weird effect, it is very useful to make long rows of trees or cliffs for example.
  • Once a tile is placed, if you want to resize it, select it and use the “R” key (for R esize ) on your keyboard: the size will resize directly from the mouse to your mouse. Very convenient.
  • Once a tile is placed, if you want to bring it back over the other tiles that overlap it, press “T” (for T op ). If you want to put it all the way down, press B (for B ottom ).
  • You can make multiple selection by holding down the left mouse button with no items selected at the start.
  • You can use the Ctrl or Shift keys to select (or deselect) one or more items.
  • Element Copy and Paste is supported: Ctrl + X, Ctrl + C, Ctrl + V.
  • To stop placing an item, click on an empty place on the tileset.

With these tricks, you have enough to place a few small trees like these:

Small trees

One last thing before you start the next part: put a destination (the first icon in the feature creation toolbar) on the map. The destinations are used to indicate to the engine where to send the hero during a teleportation but also at the start of the game. The destination system allows you to be more flexible than just entering coordinates, because it avoids having to modify coordinates When you move your scenery. On the other hand, the name of the destination must not change, otherwise someone who has a backup on the old name of this destination will not be able to start the game in this area correctly. Make sure you're aware of this when you rename maps or destinations!

Once the destination is set, double-click it or press the Enter key to display its properties. Enter an identifier in “Name”, for example “start”, then press OK. Now we have a nice map. Example of what you can do:

But if we launch the game now, we remain on our title screen, because we have not launched a game. So we will do a little (very little) programming.

Programming the Start of the Game

Reminder of the previous tutorial: in main.lua , you had two functions defaulted by the engine. You can delete them now because they do not serve us (here is the content to delete, line 4 to 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

What we are going to do here instead is that when the Space key is pressed, we will start the game. Here is the corresponding code:

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

Here is the usual analysis of this function, although it is correctly commented. First line: this is the function called by the engine when a key on the keyboard is pressed, with the name of the key as parameter (for the Space key , the name is space). So, we check that the name of the key is indeed space , if that is the case we create the part. The function sol.game.load allows you to initialize or load a backup. Understand that if the file you specify does not exist, the engine creates a new one. The line just after is required only with Solarus 1.0, because it does not guess in which map and to which destination to launch the game. In Solarus 1.1, the default map is the first map in the map list, and in each map, A default destination can be specified. game:set_starting_location Here, the function takes two parameters: the id of the map (thus “test_map”) and the destination in this map (the only one that was created, “start”). Once these formalities are completed, the game is requested to start the game via game:start.

If you try to start the game by pressing the space bar, you will have a disappointment. Indeed, the function on_draw of sol.main is constantly being called by the engine, and so the title screen does not disappear! To remedy this, we will slightly modify the code we wrote in the previous tutorial. We will put the variable game of this file at the same level as the variable title_img, and we will display the title screen only when this variable is empty. Here are the contents of the file after these changes:

-- 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

Information about what we have just done: we have just added an if statement in the display function of the title screen; in this if statement, there is the keyword nil, which means an empty value. This is the equivalent of null in PHP, Java, C, and many other programming languages. The only change we have made in the function we added in this chapter is that there is no longer the local keyword in front of game = sol.main.load(“save1.dat”) because we do not want to declare a new variable but use The one declared above in the file.

No exercise on this chapter! We'll do another on the next one, but for now just have fun with the tiles on a map: you have the basics to create maps that should at least be interesting to browse. You can still download the resulting quest file if you wish.

Chap. 1 : Getting StartedChap. 3 : Houses and ForestsTable of Contents

tutorial/the_first_map.txt · Last modified: 2018/12/22 14:14 (external edit)