== Lesson 13: A Game Folder image::learn/13-game-folder.png[The finished lesson, 480] Your game is a script in a folder you remember the name of, started by typing its name at a terminal. That is fine for you and useless for anybody else. A player should be able to copy a folder next to Singe, start the menu, see your game listed with its title and its artwork, and press a button. The picture above is that menu, with your game in it. That takes one new file, about six lines long, and two pictures you can take with one key. Your script does not change at all. === Give the Game a Name A game has two names, one for the computer and one for people. The one for the computer is the folder, and you chose it in lesson nine: `rocks`, with `rocks.singe` inside it. The folder and the script share a name, the way every lesson has since lesson one, which is why `Singe rocks` finds the script from the folder alone. Keep that name plain. No spaces, which a terminal reads as the gap between two names. And the same capitals everywhere you type it: on most computers that are not Windows, `rocks` and `Rocks` are two different folders, and a game that only runs on your machine is not a game anybody else can have. The name for people can be anything you like, capitals, spaces, and all, and it does not live in the folder name. It lives in the file this lesson is about, so that renaming the game on the menu never means renaming a folder. === What Goes in the Folder Everything your game needs, and nothing else. By the end of this lesson it looks like this: ---- rocks/ games.dat What the menu reads rocks.singe The game art/ The art kit from lesson nine spaceship.png asteroid.png bullet.png star.png shoot.wav boom.wav ... cabinet.png A picture the menu shows beside the list marquee.png A picture the menu shows above it ---- Anything else that ended up in there while you were learning -- `walk.singe` from lesson nine, the little sound test from lesson ten -- is not part of the game. Move them into a folder of their own beside `rocks`. The art kit also has a few files this game never loads, and they do no harm for now. Lesson thirty is where you go through a game folder and take out everything that is not the game. The rule behind that layout is that a game never reaches outside its own folder. Not for artwork, not for a sound, and not for a library you also use in another game -- if you share code between two games, each one keeps its own copy. There is exactly one place outside the folder a game may load from, and you are already loading from it: the engine's own `Singe` folder, where `Singe/Framework.singe` lives, and since lesson ten the click and the music. The game folder sits in your work folder, beside the engine: ---- singe/ Your work folder Singe-v3.00-... The engine itself, whatever yours is called Menu.sh Starts the menu. Menu.bat on Windows Singe/ Support files. Not yours; leave them alone data/ Everything anything writes, your save among it rocks/ Your game ---- That is the shape a player's machine has too. The engine wrote `Singe`, `data`, and `Menu.sh` (`Menu.bat` on Windows) the first time you ran anything, back in lesson one. Lesson one mentioned the first two. The third is new to you, and this lesson puts it to work. === Paths Count from Where Singe Started You have been doing this since lesson nine, so this is a reminder, not a change. Every name your game loads -- `art/spaceship.png`, `art/boom.wav` -- is looked for starting at the folder Singe was *started in*, not the folder your script is in. You start Singe in your work folder, so a bare `art/spaceship.png` would be looked for in `singe/art`, which does not exist. `DIR` is your script's own folder with the slash already on the end, so a name joined to it points at your file from wherever Singe was started: [source,lua] ---- local shipSprite = spriteLoad(DIR .. "art/spaceship.png") ---- The menu starts Singe in the folder `Menu.sh` sits in, which is your work folder again, so `DIR` does there exactly what it does for you. It keeps doing it when the game is packed into a single file in lesson thirty, when somebody else's work folder is called something else entirely, and on a machine you will never see. A name that begins `Singe/` is the engine's folder and never needs `DIR`; every name that is yours does. === games.dat `games.dat` is how a game introduces itself. The menu reads the `games.dat` of every game folder beside it and lists what it finds. No `games.dat`, no listing: your folder is invisible, however good the game inside it is. Make a new file called `games.dat` in your `rocks` folder. This is the smallest one that works: [source,lua] ---- GAMES = { { TITLE = "Rocks", SCRIPT = "rocks/rocks.singe" } } ---- That is Lua, and it is a table of the kind you met in lesson six: `GAMES` is a list, and each thing in the list is a record describing one game. One folder can hold several games -- that is why it is a list -- but yours holds one. `SCRIPT` is the field the engine needs to run the game, and `TITLE` the one the menu needs to list it. The script's path is counted from the folder *above* the `games.dat`, not from the folder the `games.dat` is in. So a `games.dat` inside `rocks` names its own script as `rocks/rocks.singe`. That looks like it says `rocks` twice and it is correct. Every other path in the file works the same way. Get it wrong and nothing complains when you type the name: the entry simply never matches the script you ran. `TITLE` is the name for people from the start of this lesson. It is what the menu shows, and games are listed in title order, so a title is also where your game sits in the list. === Telling the Menu More The menu has a whole panel to fill beside the list, and it fills it from the rest of the entry: [source,lua] ---- GAMES = { { TITLE = "Rocks", SCRIPT = "rocks/rocks.singe", CANVAS_X = 720, CANVAS_Y = 480, YEAR = 2026, GENRE = "Shooter", DEVELOPER = "Your Name Here", PUBLISHER = "Your Name Here", DESCRIPTION = "Shoot the rocks before they reach your ship.", CABINET = "rocks/cabinet.png", MARQUEE = "rocks/marquee.png" } } ---- `CABINET` and `MARQUEE` are ordinary image files in your game folder, in any format Singe can read. The cabinet art is the big picture beside the list and the marquee is the strip above it. Make them whatever size you like; the menu fits them into their panels. You do not need a drawing program to make them, because your game can take its own picture. Run it, and when the screen looks the way you want the world to see it, press F12 (or F11, because some desktops keep F12 for themselves). Singe saves a picture of the window into your game's data folder, `data/rocks`, named `singe000.png`, then `singe001.png`, and so on. Take one of the title screen and one in the middle of a fight. Copy them into your `rocks` folder and rename them: the fight is `cabinet.png`, the title is `marquee.png`. A real marquee is a wide strip with the game's name in big letters, and a whole screen squeezed into it looks like a postage stamp. It will do until you have something better. Leave `MARQUEE` out and the menu puts the engine's own missing picture there instead, a pink checkerboard that says MISSING, which is worse. `YEAR`, `GENRE`, `DEVELOPER`, `PUBLISHER`, and `DESCRIPTION` are the text underneath, and the engine never looks at them. They are for the person reading the menu, which is the point. `CANVAS_X` and `CANVAS_Y` are the size of your game's world, and 720 by 480 is the default -- the same world you have been drawing in since lesson one. Set them only if your game wants a different shape. A game with no `VIDEO` field is a game with no video, which is what yours is; lesson fourteen is where that field starts to matter. The reference's `games.dat` section lists every field there is, including several for hardware you do not have yet. A few more are worth knowing the names of now. `REQUIRES` says what a game needs from the machine beyond plain 2D: `"GUI"` for the menus and pages of lesson twenty, `"SCENE"` for the 3D that starts in lesson twenty-two, and a few more. The menu reads it so that it can tell a player "this machine cannot run that" instead of letting the game fail halfway in. Rocks is plain 2D, and leaving `REQUIRES` out means exactly that, so leave it out. You will rarely have to work out the list yourself, because Singe notices what a game uses as it runs and says so when the entry does not list it. From lesson twenty on you will see lines like this one, whether or not the game has a `games.dat` at all: ---- Warning: this game uses GUI, which its games.dat does not list in REQUIRES. ---- It is advice, not an error; the game runs either way. The cure is one line in the entry, `REQUIRES = { "GUI" },`, and packing a game in lesson thirty writes the list for you if the entry has none. Its partner `TIER`, a number from 0 to 3, says how much machine a game wants, and can wait until you write a game heavy enough to care. `GAME_ID` is a unique identity for your game, which the online high score tables in lesson twenty-eight need and nothing else does. And `RESOLUTION_X` and `RESOLUTION_Y` ask for a particular window size. Ignore the rest until something sends you looking. === Running It from the Menu Run `Menu.sh` -- `Menu.bat` on Windows -- from your work folder. It finds the newest Singe beside it and starts the menu. Your game is in the list, with its artwork beside it and its description underneath. It is the only thing in the list, because `rocks` is the only folder you have given a `games.dat`; `hello`, `dodge`, and the rest are not games as far as the menu can tell. Up and down move one game, left and right move a page, and start or a fire button plays the one that is selected. Quit the game with Escape and you are back at the menu, on the same game, ready to go again. The menu remembers which game you were on between runs, too. That is the whole of shipping a game, as far as the engine is concerned. A player copies your folder next to Singe and it appears. Typing the name still works, and works the same way: ---- Singe rocks ---- When you launch a script by hand like that, Singe looks for a `games.dat` beside it -- and in up to three folders above it -- and if an entry names the script you launched, that entry's settings apply to it. So a game plays the same from a terminal as from the menu, which means you can go on working the way you have been, with `-R` and a text editor, and still trust what a player will get. It writes to the same place, too: started either way, your game's save is the one in `data/rocks`. === Later: One File A folder is easy to work in and slightly awkward to give away: a dozen files, a folder inside a folder, and a player who unzips it into the wrong place. A finished Singe game can be packed into a single `.game` file that the engine runs directly, artwork and sounds and all, which a player copies next to Singe and is done. Nothing in your game has to change for that. It is lesson thirty, and it is worth waiting for: pack a game that is not finished and you will pack it again tomorrow. === What Just Happened [source,lua] ---- GAMES = { { ---- Two braces, because it is a list of records. The outer one is the list. The inner one is the first thing in the list, which is the record for one game. Getting one of them wrong is the usual mistake, and Lua will tell you the line. [source,lua] ---- SCRIPT = "rocks/rocks.singe", ---- Counted from the folder above the `games.dat`, which is your work folder. It is the same name you would type after `Singe` to run the script by hand, and that is the easiest way to remember it. The comma at the end of the line separates one field from the next, exactly as in lesson six. The last field in a record has no comma after it -- Lua does not mind if it does, but leave it off and your file will look like everybody else's. A comma that is missing in the middle is another matter, and it is this lesson's error. [source,lua] ---- CABINET = "rocks/cabinet.png", ---- A picture the menu loads, not your game, so it is named the way `SCRIPT` is, from the folder above, and not with `DIR`. `DIR` belongs to your script while it runs, and the menu and the engine read `games.dat` before your script has started. === Try It . *Make better artwork.* If you have a drawing program, make a proper `marquee.png`: a wide strip with ROCKS across it in big letters. Put it in place of the screenshot and look at the menu again. . *Give Dodge a games.dat.* Write a `games.dat` in your `dodge` folder from lesson seven and start the menu. Two games now, in title order. Then change the `TITLE` of Rocks to `Asteroid Field` and watch it move above Dodge: the list is sorted by title, not by folder. . *Break games.dat for the menu.* Delete one of the closing braces in the `games.dat` in `rocks` and start the menu. Your game is gone from the list, and the terminal says why. Put it back. . *Get SCRIPT wrong.* Set `CANVAS_X` to `1280` and `CANVAS_Y` to `720`, and run `Singe rocks`. The field is wider. Now change `SCRIPT` to `rocks.singe` and run it again. The game is back to its old size, and nothing told you: the entry no longer names the script you ran, so it does not apply. Put both back. . *Find your save.* Start the game from the menu, set a high score, quit back to the menu, and quit the menu. Run `Singe rocks` and look at the title. Then look in `data/rocks` for the file that remembered it. === Break It on Purpose Take the comma off the end of the `TITLE` line, so the top of the file reads: [source,lua] ---- GAMES = { { TITLE = "Rocks" SCRIPT = "rocks/rocks.singe", ---- Run `Singe rocks`. The game starts, and the terminal says this: ---- Note: rocks/games.dat ignored: [string "rocks/games.dat"]:4: '}' expected (to close '{' at line 2) near 'SCRIPT' ---- Your game still runs, because a game started by name does not need its entry. It just runs without it. Start the menu, though, and your game is gone. If it was the only one there, the list says `No games yet`, and the terminal says the same thing a different way: ---- rocks/games.dat: rocks/games.dat:4: '}' expected (to close '{' at line 2) near 'SCRIPT' Skipped. ---- Read it like any other Lua error. The file is `rocks/games.dat` and the line is 4. But line 4 is the `SCRIPT` line, and there is nothing wrong with it. The mistake is at the end of line 3. After `TITLE = "Rocks"`, Lua expected either a comma and another field, or the `}` that closes the record that began on line 2. It found `SCRIPT` instead, so line 4 is where it noticed. Its guess at the fix -- a `}` -- is wrong; its line is out by one. When an error points at the start of a line, look at the end of the line before it. Put the comma back, and start the menu again. === What You Learned * A game is a folder: the script, its artwork, and a `games.dat`, and nothing from outside it except the engine's own `Singe` folder. * The folder's name is for the computer, so keep it plain. The name for people is `TITLE`. * Names your script loads are counted from where Singe was started, which is why every one of them is built from `DIR`. * `games.dat` is a Lua file holding a `GAMES` list, and each entry is one game. * An entry needs `TITLE` and `SCRIPT` and nothing else; paths in it count from the folder above the `games.dat`. * `CABINET`, `MARQUEE`, `YEAR`, `GENRE`, `DEVELOPER`, `PUBLISHER`, and `DESCRIPTION` are what the menu shows the player, and F12 takes a picture you can use for the first two. * `REQUIRES` tells the menu what a game needs beyond 2D, and Singe warns you when a game uses something its entry does not list. * `Menu.sh` or `Menu.bat` starts the bundled menu, which lists every game folder beside it, sorted by title. * A game launched by name gets its `games.dat` entry too, so it behaves the same either way, and a `games.dat` that will not load is reported and ignored. * A finished game can be packed into one file later, in lesson thirty. === Next Time That is part two finished: you have a game, with art, sound, collision, score, and a way for somebody else to run it. Part three is about the thing almost no other engine does -- playing film as the world the game happens in -- and lesson fourteen starts with the disc, the frame, and the wait.