This year the
Global Game Jam was scheduled at the beginning of February;
so since I had recently
been gifted some additional free time,
I decided to take a road trip over to Cleveland, Ohio to help out at their site. While the
attendees made
a bunch of cool games,
we made sure they were well-fed and offered help and advice when needed. In the in-between times,
I progressed further on my SMS Beholder High project, getting close to a final form.
It had been a while since my last foray into SMS, so I was eager to make sure I could still
leverage
Twilio easily. After a bit of
trial and error with their Ruby API, I realized I only needed to use it if I wanted to start a SMS
conversation. Since I only wanted to respond, I could stick to using Sinatra and point Twilio to
my simple web server:
Twilio messaging setup for the number
Luckily their TwiML™️ schema includes a way to
reference MMS media by URL,
so I had pictures going to phones pretty quickly:
post'/sms'dosource=params['From']ifplayer_data.key?(source)puts"Player #{source} has data #{player_data[source]}"player_data[source]['old_state']=player_data[source]['state']player_data[source]=process_misc(params,player_data[source])player_data[source]=process_input(params,player_data[source])elseputs"Player #{source} is a new player!"player_data[source]={}player_data[source]['old_state']=''player_data[source]['state']=params['SkipToState']||'SPLASH'player_data[source]=process_misc(params,player_data[source])endresponse_body=process_output(player_data[source])response_old_state=player_data[source]['old_state']response_state=player_data[source]['state']response='<?xml version="1.0" encoding="UTF-8"?>'\'<Response>'\' <Message>'\" <Body>#{response_body}</Body>"unlessGameStates.same_image?(response_old_state,response_state)puts"New image! #{response_state}"response+=' <Media>https://301days.com/assets/beholder_high/'\"#{response_state}.png</Media>"endresponse+=' </Message>'\'</Response>'putsresponseresponseend
Yes, I did put all of the images in
a handy directory of this site,
which seemed like the easiest thing to do. And yes, I uploaded them by hand instead of adding it
to the CI. And yes, the XML is assembled by hand; it’s simple enough that I didn’t see the need
to call Twilio’s methods to assemble it, so I get away with
one fewer dependency.
Speaking of expediency, SMS is kind of slow and expensive, so how can we optimize the
interactions?
The first thing I did was to prevent the same image from being sent twice in a row. You may have
noticed the call to GameStates.same_image? above. My initial implementation of that method was
a little kludgy, since a given state didn’t necessarily include all of the image parameters, but
it worked:
defself.same_image?(state1,state2)puts"Comparing states #{state1} and #{state2}..."returnfalseif@states[state1].nil?||@states[state2].nil?@states[state1].fetch('bg',nil)==@states[state2].fetch('bg',nil)&&@states[state1].fetch('beholder',nil)==@states[state2].fetch('beholder',nil)&&@states[state1].fetch('beholderPos',nil)==@states[state2].fetch('beholderPos',nil)&&@states[state1].fetch('beholderExp',nil)==@states[state2].fetch('beholderExp',nil)end
While testing, sending a new message to trigger each state got tiring quickly. If there’s no
response required from the player, why not just send the next piece of text?
Even including multiple messages in the same XML payload, they are delivered in apparently random
order, subject to the vagaries of the path from Twilio to my phone. Multiple messages at once
is a no-go.
If I could really only send one message, at least I could include multiple game states where it
made sense. Until we exceed 300 characters, or need input, or have a new image to show, we just
keep adding to the message body:
Not pretty, but it worked. I may do some restructuring around this way of handling the messages,
and possibly convert to a more serverless approach to reduce infrastructure cost. But for now, I
finally have a phone number to share with friends so they can play.