Monday, March 7, 2011

If You Want Something Done

Sup guys, delta here. It's been a while since I wrote a blog post, so it's about time to get technical once more.


Visual novels, seen as computer programs, don't have a lot of "features" you really need to think about. There may be slight differences, but all in all they're really similar as far as user experience goes; and that is perfectly fine, since they are not wildly dissimilar things to begin with - "visual novel" already pretty much defines the experience. In fact, one reason you would use a pre-existing VN engine is that they come with the full feature set you would expect from the medium. VNs are not the most difficult things to program but in a field so narrow there is little reason to reinvent the wheel. However, that does not absolve a developer from thinking about what they are doing. A lot of design decisions in the VN user experience are like they are by convention, and convention are not necessarily right (or wrong) - if the developer decides that they don't want to live with the usual, they can and should do it the way they want regardless what the engine or convention says.

One of these features is "some way of rereading text you have already read". This has to be possible in some way, and there are indeed conventions about how to do that. The method I have seen in most VNs is to show a backlog in list form that you can scroll up or down, or page through. Ren'Py, the engine we are using, solves the problem in a different way, which is calls "rollback" (and the method described above is described as "readback" in contrast to that). Rollback lets you "roll back" the whole interpreter state to a previous point. This is definitely the technically superior method, and a lot harder to implement, and it's one of Ren'Py's selling points. The reader can not only read the prior text, but they also get context - the whole screen, with character expressions, sounds, animation, everything.

Now there is a problem with that - out of the box Ren'Py supports only this method, and developers want choices. The reason for this can be manifold; maybe they want an "authentic Japanese feel" to their game. Maybe there is some narrative reason for doing it a different way. And more importantly (for me), Ren'Py rolls back the entire interpreter state, discarding any player input that happened prior, including choices. This is where a design decision comes in - what does read/rollback actually mean? Ren'Py assumes that the engine is just a tool to display the game to the player and leave as much choice open to the reader as possible - a "reader application" as opposed to a designed experience. An argument frequently brought up in favor of rollback is "the reader can just save and restore the game, you surely are not not going to forbid that too?" In my opinion, that is not a valid argument. For starters, yes, a game designer may decide to indeed forbid what is called "save scumming" in more general video games. KS does not do this, but there may be narrative or other reasons that nobody has yet thought of for it (As an aside, KS also includes a tweaked save/load system, because by default Ren'Py works with a "slot" system directly lifted from Japanese VNs, which in turn lifted it from battery-backed NES games. Not something entirely contemporary, so KS uses a system that Source games ca. 2004 use - hooray for at least living in this century)

What it comes down to is this: I consider the text backlog in KS a form of protagonist memory, and memory is immutable. When you roll back, you don't "roll back an interpreter", you retread what you have already seen. This implies not being able to redo choices. Sure, you can still save and reload, but saving and reloading is a far more conscious, weighty thing, a lot less casual than just scrolling your mouse wheel.

Whatever the reason is, there is no reason to restrict the game developer just because something is "inherently superior". It's like saying that you should not make a film in black and white when color is available. Restricting the player interaction can be a design goal, for whatever reason, and if the developer wants to do that they should be able to. And while Ren'Py does not offer any other method of backlogging, it is open and flexible enough to allow custom solutions.

Act 1 of KS included a custom implementation of readback of my own design. It still allowed rollback (because it is indeed a nice thing to have), but it blocked rollback after choice points, yo you could never roll back beyond a choice. That way, you could not change a choice you had previously made, and if you wanted to access the text displayed before rollback was blocked, you had readback available. I never found this completely satisfactory, because it was an obvious crutch. I felt that the version I want was full rollback without the ability to retake choices. So I went and did that.

The solution is slightly elaborate and I won't go into all details here. I'll just say that what makes this hard is that Ren'Py has no concept of a "per-playthrough" memory independent of rollback, which is exactly what this is all about. It just has the "store" (which stores per-playthrough data, but also gets completely rolled back), and "persistent" (which does not get rolled back, but is global for an installation of a game). I ended up generating a unique ID at the beginning of each playthrough and save it in the store, then using this ID as the index in a database of values that is stored in persistent. Not actually all that complicated, but it was still something I had to think up and implement. It may not even end up being the thing KS eventually ships with, but it had to be done to be evaluated. So the lesson here and the reason I am writing this up is, think about what you want and at least try it out. Don't let yourself be limited from the start by what the engine or convention says, even if it's just in a small way that may not matter to anyone but you. Don't do something because everyone's doing it, but be ready to pick and choose the best from conflicting approaches. And in the end, maybe you will come up with something that is "better" or at least more fitting than either.

At least until everyone dislikes it and it's back to the drawing board.

P.S. Aura was faster with the art but climatic wanted to be part of it as well. So here's his effort as a reward for reading all the way to the end.

— delta

» Discuss this post on the forums