Placeholder Image

Subtitles section Play video

  • Playing Pokemon Together with Node.js - Samuel Agnew

  • Hey!.

  • OK.

  • Another fun fact about our next speaker: If you haven't seen his profile picture for the

  • conference, definitely check it out.

  • It's actually him playing onstage at metal fest in Peru, when he did a South American

  • tour with the thrash metal band.

  • Lots of talent.

  • So next we have playing Pokémon with Samuel Agnew.

  • Guess I should have checked this before.

  • I see someone coming forward.

  • [applause]

  • Is there any way I can get like something where I don't need to use my hands?

  • >> Unless I could, could, like, one-hand live code.

  • >> AUDIENCE: Technically you just did.

  • >> Yeah, I guess I did.

  • There's my talk.

  • Dang, though, so this thing is not a thing.

  • OK, I don't need to be coding until a couple minutes into my talk so I might as well get

  • started.

  • How's it going JSConf, a company called Twilio pays me to build goofy hacks and about them

  • and I flew in from New York City the other day, and speaking of JavaScript developers

  • from New York, I want to give a quick shout to by buddy speaking in the other track.

  • You should watch it on YouTube later because he also organization a meetup called Queens

  • JS which is one of my favorite ones and sometimes I convince my employer to give them money.

  • This talk is going to be more of a fun one than a serious.

  • It's the last session and I know towards the ends of conferences attention spans start

  • wane, so I figured what could be more fun than playing Pokémon with a bunch of JavaScript

  • developers.

  • I'm running Pokémon red version which is a game I played a ton as a kid.

  • And I have the Windows version of this emulator running, even though I'm on a Mac and the

  • reason for that is there are a lot of old game emulators where the Windows versions

  • of them have developer tools, because people still make real games for these old systems,

  • and for some reason or other, most of those developers use Windows, so one of the features

  • that this emulator has that I'm going to be using for my talk is scripting functionality

  • so we can run lui scripts and we can control the memory of the game and button input and

  • stuff like that.

  • I'm being mic'd up.

  • Cool. [laughter]

  • So what we're going to do is we're going to write a Lewis script that interacts with a

  • node.js express server sitting behind a Twilio phone number and I'm going to have you all

  • text a Twilio phone number to tell me what buttons to press in the game and the Node

  • app and the script are going to communicate with each other.

  • Testing, can you hear me?

  • AUDIENCE: Yes!

  • Sweet, awesome, so this might sound kind of familiar to to some of you.

  • If you about five years ago, there was a twitch.tv livestream but instead of a human being playing

  • it, it was everyone watching the stream typing in the chat which buttons would be pressed

  • and when you have 80,000 people playing the same game controlling it at the same time,

  • things get pretty interesting.

  • So when I found out that these emulators had scripting, I guess because I work for Twilio,

  • I was like, whoa, wouldn't it be cool if you could do that with text messages, too?

  • And I it turns the Lua scripting thing is really popular in the speed scripting community.

  • Where people try to write scripts to complete games in the most efficient way possible.

  • This documentation seems pretty bare boneses so I've actually been following this other

  • emulator's documentation.

  • Turns out all these old game console emulate y they have the exact same Lua API I guess

  • because they're all open source and once one implemented it the other ones were like, cool,

  • gonna copy and paste that.

  • You can do stuff like read and write bytes to the game's memory, like the RAM and ROM

  • and that kind of stuff.

  • I'm going to have this Twilio phone number set up so that I can programmatically control

  • T so whenever you send a text message to this phone number and it's a 760 phone number which

  • I think is an area code around here.

  • So whenever you send a text to that number Twilio is going to send a post address to

  • this address right here, which is basically a tunnel to a port on my local machine that

  • my Node express app is going to be listening on.

  • That app does not exist yet so we'll get to that later.

  • If you text this number right now, literally nothing will happen because it will be dropped

  • on the floor because the code doesn't exist.

  • I'll show it on the screen later so you don't have to copy it down right now.

  • Anyway, let's get into the basics of how to write code for this Game Boy emulator.

  • I'm going to do a Hello World thing, you might have seen on this, I have my Twitter handle

  • up on the Game Boy emulator.

  • My Twitter is sagnewshreds,

  • I'm going to say hello, JSConf with a smiley face, and I'm going to save that and I'm going

  • to stop this other script from happening.

  • And I'm going to go find this Lua script on my computer in my talks folder in the JSConf

  • folder and I'm going to run that and it says, hello, JSConf cool, we've run some Lua.

  • But it disappeared.

  • And the reason is it's only running once.

  • We can repeatedly print this on every frame if we want it to stay.

  • And for that we need to write an infinite loop.

  • Because infinite loops rule, right?

  • We write those all the time.

  • Because this emulator, the whole environment in there is single threaded this will actually

  • stop the game from even playing.

  • So this emu object gives you a function where you can control the frames so you can advance

  • to the next frame.

  • This way our infinite loop is pretty much taking over the run time of the game so that

  • each iteration of this loop is going to be one frame of the game.

  • So all this code will execute on each frame so I'm going to advance to the next frame

  • at the end of each loop and going to restart that and now the hello JSConf is going to

  • stay there.

  • Now I'm going to write some useful stuff.

  • So what we want to do is this Lua script is going to communicate with our Node.js stuff.

  • I know this is JSConf and I'm writing Lua.

  • I'm not much of a Lua developer.

  • I don't know how many of you in this room consider yourselves Lua developers, but I'm

  • not particularly.

  • So I'm going to write some code to communicate with that Node.js and we're going to do something

  • technologically advanced here.

  • Really complicated stuff.

  • We're going to communicate by reading and writing to text files.

  • Yeah, so on each frame I'm going to read from a file called button.txt, to see if a button

  • was pressed.

  • So I'm going to write some utility function, so I'm going to write a function that can

  • read a file and then I'm going to open that file.

  • If I can type correctly.

  • Cool.

  • So I'm going to open that file name with the read flag and then I'm going to check to see

  • if that file actually exists, so if it's nil, then I'm going to set the input to be that

  • file, and then I'm going to create a variable called content and read the contents of that

  • file into it.

  • And then I'm going to close the file, because you always gotta close something you open.

  • You gotta finish what you started, right?

  • And then I'm going to return the content of the file which should just be a string of

  • whatever was in the file.

  • And next I'm going to write a quick function to press a button in the game.

  • So this is going to take a button, just like the text of a button, like A, B, start, select,

  • up, down, something like that.

  • And the way the joy pad API works in this Lua scripting is that it takes a table of

  • buttons, like a key value kind of thing, like a JavaScript object or a Python dictionary

  • and it takes the button name and true or false for whether that button is being pressed or

  • not.

  • So I'm just going to create an input table here.

  • And empty one, and I'm going to set whatever button we're trying to press equal to true.

  • And then I'm going to call the joy pad.set function, and this is actually kind of interesting

  • right here.

  • One of the idiosyncrasies of this is there's only one or two controllers, but I guess because

  • they copy and pasted for the consoles, you still have to give it the button input.

  • So unless you're giving the link input, there's only one player, so player 1 is going to have

  • this input table and I'm going to go down to this infinite loop and we're going to say

  • for each frame of the game I'm going to check to see if there is anything in button.txt,

  • so I'm going to create a variable that is going to read the contents of button.txt and

  • if the button is nil.

  • Press the button, pretty simple, right?

  • So I'm going to put a message out to say I'm pressing the button.

  • As I said, I'm not much of a Lua developer, so Lua string concatenation is just two dots.

  • So if that looked a little funky to you, that's what that is, that is just string concatenation.

  • So I'm going to avoid duplicates like if you send A to the text message thing and then

  • it writes the button to that file, I just want to press the button once, I don't want

  • to keep pressing on each frame repeatedly.

  • Like if you want to press the button twice, you'll.

  • It's going to return nil and button is going to be nil, so this won't be executed, but

  • speaking of pressing buttons for multiple frames, that's another thing I want to address.

  • So you are all human beings and when you're playing a video game, you're not playing as

  • fast as machine would, so when you press a button on a Game Boy you're at least holding

  • the button down for a solid portion of a second.

  • So we're going to want to press it for a certain number of frames.

  • Let's say 5.

  • Which is still not a long time, but long enough for it to register and this is the syntax

  • for a foreloop in Lua.

  • But I want to make sure I advance the frame again after each iteration of the loop.

  • So we're done with the talk using a language no one writes, or at I guess some of you do.

  • I guess technically do.

  • Because I'm writing it right now.

  • But first I'm going to reload this Pokémon.lua script.

  • Now I'm going to write the letter A, capital letter A in this text file and if I didn't

  • mess anything up, when I go back to the emulator, it should be pretsing the A button and as

  • you see, it's on this menu screen, so if it works this should go to the screen where I

  • select a new game.

  • Pressing A. -- I mean I guess it said it was pressing A. Oh, there we go.

  • Maybe five frames wasn't enough, actually.

  • But we'll see.

  • So the Lua code works, that's great.

  • I'm glad to hear that.

  • Now I'm going to open up a saved state that I have, because later on once we're actually

  • playing this, I don't want to have us to sit through Professor Oak telling us all what

  • to do.

  • All right, time to go now, I'm going to write some JavaScript finally.

  • So I'm going to open a file called index.js and I'm going to build a quick express app

  • so for a lot of people who are already familiar with backend Node development this will seem

  • pretty straightforward for you for those of you who aren't familiar with backend node.js

  • development, I guess this will be a good little Kickstarter.

  • So first, going to require the FS module, because you know, writing to files, gotta

  • use the file system for that.

  • Also going to require express, because it is the web framework that I'm using, and I'm

  • going to grab body parser, because I'm going to need to deal with the body of a post request,

  • because when you send the text message, Twilio sends the post request representing the message

  • and I need to get stuff in the body of that post request to access what the text of that

  • message is.

  • So body.parser and now I need to use the Twilio API.

  • The Twilio node module and I'm going to grab the messaging response object from that so

  • this will generate the twiml for me.

  • Twiml being the Twilio SMS.

  • My web app is going to have to respond with these XML tags, particularly the messaging

  • response one, saying hey, respond to this message with a text message and no one wants

  • to write XML by hand, I don't so I'm going to do this.

  • Cool, I'm going to create my app object and I'm going to make an array of valid Game Boy

  • buttons that you can text.

  • They're also the start and select buttons on the Game Boy, but I'm not going to use

  • that one, because that opens up the opportunity for you all to troll me by spamming the start

  • menu and that's not fun, so I'm not going to let you do that, at all.

  • Next I want to make sure I'm using the body parsing middleware, can't forget that so when

  • I get the URL encoded post body I'll actually be able to use it.

  • Gonna write that real quick.

  • Cool.

  • Now we can get to the fun stuff.

  • Writing the post handler, so this will be a /sms route as you saw me write in my Twilio

  • function.

  • First time I'm going to do is create a new twiml messaging response object and then I'm

  • going to grab the button that you want me to press so I'm just going to assume whatever

  • text message you sent me is only going to be a Game Boy button and I'm going to grab

  • that from the request body.

  • This is going to look slightly confusing, because the inside of the body of the post

  • request, the value that I want is body with an upper case B because that's what Twilio

  • sends you as the actual text of the message.

  • It's called the message Body.

  • So I'm grabbing the body and I'm going to convert it to lower case so I can make this

  • case insensitive and also because I don't have to put the burden of you dealing with

  • your autocorrect and stuff.

  • We don't want to deal with that.

  • So going to convert that to lower case and then I'm going to see if what you texted me

  • is actually in our list of valid buttons that we want you to be able to text, so if you

  • text me start, not gonna get that.

  • So if you sent me a valid button, I'm going to add a message to this twiml objected and

  • this will be the text message that I sent to you in response and I'm going to say thanks

  • for playing Pokémon with me and if you have any questions I'm going to give you my Twitter

  • handle again, or my email address in case you want to send me some more longer-form

  • complaints about how I'm using semicolons and you hate that or something and I'm going

  • to send you a smiley face because I'm really happy you're all here.

  • So next I'm going to write this button to the text file to communicate with my Lua script,

  • but an interesting thing here is when you're trying to press the A or B button, it expects

  • it to be upper case, but if you're trying to press like up, down, left, right, start

  • or select, it expects it to be lower case, so slightly annoying, but we can deal with

  • that.

  • I'm going to say if you're trying to press A or B, going to throw that back to upper

  • case -- oh, no, I'm going to say if you're pressing A or B in this little "if" block

  • here then I'm going to set the button to upper case so then I'm going to actually press the

  • button by doing this super-complex writing to a text file.

  • So it's going to go to button.txt, I'm going to write that button to it and I'm going to

  • go to utf8 encoding and now if you text me something that's not a valid Game Boy button,