kitbeard's blog

Twine: Bar Charts.

Howdy. The name's Kit. I've been trying to work out how much you can make Twine do that isn't just display the characters you typed in different ways. I'm working on a battle simulator, and I realised that to make it look computer-gamey, it would need health bars. How does one make a bar chart in Twine, anyhow? Well, after a few hours of poking, I can suggest that this is one way - well, three ways. It's best to read them in order, but it's ok, they get simpler. They are all built around the idea of recurring a passage using an if condition nested inside itself, as suggested here.


Method 1


Each bar has three variables - health, which is what the bar is intended to measure, increment, which is the number represented by each unit of the bar, and symbol, which is what each unit of the bar is displayed as. Outer 1 prints the value of health for each bar, divides health by increment, and saves this value as block. It uses a ceiling function (Math.ceil, everyone loves a little javascript) so that if block is not an integer, it is always rounded up. If block is greater than 0, Inner 1 is fired off, which prints the symbol, subtracts 1 from block, and fires itself off if block is still greater than 0. By the time this stops calling itself, it has printed the symbol block times.

Include where you want bar (set the values for health, increment and symbol that you wish - symbol must be in ""s)
<<set $health = 30>><<set $increment = 5>><<set $symbol = "O">><<display 'Outer 1'>>

Outer 1:
<<print $health>> <<set $blocks = Math.ceil($health / $increment)>><<if $blocks gt 0>><<display 'Inner 1'>><<endif>>

Inner 1:
<<print $symbol>><<set $blocks = $blocks - 1>><<if $blocks gt 0>><<display 'Inner 1'>><<endif>>


Method 2

30 ||||||

These bars run using the passages Outer 2 and Inner 2. The bars work exactly the same as in Method 1, except the symbol is not specified. It is "|", hard-coded into Inner 2. If you always intend to use the same symbol, the code should run slightly faster if you use this method rather than that shown in Method 1.

Include where you want bar (set the values for health and increment)
<<set $health = 30>><<set $increment = 5>><<display 'Outer 2'>>

Outer 2:
<<print $health>> <<set $blocks = Math.ceil($health / $increment)>><<if $blocks gt 0>><<display 'Inner 2'>><<endif>>

Inner 2:
|<<set $blocks = $blocks - 1>><<if $blocks gt 0>><<display 'Inner 2'>><<endif>>


Method 3

10 ||||||||||

This is the simplest version of my bars to use. The only variable that has to be specified is health, which will be the length of the bar. Outer 3 has been simplified because of this.

Include where you want bar, specifying health:
<<set $health = 10>><<display 'Outer 3'>>

Outer 3:
<<print $health>> <<if $health gt 0>><<display 'Inner 3'>><<endif>>

Inner 3:
|<<set $health = $health - 1>><<if $health gt 0>><<display 'Inner 3'>><<endif>>


There is one bug I have found - if I try to display a bar of length zero, not only will it not print a bar (which is what I'd like), it also won't print the number 0. I have no idea why this is, but if anyone does, any help is appreciated! If you want to see these running, go to the barchartdemo listed below.

Syndicate content