Text by the Book

As anyone who’s done so can attest, giving the user the power to enter text opens up a whole can of worms. Fortunately, the Playdate SDK includes a text entry keyboard, so I don’t have to start from scratch. It is also based on rotating tumblers so it fits Tally Pal’s theme (even if that means that “keyboard” is kind of a misnomer).

I spent a fair amount of time on this due to my tendency to try to break things while playtesting. Partly I think it’s my QA tendencies, but perhaps it’s also a way of procrastinating. After all, I can put off committing to an approach if I keep picking at the edge cases. Text entry in particular provides such a huge possibility space that trying to find out ways to break it is a pretty compelling exploration. It does give me robust results, though. Good thing I have such a small scope for this project.

The keyboard in action.
The “_” after “Apples” blinks to indicate that more text could be added.

For example, while adding in text entry doesn’t seem like a great deal of work, I’ve already established that I have to use the same font to display the title that the keyboard uses, or else some of the glyphs won’t match up (in a longer-term project I’d simply make a new font). I’ve also added a blinking cursor to the text entry field, a check to have the text scroll out from under the keyboard display if it gets too long, and feedback for indicating when the character limit is reached.

A critical thing to establish with any text entry is defining what exactly a user can enter. Are there any characters that don’t render properly, or wouldn’t make sense in context? How many characters should they be limited to entering, if at all? One trick I like to employ is to enter a row of “W”s to get the maximum possible width. That informed what my character limit should be. It’s unfortunate to have to limit titles to just 10 characters (in the future I may have it calculate the width of the text and cut off anything that would go off screen to be replaced by an ellipsis). Localization will not factor into this project, but if it did, translating into German generally gives the longest words in terms of characters. And those are just the considerations apart from whether the content of the text itself is appropriate, which could be a whole blog entry and more on its own.

On the opposite end of things: what happens when nothing is entered? In this case, it would produce an error whenever the title is loaded, so we can’t have that. My initial thought was to prevent the user from entering anything invisible, i.e. nothing at all or only space characters. Here’s the solution I use to validate that the string the user has entered is something visible, while still giving them the freedom to use spaces freely, presuming there are other characters in the string:

-- If the first character is a space
if string.sub(playdate.keyboard.text, 1, 1) == " " then
	-- check that at least one other character in the string is not a space
	for i = 2, (string.len(playdate.keyboard.text)), 1 do
		if string.sub(playdate.keyboard.text, i, i) ~= " " then
			titleValid = true
	-- or that the string is not empty
elseif playdate.keyboard.text ~= "" then
	titleValid = true

(I don’t know if I’ll ever get used to typing “~=” to mean “not equal to” in Lua. I keep reading it in my head as “sorta equal to”.) In the end, I decided to allow space characters. If it were, for example, an entry field for one’s handle in an online game, I would disallow it, but here it doesn’t really have a downside apart from looking odd, and I suppose the user should have the freedom to do that.

It’s compromise time indeed as I try to put a bow on Tally Pal. I hope to have a solid, if not too extravagant, project done before I start at my new job next week. This is a good, challenging exercise, but I look forward to being back in the more complex but familiar world of VR development.