How to Make a Media-Rich Twine Game and Package it for Embedding on Itch.io

Featured image for blog article (web-playable Twine game on itch.io)

Lots of indie game writers love Twine for its simplicity and accessibility. Write a game, save it as an HTML file, and bam: instant interactive fiction, playable with any modern web browser.

But with the help of languages like Sugarcube 2, Twine is also capable of more feature-rich stuff complete with visual assets and music. Unfortunately, the documentation on that can be a little sparse. So, to save the next person down the road some time, here’s a quick guide on how to get images and music into a Twine game, and how to package that game to be playable on itch.io.

I recently released a new game (which you can play now!) so we’ll use that as an example. I’ve also included the source files for pumpkin.jpg at the bottom of this post, with a few terms for their use.

Please note: For this tutorial, I’m going to assume you’re using the desktop version of Twine, the Sugarcube language, and have general familiarity with both. If not, you’re going to want to consult some other tutorial first. If you’re using another language like Harlowe, the principles are probably pretty much the same, but I don’t use it myself, so I can’t help you.

HTML5 Game File Structure

The first thing it’s helpful to understand is the way an HTML5 game is structured at the folder level.

The heart of any html game is the index file. This is what a browser looks for when you open an html page; anything else in the folder are things the index file references and calls.

1. Desktop view of game files
1. Desktop view of game files

Here you can see the folder for pumpkin.jpg. Index.html is my published Twine story. The folders are where I store the images and music.

Those also have subfolders within them. Here you can see those expanded.

2. Desktop view of game files with folders expanded
2. Desktop view of game files with folders expanded

You don’t have to name your folders like I do. All of that is up to you. The only filename that’s mandatory is index.html.

Calling assets in Twine

To call external images within the game itself, I just use a standard html image tag.

Here I’ll call the image “titleimg.jpg”, within the folder images/assets:

3. My game, "pumpkin.jpg", open in the Twine desktop editor
3. My game, “pumpkin.jpg”, open in the Twine desktop editor
4. The start passage of pumpkin.jpg, with an HTML image call highlighted
4. The start passage of pumpkin.jpg, with an HTML image call highlighted

Here’s that filepath in my desktop file browser, just for reference:

5. Desktop view of the filepath for that image
5. Desktop view of the filepath for that image

Crucial note here: this filepath is case-sensitive. If you call an image within Twine using the wrong capitalization in the file-path, it may not load correctly in all browsers.

So if you notice an image isn’t loading while testing your game, and you’re pulling your hair out trying to figure out why, go into your Twine file and double-check your capitalization. (ASK ME HOW I KNOW.)

Audio calls are handled pretty similarly, though for those, I use Sugarcube’s built-in audio handler tags. In image 4 above, you can see how I preload each audio file at initialization. Then, when I want to call an audio asset later on, I just do this:

6. The Twine editor, with a Sugarcube audio call highlighted
6. The Twine editor, with a Sugarcube audio call highlighted

(For more on that, check Sugarcube’s documentation, which you can find here.)

For all the fancy aesthetic stuff, like styling fonts, adjusting image sizes, setting window margins, etc, I use CSS, which you can find in your dropdown menu in Twine under “edit story stylesheet”.

I barely understand how to get Twine and CSS to play nicely together myself, so I won’t even try to give a tutorial on that stuff; you’re gonna have to muddle through and angrily google stuff on your own like I do. Sorry! But if you’d like to explore my stylesheet for pumpkin.jpg, you can find it in the example files at the bottom of this post.

(But again, I barely know what I’m doing, so by no means should you take my hacked-together crap as an example of “good” CSS code. I just stumble through on trial and error.)

Testing Your Game

Because we’re pushing Twine a little beyond what the base engine is designed for, the built-in PLAY button in the lower right-hand corner won’t help us much. If you try to playtest a game with external assets using the PLAY button, the images won’t load. This is because that button builds and runs your Twine game based ONLY on what’s inside it; the Twine software can’t “see” anything else.

Instead, you’re going to use the PUBLISH button.

7. Screenshot of the Twine editor, showing where to find the Publish button
7. Screenshot of the Twine editor, showing where to find the Publish button

Navigate to the folder where you intend to keep your game assets, and save your published Twine file at the root level as “index.html”.

Then, to test your game, just run index.html in the browser of your choice!

(Note: some browsers disable the ability of an html file to pull from locally-hosted assets on your computer, by default. Apparently it’s a security thing. This takes about 10 seconds to disable in most browsers and is a pretty common question, so google should be able to tell you how to do it in yours.)

Unfortunately, you’ll have to republish your file every time you want to test it. Thankfully, when you click publish, Twine automatically opens to your most recently-viewed folder, so all you have to do is click the existing index.html file and overwrite it.

Why do all this instead of just hosting assets online, e.g. on my WordPress site?

  1. The images will load faster in your game.
  2. It allows you to package your game for distribution as a browser-playable, without needing to access any other websites.
  3. It also lets you package the game as a self-contained thing, i.e. so someone could just download it and play it offline.
  4. It doesn’t require you to even have your own website, because a lot of creative people don’t nowadays. (Which seems crazy to me, but I guess that just makes me an old geezer.)

Packaging for itch.io

Once your game is complete, publishing it as a web-playable browser game on itch.io is as easy as zipping the folder and uploading it!

8. Desktop view of game folder compressed into a ZIP file
8. Desktop view of game folder compressed into a ZIP file
9. Screenshot of the itch.io dashboard with an example project created
9. Screenshot of the itch.io dashboard with an example project created
10. The EDIT page for the example project.
10. The EDIT page for the example project.
11. The Upload area of the edit page for the example project.
(You have to scroll down to find this.)
11. The Upload area of the edit page for the example project.
(You have to scroll down to find this.)

Note that when itch unpacks your zip file, the scraper accesses things at the root level of your game’s folder. (Basically, think of itch as a little robot that plunks down right next to your index.html file). That means you don’t need to include the folder name itself in your filepaths.

Other browser-game hosts may handle this differently. I wouldn’t know. Be sure to read whatever documentation they provide carefully!

Also, if you want the game to be browser-playable (rather than a download), make sure you set the filetype correctly on your game’s edit page.

12. The "Kind of project" dropdown on the itch.io edit page
12. The “Kind of project” dropdown on the itch.io edit page

Source files

If you’d like to tear through the source files for pumpkin.jpg, you can download them here.

(I’m sharing this under a Creative Commons 4.0 International License, which means you’re free to share, copy, and redistribute it, so long as you’re not selling it and you attribute it to me. You can modify it as much as you like for your own learning purposes, but you’re not allowed to distribute it with modifications.)

Hopefully this helps save someone else some time!

If you have any questions, feel free to pop them in the comments.