Placeholder Image

字幕列表 影片播放

  • 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,

  • I'm going to respond with a message asking you to send me a valid Game Boy button.

  • Because you know, you might make a typo or something, or maybe you want to comment on

  • my hair or something, I'm just going to say hey, please text me a valid Game Boy button.

  • No smiley face on that one.

  • [laughter] And now I'm going to deal with actually responding

  • to this HTTP request, so I'm going to make sure that it's a 200 response, because if

  • I'm actually getting the text message and stuff, just going to give it 200, let's go

  • with that.

  • I'm going to set the content type to be text/xml, and I'm just going to send the twiml object

  • a stringified version of it, so this is just going to be the xml that it generates, which

  • is just going to be the text message I want to send back.

  • Should be about done now, make sure this is listening, I'm going to go to port 3000, console.log,

  • express app listening on port 3000, going to put a bunch of exclamation points.

  • That should be all the JavaScript I have to write before I open this up for you to all

  • play Pokémon with me, though, I want to make sure I don't have errors.

  • I'm going to run this and I'm going to text this, if you did take that number down, I

  • guess you can play it.

  • yeah, someone pressed up, someone lent left.

  • OK, so people are actually -- it looks like the code is working at this point, because

  • I'm not getting any errors.

  • And you know what that means?

  • That means we get to play Pokémon together, so who wants to play Pokémon until we run

  • out of time.

  • So I'm going to need you to take your phones out, and send a message to this number, 760492-6659,

  • and let's see if we can go select a starter Pokémon and battle our rival.

  • If we can get past that, I'll be pretty stoked.

  • So want to go up and down, want to get out of mom's house, because we're a big kid now.

  • All right, it's sagnews house, that's my house.

  • We want to go up and to the right.

  • All right, we want to go right.

  • Let's do that.

  • Isn't it great that I didn't let anyone press start because we would just be standing still

  • right now.

  • Gotta get in the tall grass so Professor Oak will see us, be like.

  • All right, so you want to go right and up.

  • Let's do it.

  • Let's do it.

  • Right?

  • I believe in you.

  • I believe that this community can stick together and we can defeat.

  • Yes.

  • OK.

  • All right, Oak is looking out for us, now let's just span A and B so we can get past

  • this guy talking to us, this science guy, Professor Oak the science guy.

  • Cool we're on our way to his lab.

  • Gonna get our first Pokémon, I'm excited for our adventure, we don't even have to write

  • up, the game scripts that for you.

  • As you can see, I named my rival fool.

  • Because it's customary to name your rival will something not nice and I think he's kind

  • of a fool.

  • When I was young I was a serious Pokémon trainer, cool.

  • I'm going to span 3 so we don't accidentally spark a conversation with him.

  • All right, so now we want to go down and right once we're done this.

  • All right, let's go right.

  • Let's do it.

  • We got this.

  • So we're going to go right.

  • Oh, I believe in us.

  • I believe in us.

  • I believe in us.

  • I actually just copied right and I'm just copying and pasting it now and sending it

  • in a text message.

  • Now we want to go up and press A. Which Pokémon should we select?

  • Well, at least we're going to be able to fight against charm it's

  • probably better.

  • Oh, A, AI, OK.

  • J, P, -- or JZ OK, cool, really creative nickname, extremely creative nickname and this fool

  • is going to take charm ander, sow now we have to battle him.

  • And what's our strategy going to be for this battle?

  • Are we just going to repeatedly tackle?

  • You want to use growl at all?

  • >> Bulbasaur, yeah, I think Charmander has tail whip.

  • Oh, no, we hit growl.

  • We're growling at each other.

  • Oh, yeah, we're going to tackle, tackle him now.

  • Not a very strong tackle, probably.

  • Oh, no.

  • We're -- if we lose to this Charmander, what does that say about the JavaScript community?

  • Oh, he's scratching us.

  • I think we can do this.

  • I should have grabbed this possession and then saved after that.

  • But that would have been cheating.

  • We don't need to do that.

  • We can do this ourselves.

  • As long as we spam A and get lucky.

  • I think we're going to win.

  • Uh-oh.

  • We've got to press up, like, once.

  • Oh, no.

  • At least the Charmander is going to be really weak.

  • We're just growling at each other.

  • This is like an intimidation match right here.

  • I still have faith in us.

  • I think we can -- all right, we hit tackle.

  • We hit tackle.

  • Oh, no, critical hit uh-oh.

  • That ain't good.

  • Uh-oh, I think we can do it, though, we're at least making him weaker.

  • All right, we're tackling again.

  • Charmander is growling at us, getting weaker as time goes by, but so is Charmander.

  • Oh, no!

  • We're doing one damage to each other.

  • Growl can't make him any weaker.

  • No.

  • Oh, no.

  • All right, nothing happened.

  • All right.

  • We got growl.

  • If nobody ever presses up or down again, then I think we got this.

  • I think we can win.

  • Oh, no!

  • You know, I still believe in us.

  • Oh, no!

  • You know, if we get a critical hit, we can make this happen.

  • We can win.

  • Oh!

  • It's still possible.

  • It's still possible!

  • Oh, no!

  • OK.

  • All right.

  • You know, I'm never -- I'm not going to give up on us.

  • I'm not going to give up.

  • That is unfortunate that we missed.

  • And he's still growling.

  • OK, come on, critical hit.

  • No.

  • All right.

  • No.

  • Well, well, we lost -- I guess we're the fools now.

  • Oh, man.

  • Well, whoever shouted Charmander should be happy now, because at least you know Charmander

  • is the best choice.

  • And that's my favorite line, gramp, smell you later.

  • But I guess we lost that first battle, but I have faith we can grow as Pokémon trainers,

  • and learn, because you know, going to conferences is all about learning and improving and stuff,

  • right, so we're going to become better Pokémon trainers yet, just you wait and see.

  • With that said I think that's all I have.

  • My name is Sam Agnew, I'm a developer evangelist at Twilio.

  • I'll be at the pool and the after party later.

  • Have a good rest of JSConf.

  • [applause]

  • And thank you for playing Pokémon with me.

Playing Pokemon Together with Node.js - Samuel Agnew

字幕與單字

單字即點即查 點擊單字可以查詢單字解釋

A2 初級

用Node.js一起玩口袋妖怪--塞繆爾-阿格紐--美國2019年JSConf。 (Playing Pokemon Together With Node.js - Samuel Agnew - JSConf US 2019)

  • 8 0
    林宜悉 發佈於 2021 年 01 月 14 日
影片單字