I've been trying lots of things in Twine/Harlowe, and seems to be a powerful tool if taken seriously (by seriously, I mean: a tool to create really deep and complex games).
But I'm not a game developer, more like a curious, and there's plenty of options like Ren'Py. So can someone experienced tell me if Twine is really that "solid", and able to develop complex games? For example: a huge adventure with inventory system, lots of ways to complete it, battle and drop/equip items systems, etc?
Or after a bunch of code it will became sluggish? (I tried a page with dozens of if and either statements, and its visible slow to open.
Thanks in advance for any opinions.
Comments
If you want to have good performance you'll need to do some optimisations:
1. Run it as an app, not as a browser page. This can be achieved by packaging the html into nw.js. Browsers are pretty bad at running complex stuff without slowdown, especially if you have other programs running in the background.
2. Look very carefully at when the DOM change happens. As you can see in my video, the art animations and the passage text change happen at different time. This is a deliberate strategy to avoid everything being loaded at once. Especially since text rendering is quite a heavy process, so I try to not have too much going on while the game is rendering the passage text.
TBH I think Harlowe is pretty bad for this kind of timed optimization. It doesn't give you anywhere near the tools SugarCube does for managing the DOM. Harlowe is really only designed for simple, out of the box games - its creators drew a line and decided it would only be for certain types of games. On the other hand, SugarCube gives you precise control over when things are processed into the DOM, is capable of splitting its <<if>> calculations and text rendering into different points, and has a lot better history optimization. In my biased but not inexperienced opinion, this makes SugarCube (and Cradle, see point 4) the only format truly capable of complex games without a hard performance limit.
3. Keep the code optimised per page. There's no feasible use case I can think of for the test you did, of dozens of if/else statements loaded at once into the DOM. My game is very complex, but page lengths are short (as they should be to keep player interest high). Therefore, I don't have essays with lengthy code on each screen - I just do on each screen what I have to do, and that's it. If I need to do more complex stuff, I space out the interactions over a couple of seconds.
4. If you want, convert it into a Unity game using the Cradle Unity plugin. If you already know Unity, or are willing to learn, that would be a good option when starting from scratch. Cradle is its own Twine story format.
Twine is much more powerful than Ren'Py, if you're handy with CSS and Javascript.
The nw.js is a good tip, I was really thinking how to protect the source code.
Ren'Py is good for simple stuff but CSS gives you far more control over animation and graphics if you're good at it. Of course, it can take a lot of time to learn CSS, but there are lots of good books on it.
You can add dungeon exploring and RPG elements (think of the old Joe Dever's Lone Wolf games), with an inventory system, hit points, etc, but it can't get much more complext than that without struggling a bit.
If you are aiming to achieve something similar to what Claretta has, than SugarCube is a good choice. Much better than Ren'py.
The only drawback (of all twine formats) is that if you have a zillion passages, it can get a bit difficult to handle them.
If you want to build a traditional JRPG, then go RPGMaker as it's both easy to learn and very complete.
Anything more complex is probably better handled with Unity, or Cradle.
There are command line tools for generating a Twine Story HTML file from (Twee-based) text files which you can edit using your favourite Text Editor/IDE, which makes handling a large Twine/Twee project no different than handling one in many other programming languages.
I'm struggling A LOT on my inventory and drop/equip system. Maybe I should try hard with SugarCube... Harlowe is so easy and fun that I don't even considered other format.
Most of the time I'm typing on Notepad++, then pasting on Twine. It has some issues for me with large blocks of code/text (slowing when typing, and there's no Ctrl Z sometimes...).
Ah, yes, thank you! That's exactly what I meant, but expressed it horribly.
A possible cause if you are using either complex collection objects (eg. a data-map/array that reference other data-maps/arrays) or large collections, or many collections, is the fact that each time you navigate from one passage to another a 'copy' of the values of all 'known' variables is made (known as state), and it is this 'copy' that is made available to the new passage being shown. The coping process takes time and each of these 'states' take up memory, these 'states' are used by the History system and are what makes Undo possible.
This process is also part of SugarCube but it allows the Author to control the maximum number of states stored.
Yes.
Yups.
Aaaand yeah. Gimme all of that. Also my data is nested, that is, datamaps inside datamaps or arrays inside datamaps.
Very interesting. Disabling the history could be useful for me, since I don't need it and Harlowe's history forces me to minimize the content in my variables, in order to not reach the localStorage limit.
Later today I'm trying to write a basic description of the algorithm my passages run. I've tried to debug it but it's very difficult to know which part is the cause for the bad performance (maybe the loops, maybe the display macros, maybe the datamaps...).
http://twinery.org/forum/discussion/6640/dos-like-interface#latest
I would say look at the various formats and then do basic "tech demo" style games.
If any of the data within your object structure is reference only, as in it does not change for the complete life-cycle of the story, then it would be better to not store that data in story $variables and to store it somewhere else like within your own Javascript Namespace or if you are using SugarCube then possibly within the setup special variable
I've posted a lengthy explanation of my system here. I'd be grateful if anyone could help, but I understand it if it's too complex/abstract/esoteric/long. Anyway, thanks!
You suggest big complex datamaps impact performance. What would perform better: one datamap with 25 records, or 25 different variables? Or the Sugarcube equivalent?
Thanks!
I believe there are two main points where performance could become an issue: when you are processing the data (looping, etc) and during the story format's History tracking process.
From what I understand Harlowe and SugarCube both track the state of all currently known variables for each passage visited, although they do it in slightly different ways:
1. Harlowe creates a new empty variable container for each passage visited, each container contains a reference to the previous container as well as references to the current state of any variables used in the construction of the current passage.
2. SugarCube creates a clone of the previous variable container (contains the current state of all currently known variables) and associates the clone with the current passage being shown.
I had some very big datamaps (like 50 values with other datamaps or arrays nested inside) defined from the very beginning of the game although they were empty, names with no values.
I redefined them as totally empty datamaps (no names) and introduced some checks so that an non-existant pair wouldn't cause an error. I had never thought that the big datamap could slow the game more than the extra ifs. Now the game plays faster than it ever has.
Gentlemen, I take off my hat to you.
The problem is that my game has nothing to do with the branching CYOA that Twine was designed for.
I must add that every single complication I introduced to the original mechanic I started writing almost one year ago was the result of a narrative requirement I understood. Like not having the same character in two places at the same time, or being able to notice stuff that happens in another room near you. Is there a way of tracking the location of 10 characters without a datamap containing the name of the character and the room they are in? I really feel that my engine can be made more efficient, but hardly simpler.
<<set $unclebob to 1>>
means unclebob is in room 1. So for 10 characters, that means all that's needed is 10 variables to track all their movements.
<<if $currentroom is 1 and $unclebob is 1>>"I'll be back"<</if>>
Dude, your game's gonna be AWESOME! Do you know when it'll be finished?
Oh, wow! It's gonna be awesome by then! Will you release a beta?