As of October 1, 2023, LINE has been rebranded as LY Corporation. Visit the new blog of LY Corporation here: LY Corporation Tech Blog

Blog


LIFF + TIC-80

Hello, this is Seisuke. I work at LINE Fukuoka as an engineer for LINE app for Android. Our office held a hackathon for LINERs in November 2018, at which I had a chance to try out TIC-80, a fantasy console, with LIFF. I wanted to share some of the lessons I learned through the event.

LINE Fukuoka annually holds a hackathon for LINERs. The way it works is this; someone with an idea submits a proposal, and then four to five developers who are interested in a particular idea make up a team to implement the idea. Hackathons are usually held for a couple of days. I consider hackathons are great, because it gives you an opportunity to try out new technology, especially the ones that are not directly related to your work. My proposal for the hackathon was running TIC-80 with LIFF, using WebAssembly.

What are TIC-80 and Fantasy Console?

TIC-80 is a fantasy console written in C. A similar kind is pyxel, written in Python. Have you ever thought why it's called Fantasy Console? The word "fantasy" implies something virtual. Here, we'll consider the real as personal computers often used at home with a single tasking OS like MSX or MS-DOS. Although I am not of that generation, there are many programmers who stepped into this world after making games in BASIC on such computers.

Fantasy Console is not for emulating real computers. Rather, its purpose lies in providing an environment to help focus on developing games. The environment is setup with limitations on resolution, display color and music; and comes with API, code editor, map editor and music editor. Having the environment both for game playing and developing enables you to see in what language and with what materials the game you are playing is made.

Usually, Lua is the language for TIC-80 programs, but you can also write games in other languages such as JavaScript and Python.

Here is a part of the TIC-80 specification from their website. See how the specifications are limited.

  • Display: 240x136 pixels
  • Sprites: 256 8x8 foreground sprites and 256 8x8 background tiles 
  • Sound: 4 channels with 16 waveforms
  • Code size: Up to 64KB

Due to the minimal specification, games created for TIC-80 — they call it carts or cartridges — are really small and thus easy to share. Which is good for us, because we can run them on LIFF, and share with LINE friends to play a cart that you make yourself. This use case seemed an ideal case for a fantasy console, so was chosen as my proposal for the hackathon.

TIC-80 on LIFF Overview

We made a basic web app with Sinatra and serviced it on Heroku. We used TIC-80 console to upload our cart. Once uploaded, a download URL is displayed in a chat window. By sharing the link with a friend, your friend can also play the game as a LIFF app on LINE.

Running TIC-80 on LIFF

LIFF (LINE Front-end Framework) is a web app platform that runs on LINE the messenger app, which can be launched over a chat window and make use of LINE user IDs. 

Since TIC-80 can be compiled into WebAssembly (WASM), we can run TIC-80 on web browsers, but the browsers on mobile devices are not in the support scope. It's better to play with a game pad or keyboard, which brings us to take the following into account to guarantee smooth operation of TIC-80 on LIFF.    

Display width

When you run WASM, the display is drawn on a designated canvas. It seems that the display size is set by default to that of the original binary. TIC-80 allows you to change the size of a cell; we set the width to 512px (240x2 plus margin for both sides, 16x2), and the view port to 512px, as below:

<meta name="viewport" content="width=512, user-scalable=0">

A better practice would be to remove all the margins set by TIC-80 and set the styles with CSS instead.

Implementing the game pad

TIC-80 probably comes with a virtual game pad, but it's set not to run on WebAssembly. Instead of searching for a way to run it on WebAssembly, we developed a virtual game pad with JavaScript to play the game on LIFF.

window.dispatchEvent(new KeyboardEvent(name,{'keyCode':code}));

Dispatching events with the code like above works fine; a key input gets delivered to TIC-80. But, we need to take care of long taps as well as concurrent key taps. Well, we'd need to take care of light presses as well but we decided to skip it for this hackathon.

Keyboard inputs

TIC-80 processes keyboard inputs with SDL2 like many other open source multi-platform games do. This applies for game pad inputs too. TIC-80 presumes that a frame is allocated for displaying a keyboard and another for hiding the keyboard. Some virtual keyboards like the one on iPhones are shown and hidden instantly, which might not display the keyboard at all. If the keyboard is shown in between frames, only then we would be able to use the keyboard. To resolve this issue, we made modifications in TIC-80 itself. 

Handling the space key

If the space key is tapped, the LIFF app would automatically scroll down from the chat window. To avoid this, we need to block the space key from the windowobject in our JavaScript code.

WebAssembly and JavaScript

With WebAssembly, C functions and JavaScript methods can interact with each other. Our project only required calling JavaScript from C. We used EM_JS to write inline JavaScript code in C. As long as there are global JavaScript methods in LIFF web app, they can be called from C.

Uploading carts are done using a TIC-80 command. All there is to it is calling server APIs we implemented, with JavaScript. We used XMLHttpRequest, and if the call was successful, the URL to download the game is returned. Messages are displayed on a user's chat window by using LIFF's features with callback functions. We implemented the part up to calling callback functions with inline JavaScript with WebAssmebly and the message displaying in our web app.

What lies ahead

Having only two days was quite a pressure. We aimed to implement the most basic features. It'd be fun to develop on from what we'd developed, may be with the ideas we had to leave behind, such as recording scores or even ranking using a LINE user ID. We could acquire a user's LINE ID with LIFF and pass it to TIC-80 as a parameter on a command-line. We could provide an API for game creators to call and store the ranking data on a game server. 

I'd recommend children who are interested in programming to try out fantasy consoles after getting their hands on visual programming with Scratch. Language support and minimized versions would surely be helpful. I myself have been trying adding various features on TIC-80, such as a Japanese dot font which I was able to implement to a certain level thanks to it's basic UI structure, but adding something as an addon is quite difficult.

Although I landed on TIC-80, my original idea for this hackathon was to use Kotlin/Native and Web Assmebly. Perhaps I'll give a go at making an ideal fantasy console with Kotlin/Native.