iftechfoundation / twine-cookbook

Twine Cookbook
132 stars 31 forks source link

Harlowe cycling example in the cookbook #43

Closed AtticsandSheds closed 6 years ago

AtticsandSheds commented 6 years ago

I'm new to all this and the cookbook and Harlowe manual have both proved absolute lifesavers. However, I've noticed that the Harlowe code example for cycling choices used in the cookbook doesn't appear to work when typed into twine 2, even when it's just copy-pasted. It involves a lot of "if $choicecount>=it then set to 1" and it just seems a little overwhelming as a beginner. I couldn't spot any proposed alternatives, so I took the liberty of providing my own that seemed a little less clunky (at least from here, I'll happily admit that I'm learning a lot of this as I go)

Isn't it easier to just rotate the array and always display the first entry? If you update the button every second then you can just keep on clicking. You can even add a back button by copying the code and changing it to rotate -1

EXAMPLE (set: $choicecount to (a: ["One"], ["Two"], ["Three"])) (live:1s)[(display: 1st of $choice)] [Next]<next| (live:1s)[(click: ?next)[(set: $choicecount to (rotated:1,...$choicecount))]

Setting up a simple "go" button has proven a little difficult, but I've had some success using a secondary passage that loads up the choices. as its basically only functioning as a directory that the reader doesn't see

EXAMPLE 2 CHOICE PASSAGE (set: $choicecount to (a: ["One"], ["Two"], ["Three"])) (live:1s)[(display: 1st of $choice)] [Next]<next| [Go]<go| (live:1s)[(click: ?next)[(set: $choicecount to (rotated:1,...$choicecount))] (live:1s)[(click: ?go)[(go-to: "Loader Passage")]

LOADER PASSAGE (if: 1st of $choicecount = ["One"] [(go-to: "Passage One")] (if: 1st of $choicecount = ["Two"] [(go-to: "Passage Two")] (if: 1st of $choicecount = ["Three"] [(go-to: "Passage Three")]

There's probably an easier solution somewhere, but if this is any help for the cookbook, please take it. If I'm just creating more issues than I've solved I'm sorry for wasting time but I'd appreciate any criticism so I can get better at this.

greyelf commented 6 years ago

@AtticsandSheds Thank you for your suggestions.

doesn't appear to work when typed into twine 2

It would help if you explained what issues you had with the example.

The only Twine 2 application related issue I know of is that if you choose Harlowe 2.x as your story format then the (array:) macro will incorrectly be marked as invalid, even though the 2.x series actually supports both the (array:) and (a:) syntax for creating an Array.

As explained within the Organisation > Layout section the supplied examples are in TWEE Notation, which means you may need to add one or more new Passsages (with the relevant names) to your project to get the example to work. Or if you are using the Twine 2 application then you can also download and import the linked Live Example, which will automatically create the required Passages for you.

Isn't it easier to just rotate the array and always display the first entry?

You are correct in that you could use the (rotated:) macro to reduce the number of story variables needed to achieve the same result, although there are a number of potential issues with your implementations.

  1. The (live:) macro creates a timer which interferes with the user's ability to interact with the page each time the related event fires, this interference becomes more noticeable when you either reduce the delay , increase the number of (live:) macros in a Passage, or do both. Because of this it is generally suggested to only use a single (live:) macro per Passage and to only use then when absolutely necessary.

  2. The (click:) macro needs to wait until the whole Passage has been processed before it can scan the whole page looking for the indicated hook or text, and any dynamic HTML changes done to the resulting page (eg via macros like (replace:) which alters the page) can cause that scanning process to reoccur. This is why it is generally suggested to only use them when absolutely necessary.

The following is one possible implementation that uses the (rotated:) as you suggested, without the above potential issues:

:: StoryTitle
Cycling Choices in Harlowe

:: Start
(set: $choices to (array: "First", "Second", "Third"))
Click options to cycle: [(display: "Cycling")]<choice|
[[Submit|Results]]

:: Cycling
{
    (link: (text: $choices's 1st) )[
        (set: $choices to (rotated: -1, ...$choices))
        (replace: ?choice)[(display: "Cycling")]
    ]
} 

:: Results
Selected choice: (print: $choices's 1st)

NOTE: The above also solves the potential issue of exceeding the web-browser' maximum allowable HTML structure depth (which will cause an error) that the Cookbook's Harlowe example can trigger if the user keeps clicking, this is why the above uses a named hook combined with (replace:) macro to update the link.

videlais commented 6 years ago

Updated by @greyelf.

Commit #45.