+2 votes
by (150 points)
It's been a while since I've dug into Twine and my code brain is stunted. I'd like to create a sort of magnetic poetry function and thought Twine might be able to handle it.

It doesn't have to be fancy. Something like: the audience would see a blank area, and a "word bank". They could click on a word in the bank, and that word would appear in the blank area. They could click another word, and that word would appear next.

I don't so much care about undo or unselecting words right now.

A nice bonus would be if there was a way to share their creations, but that seems like a lot to ask!

Is this possible?

I prefer using Twine Original Flavor, but am willing to transition to Twine 2 if that's necessary!

1 Answer

+1 vote
by (63.1k points)
edited by

That's a cool idea.  How I'd handle it is through a single string variable containing the poem, then use DOM replacement macros (<<replace>> in SugarCube) to update the output.  I'd store the word bank itself in an array.

Here's a rough example of how something like that might look in SugarCube 2.  Note that you can install SugarCube 2 in Twine 1 if you want to stick with 1.

::StoryInit
<<set $poem to ''>>
<<set $wordBank to [
    'hello',
    'how',
    'the',
    'sky',
    'blah',
    'feels'
]>>

::main
<div id='poem'>$poem</div>
<div id='word-bank'><<include 'bank'>></div>

::bank
<<for _i to 0; _i < $wordBank.length; _i++>>\
    <<capture _i>>\
        <<link $wordBank[_i]>>
            <<addword $wordBank[_i]>>
        <</link>>
    <</capture>>\
<</for>>
<<button 'Add Line Break'>>
    <<addbreak>>
<</button>>\

::widgets [widget nobr]
<<widget 'addword'>>
    <<set _word to $args[0]>>
    <<set _del to $wordBank.indexOf(_word)>>
	
    <<if $poem is ''>>
        <<set $poem to _word>>
    <<else>>
        <<set $poem to $poem + ' ' +_word>>
    <</if>>
	
    <<run $wordBank.deleteAt(_del)>>
	
    <<if $wordBank.length < 1>>
        <<replace '#word-bank'>>\
            <<link 'Again'>>
                <<run Engine.restart()>>
            <</link>>\
        <</replace>>
    <<else>>
        <<replace '#poem'>>$poem<</replace>>
    <</if>>
	
    <<replace '#word-bank'>><<include 'bank'>><</replace>>
<</widget>>

<<widget 'addbreak'>>
    <<set $poem to $poem + '\n'>>
    <<replace '#poem'>>$poem<</replace>>
<</widget>>

Then in CSS:

#word-bank {
  float: right;
  margin: 2em;
  margin-top: 10%;
  padding: 1em;
  border: 2px #eee solid;
  height: 20em;
  width: 10em;
}

I'm not sure if there's an easy way to accomplish this in Harlowe or Sugarcane; the <<for>> macro and the <<capture>> macro are pretty important here, and Sugarcane lacks both.  It might work with some modification in Harlowe.

by (157k points)

NOTE: Harlowe is a Twine 2 only story format.

by (150 points)
Oh wow, thank you!! this is so close to what I imagined!

The main problem I'm having is that the words aren't properly disappearing. When I click one to add to the poem, it effectively deletes it from the wordbank but doesn't visually delete it. So when I click another word that comes after that one in this list, it actually clicks one farther -- Does that make sense? I'm on Mac 10.11, and it does this with Chrome and Safari.
by (63.1k points)

I can't seem to reproduce that exact issue, but I did notice a mistake in the 'addword' widget.  Try changing it to this and let me know if that helps. 

<<widget 'addword'>>
    <<set _word to $args[0]>>
    <<set _del to $wordBank.indexOf(_word)>>
	
    <<if $poem is ''>>
        <<set $poem to _word>>
    <<else>>
        <<set $poem to $poem + ' ' +_word>>
    <</if>>
	
    <<run $wordBank.deleteAt(_del)>>
	
    <<if $wordBank.length < 1>>
        <<replace '#word-bank'>>\
            <<link 'Again'>>
                <<run Engine.restart()>>
            <</link>>\
        <</replace>>
    <<else>>
        <<replace '#word-bank'>><<include 'bank'>><</replace>>
    <</if>>
	
    <<replace '#poem'>>$poem<</replace>>
<</widget>>

 

by (150 points)

Thank you, Chapel!

I ended up getting a little outside help on the disappearing words issue. I ended up with this code, which works!

<<set $poem to ''>><<set $wordBank to [
'The', 'day', 'I', 'was', 'born,', 
]>><h1>Header</h1><div id='poem'>$poem</div><div id='bank-container'><h2>WORD BANK</h2>
    <<for _i to 0; _i < $wordBank.length; _i++>>\
        <<capture _i>>\<<link $wordBank[_i]>> <<addword $wordBank[_i]>>
            <</link>>\
        <</capture>> &middot; \
    <</for>>
    <<button 'Add Line Break'>>
        <<addbreak>>
    <</button>>\
</div>

<<widget 'bankWidget'>>
    <<if $wordBank.length < 1>>
        <<button 'Again'>>
            <<run Engine.restart()>>
        <</button>>\
<<else>>\
    <<for $i = 0; $i < $wordBank.length; $i++>>\
        <<capture $i>>\
            <<link $wordBank[$i]>>\
                <<addword $wordBank[$i]>>\
            <</link>>\
        <</capture>> &middot; \
    <</for>>
    <<button 'Add Line Break'>>
        <<addbreak>>
    <</button>>\
    <</if>>
<</widget>>

<<widget 'addword'>>
    <<set _word to $args[0]>>
    <<set _del to $wordBank.indexOf(_word)>>

    <<if $poem is ''>>
        <<set $poem to _word>>
    <<else>>
        <<set $poem to $poem + ' ' + _word>>
    <</if>>
    
    <<run $wordBank.deleteAt(_del)>>

    <<replace '#poem'>>$poem<</replace>>

    <<replace '#bank-container'>><<bankWidget>><</replace>>
<</widget>>

<<widget 'addbreak'>>
    <<set $poem to $poem + '\n'>>
    <<replace '#poem'>>$poem<</replace>>
<</widget>>

And here's the wordbank CSS for that, including a bit to make the wordbank look more like cut out words:

#bank-container {
  float: right;
  margin: 0em 1em;
  padding: 0em 1em 1em 1em;
  border: 4px #eee outset;
  height: auto;
  width: 45%;
  line-height: 200%;
  background-color:rgba(0,0,0,0.5);
  text-align: center;
}
a {
  padding: .15em .45em;
  background-color: white;
  color: black;
}

Thanks for your help!!

Welcome to Twine Q&A, where you can ask questions and receive answers from other members of the community.

You can also find hints and information on Twine on the official wiki and the old forums archive.

See a spam question? Flag it instead of downvoting. A question flagged enough times will automatically be hidden while moderators review it.
...