Dynamic UI Layouts in SugarCube (Patreon)
Content
When developing interactive fiction with Twine and SugarCube, it's often useful to have different UI layouts for different parts of your game, such as a fullscreen layout for immersive story moments and a sidebar layout for passages where you go through a daily routine.
This is something I haven't been doing efficiently in MindWare, but I now have a solution that (at least to me) seems fairly elegant and robust.
Basically, my solution uses Twine's passage tag system combined with JavaScript in the SugarCube StoryInterface special passage (used to create a custom UI):
:: StoryInterface
<script>
$(document).on(':passagestart', function (ev) {
var passage = ev.passage;
var tags = passage.tags;
var root = $('#ui-root');
if (tags.includes('fullscreen')) {
root.html('
');} else if (tags.includes('sidebar')) {
root.html(`
Game Title
`);
} else if (tags.includes('split')) {
root.html(`
`);
} else {
// Default minimal layout
root.html('
');}
});
</script>
When a passage loads, the system checks its tags and rebuilds the UI accordingly. Now you can create passages that use different layouts simply by adding tags:
:: Story Beginning [fullscreen]# Chapter OneThe story begins in a quiet village...This passage uses the fullscreen layout for an immersive reading experience.[[Enter the tavern|Tavern]]:: Tavern [sidebar]# The Rusty Dragon TavernYou enter the bustling tavern. The air is thick with smoke and laughter.
:: Notice Board [split]# Notice BoardSeveral parchments are pinned to the wooden board.
You can add new layouts by extending the JavaScript in StoryInterface:
else if (tags.includes('custom')) {
root.html(`
<!-- Your custom HTML structure. Remember that you need
because that's where the content of your passages is displayed -->
`);
}
When you save your game and then load the save, the layout system automatically restores the correct UI for the current passage. This happens because SugarCube fires the :passagestart event before the rendering of an incoming passage.
If you need certain UI elements to persist across layout changes (like a music player or notification system), place them outside the #ui-root:
:: StoryInterface
I'm not sure how many of my supporters are interested in Twine/SugarCube game development, but I hope this helps if any of you are.