All right, everybody.
Good evening, good morning, good afternoon,
depending on where you are in the world.
This is CS50 on Twitch.
And my name is Colton Ogden.
Today we're going to talk about a classic game that was played probably
by many of you growing up in elementary school, or maybe
beyond elementary school.
It's a classic pen and paper game called "Hangman."
It's a very elementary game.
But it will allow us to--
if you're new to Love 2d, new to game programming,
it'll allow us to explore some simple game programming concepts.
It will allow us to look at some drawing stuff we haven't really done yet,
some, like, sort of vector style drawing,
which we'll take a look at in a little bit.
And it'll let us work with sort of textual style input
and allow us to segue thereafter into a game suggested
by Asli, who may or may not be in the stream yet, a typing style game.
So thanks, everybody who is in the chat now.
I'm going to shout out a few folks.
We have some regulars, consistent crew.
Bhavik_Knight, Whipstreak23, Bella_kirs, Raj49274.
We have-- Damnerel was here last time, I remember.
Shout outs to Damnerel.
And Brenda, of course, Realcuriouskiwi.
Hello, Brenda.
Good to have you.
I know that it's early where Brenda is in New Zealand.
So shout outs to New Zealand.
Bhavik_Knight says, how is everybody doing?
Welcome, first timers, and hi, all regulars and Colton.
Good to have you with us Bhavik.
Good to see you, as always.
Who else do we have here?
We have somebody's name who I can't read very well.
Winlogon says hi.
Winlogon was here last time.
Thank you for joining us again.
Andre.
Good to see you, Andre.
An awesome idea.
How about a black whiteboard?
Ooh, we don't have any black whiteboards.
We have white whiteboards I did not bring one in here,
because I did no think to draw on one.
But I can maybe whip out draw.cs50.io.
Damnerel, better name, my name.
Robert_Springer.
Hi, Robert.
Good to have you.
I think it's a revolutionary idea.
We could use some kind of white material that crumbles and sticks
onto this black whiteboard.
This is revolutionary, Andre.
You should patent this idea.
Adamantine by apartheid.
What's good, everybody?
Good to have you with us Adamantine.
Adam for short.
And Winlogon says it's a pleasure.
I'm going to transition to my screen here,
after I just prepare it really fast.
Bada bing, bada boom.
So if you're unfamiliar with Love2d, this is the website
that you can go to, love2d.org.
It's something that we've done on stream many times so far.
It's what I use to teach in my games course.
It's an awesome 2D framework for getting started with game development.
And it is free.
And it is cross-platform.
So definitely check it out, if you are not already using Love.
And it uses a language called Lua, which we'll take a look at.
I'll assume that there was probably some folks that are brand new.
But a lot of the people that are in the stream already
are very familiar with love and Lua because they use it
in a lot of the streams.
But I will go somewhat slow.
I will still explain some of the many things that I do,
in case you are brand new and you want to know what I'm doing.
I'm going to create a repo.
I have prepared this tab in advance.
It's going to be called hangman-stream.
So let me go ahead and do that.
This is GitHub.
If you're unfamiliar with GitHub, it's an awesome website.
Definitely check out.
We have a stream on GitHub, a prior stream on our YouTube channel.
And we have--
Brian Yu made a excellent GitHub seminar.
Go on the CS50 YouTube channel and type in "Git" or "GitHub."
You should see Brian's GitHub seminar.
And also, his first lecture of his web course
goes into tremendous detail on git.
It's an excellent lecture.
We're not going to go into that in this stream,
just because it will take a little while if we do so.
But now there is a repo called github.com slash coltonoscopy--
that's my GitHub username-- slash hangman dash stream.
That's where I'm going to push today's code so that you can mess around
with it once it's all finished, get a sense of what it looks like on your own
and maybe add your own features, which would be always awesome.
I'm going to clear this.
I'm going to first--
very first step--
I need to actually make the folder in which I'm going to have my code.
So I have a Streams folder, which I've been putting all the stream code bases
that we've done so far.
I'm just going to call this one Hangman.
And then I'm going to open this in a text editor called vscode.
That is my text editor.
It is a awesome free text editor.
You can get this for any major operating system.
Just type in vscode in Google, and you will find a download link.
It is taking a second to open for some reason, ironically.
I'm going to close it.
I just updated it.
So it might be having a slight little hiccup.
Oh, you know what it might be, because there are no files.
Maybe that's why.
There we go.
OK.
Yeah.
See, I just updated to the November 2018 version.
So it was having a little bit of a hiccup.
New file, main dot lua.
Main dot lua is the starting point for every Love2d application.
So I created a main dot lua, in which I'm going to put some comments.
Dash dash square brackets is how you make a comment in Lua.
And then it goes until the second closing set of square brackets.
We're going to call this Hangman.
I'm the author, and this is my email address.
And I'm going to save this.
I'm going to go to my terminal.
Make sure I'm in the right place, which I am.
Go to hangman ls main dot lua.
It's right there.
If you're unfamiliar with the command line,
don't need to worry too much about all this stuff.
If you are unfamiliar with the command line
and you want to learn some more stuff about it,
we did a stream on Linux commands with Nick Wong, which was awesome.
So definitely check that out.
I'm going to get init.
Git remote at origin, the URL to my stream.
Again, no need to worry about this too much.
But if you are familiar with git, this should all make sense to you.
Git-- I'm going to add everything.
And this is bad practice, but that's OK.
I want to say initial commit.
And then I'm going to push this code to GitHub.
Oh, did I miss something?
Git remote at origin.
Oh, right.
Git push upstream origin master.
There we go.
And there we go.
So it's pushing all the code.
So now if I go back to GitHub--
and this isn't terribly important that you know this--
but if I refresh, now the repo has the main dot lua that I just added,
and I will push the rest of it later on as we continue.
All right, so let me make sure I'm all caught up with the chat.
I have a few messages that just popped in here.
So hello, CS50.
So Hsin_Wen_Chang.
Thank you for joining, Hsin Wen.
Good to have you.
Unfamiliar says, I am unfamiliar.
Adamantine says, I'm about to start that game course, Colton.
Ooh, awesome.
Definitely keep me up to speed on how you're doing with it.
We are about to start the next iteration of it for the Extension School.
So we're getting all of that set up currently.
Sashikant32-- hey, everybody.
Hello, Sashikant.
Asli, Nuwanda3333-- hi, everybody.
Hi, Asli.
Good to have you with us.
Asli is the inspiration for this stream and for the preceding stream, which
is going to be a typing game of some sort
that I haven't decided on the details of just yet.
But definitely check that one out.
This will sort of segue us into that and sort of scaffold us up there.
Brenda tossed in a link to the chat there.
So Brian's Git Seminar, awesome seminar.
Check that out, if you're unfamiliar with git.
Super good skill to have.
Bella_kirs is saying hi to everybody.
Bhavik is saying hi to everybody.
Forsunlight-- hi, Colton.
The regulars and newcomers, hello, thank you very much for joining.
Hello, Fatma.
Do you use SSH or HTTPS to clone a repo?
I believe I used HTTPS.
Yeah, HTTPS is what I typically use.
Forsunlight is saying hello to everybody.
Whipstreak-- not me.
I'm a regular.
Yes, Whipstreak23, I believe that--
Nate.
If I'm not mistaken, it's Nate, correct?
Definitely correct me if I'm wrong.
I do believe that that is correct.
I apologize if that is incorrect.
Got those meat boy emojis in the stream there.
Guys, I'm on my phone having internet issues.
I'll be away from chat to be able to watch.
If I don't reply, I didn't see it.
Oh, that's sad.
But definitely thanks for tuning in either way on the phone.
Appreciate the dedication.
Set upstream first then push works as normal?
Yeah, I forgot the dash u flag.
Beginner mistake.
Sorry to bring up GitHub, or Git, really, but I'm just curious.
Colton, have you ever used GitHub or any other git-based service
with Unity projects?
There are typically many autogenerated text files, the object metafiles,
et cetera, which can be quite annoying when there's differences to resolve.
What do you do in those cases?
Yes, I do use git for Unity projects.
And we do it in the games course.
You have to make sure-- there's a setting in Unity
where you have to export all of the metafiles as text files.
And that seems to fix the issue.
We use it without any hiccups in the games course.
We used GitHub.
Students cloned to the projects.
And they used GitHub Classroom to push their changes.
So it's definitely possible.
There's just that one setting that you need to enable.
But once you do that, everything seems to work very smoothly.
You do need the metafiles, though.
They are important.
If you don't keep the metafiles, a lot of the time, it will cause issues.
But yeah, cool.
So Hangman.
Why don't we take a look real quick at a Google image?
So somewhat not kid-friendly, but still somewhat kid-friendly.
I mean, this is something that elementary school kids are doing.
Or at least when I was in elementary school,
this was something elementary school kids were doing.
And we'll ignore the gallows for our example,
and we'll just use a stick figure.
But the gist of Hangman is somebody chooses a word of x characters long.
So in this case, four characters.
Hangman is actually the word that they chose.
And it initially starts with all of these letters being blank.
And the other person, the person who did not
choose the word, who has to guess the word,
gets to choose one letter at a time.
So in this case, somebody chose H-A-N-G and M, or H-A-N and G.
And there happens to be two A's and two N's in the word.
And they did not yet choose the M. But it
looks like they lost, because their stick figure is currently fully fleshed
out.
You see, the gallows starts off looking like this,
where there is no stick figure.
And for each letter incorrectly guessed--
if someone were to say/guess Z for this word,
it's not part of the word hangman--
you start drawing a stick figure.
So you start with the head, then the body, then an arm, then another arm,
then a leg, and then the last leg.
And then once that's happened, once the stick figure is fully drawn out
and they've guessed--
what is that, one, two, three, four, five-- six incorrect letters,
the game is lost.
They've lost.
But if they can guess the full word, if they
can guess all the letters that make up the full word,
and complete the word before their stick figure is completely drawn,
they actually win the game.
So it's a very simple game.
It's made with very simple graphics.
As you can probably guess, most of what we're going to be doing today
involves just lines and circles--
in this case, just a circle and then some lines--
some lines to underline the letters here,
and then we just need to render the letters of the word
that we're trying to spell out.
And we'll do it a little bit fancier than this too.
We're going to want to make sure that we see all the letters that
have been guessed incorrectly, so that we don't keep guessing
and we don't forget letters and incorrectly guess the same letter
over and over again.
But our game, in the end, is going to look very similar to this,
albeit ours will probably be a black window with white text
and white images, white lines and circles.
But it'll basically just be a slightly more sophisticated version
of this picture here.
So enough of that.
And again, we're going to avoid something like the gallows.
We don't need to include that in our example.
We'll just have a stick figure, and it'll be Hangman in spirit,
much less in actual implementation.
So in my text editor here, I already loaded up my project.
I'm going to get rid of the file inspector.
I don't know if I'll necessarily go super in-depth in the engineering
aspect of this, because it's a pretty simple game.
We'll see as we go along.
I actually don't have a particular game plan in mind.
I know the bits and pieces.
I have no code here off to the side.
We're going to do this completely from scratch and figure it out all together.
And maybe some of you in the chat have ideas that you would like to provide.
Definitely do so, and we can integrate that into the game as we go along.
OK, Adamantine says, looking at the Love2d downloads,
which version should I be using?
I'm using version 11.1 in this example.
My course uses version 0.10.
So if you're taking the GD50 course online, use the 0.10.2.
Don't use 11.1.
The code is made for 0.10.
But for today's example right here, we're just using 11.1.
Jabkochason-- I always fail at pronouncing that name, or Jabkochason.
Hey, guys.
It's been a while since I watched the CS50 stream.
How's it going?
It's going very well.
I do remember seeing your username from prior streams.
So thanks for joining us again.
We're making a Hangman game.
So in every Love2d application, there's a few set functions
that are sort of mandatory.
And I'm going to just write those out here,
before we get into any implementation details.
Load, update, draw.
We will need keypressed.
And these all are functions that are provided to you by the Love2d library,
and that's why they have the love dot sort of namespace
in front of the function.
So these are all functions that the Love2d framework is going to look for.
It's going to look for anything within the love dot.
It's going to look for specific words--
load, update, keypressed, and draw-- and sort of call them when it needs to.
It's going to figure out, OK, I need to call load at the beginning of the game
when it first loads up and do some setup.
I need to call update every frame.
And update gets some delta time passed into it.
And our game is not timed.
So we're actually not going to be really using delta time today.
It's all going to be very sort of key handling-based.
We're going to press a key, and stuff's going to happen.
But nothing's going to really happen asynchronously or synchronously.
It's not going to happen along any particular time frame
over a span of seconds or milliseconds.
It's going to be very instantaneous.
Love dot keypressed is a function that we're going to be using a lot today.
Because every single piece of input that we do today
is going to be less holding a key down or moving a mouse,
and much more akin to just pressing a key and having something
happen right away.
So waiting for that key to happen, that keypress to happen,
and then responding with some sort of code.
And then draw, of course.
You can't really have much of any game without some sort of rendering code.
And the love dot draw function does all of that.
It keeps all of our code for actually drawing
the shapes, the images, the text--
all the things that we're going to need for today's example.
Everything goes into the draw function that should be drawn to the screen.
Damnerel says Vim or Emacs?
I use neither.
Emacs is very popular amongst the closure community and Lisp communities.
And Vim is much more popular, I think, outside of that--
everywhere else, for folks who like CLI-based editors.
So Vim is probably much more popular.
I plan to do game dev using JS and HTML canvasses, Jabkochason.
No concrete plans at the moment.
No.
Maybe in the future, we can explore something like that.
There was a library called phasor that I was very interested in last year,
actually, while I was developing GD50.
And it was in a state of flux because it was going from 2 to 3,
and the documentation was very bad at the time.
And I'm not actually sure how the documentation looks now.
If the documentation gets to be in a stable form such
that we could easily look things up and make the same kind of stuff
we can make in Love2d, then I would say it would be worth exploring.
But at the moment, I'm not sure.
Bhavik_Knight says Vim.
Yeah, Bhavik_Knight is not shy at all when it
comes to professing his love for Vim.
That much is sure from prior streams.
So yeah, these are the Love functions.
We've seen these a bunch of times.
But if you're brand new, these might be new to you.
So that's why the explanation, I think, was merited there.
Let's just do some basic stuff.
So let's go ahead, and actually, I think we're
going to avoid using push today, which is a library that we use traditionally
for all the games that we make, just to make it look retro.
We're just going to use basic line drawing circles and text.
And we're going to do it just in our native resolution, whatever
our screen is.
So if we decide we want to do it in 1280 by 720,
the game itself will be in 1280 by 720, and the window will match that.
The window and the game will be 1280 by 720.
In prior streams, we've done this sort of virtual retro resolution
thing, where we've taken a 720p window, but we've made our game actually
like 240 pixels tall-ish.
And that makes our game look like it's a retro, very retro,
but it stretches to fit our 720p window.
So we get this nice, large window, but a really cool, crisp old resolution,
old retro style super Nintendo, NES resolution.
We're not going to do that today.
Just to complicate things, we're just going to keep it very simple.
We're just going to do 1280 by 720.
So I'm going to declare a couple of constants at the top of my file--
window width and window height, 1280 by 720.
This will be the resolution of our window.
And in love dot load, I'm going to say love dot window dot--
and I always sort of forget what this is--
set mode.
And with it, height.
So window width and window height.
And then it can take in a set of flags for whether we
want it to be full screen, whether we want
to use vertical sync on our monitor.
We're not going to worry about that.
I'm just going to say window width and window height.
So actually, if I run this, it should-- yep, it creates a 1280 by 720p window.
My computer is in 720p at the moment.
So it fits the entire screen.
I'm going to say if key is equal to escape,
then love dot events dot quit here in my love dot keypressed function.
So love dot keypressed just waits for any key to be pressed on your keyboard.
And you can specify logic within the function
to tell love what to do when you press that key.
So in this case, I said if the key--
which is being passed into the function--
is literally equal to the string "escape,"
then I'm going to call a function called love dot event dot quit,
which just means quit the application.
So now if I run this application, I hit Escape on my keyboard.
The window itself closes.
I don't need to hit Command Q or Control Q. If you're on a Windows platform,
I don't need to click the red circle on the top left or the x on the top right,
if I'm on a Windows machine.
Just super easy to just keep my hands on the keyboard and not
really worry about the mouse as much.
Let me make sure I'm up to speed with the chat here.
So Aizotv, thank you for joining us.
Adamantine says I use Microsoft Word.
I would recommend against Microsoft Word, unless you're joking.
But Microsoft Word is going to make your development life a little bit tricky,
because by default, doc files have some embedded xml and some other stuff.
I think you can theoretically use it if you keep everything in plain text mode.
But definitely, if you are using MS Word,
try to venture into using something like vscode, or atom, or Sublime Text.
Even Wordpad is a better choice, because there's no formatting,
there's no hidden elements-- xml, any fanciness that will screw up your file.
Rich Text Format.
If you're using an RTF editor, you don't want to do that.
Because source code is meant to just be literally the bytes that you see here.
Doing anything that uses rich text or xml
is going to screw up how your interpreter, or your compiler,
sees your source file.
And you do not want that to happen.
Brainwashed, BrainW4ashed, says, why is Lua preferred for games?
It is probably because it's one of the faster scripting runtimes.
I mean, traditionally, it has been.
I would say now, probably, it's the case,
that there are a lot of runtimes that are as fast, or at least comparable.
It's very lightweight, very easy to integrate into a C or C++ based code
base.
Because it just has very simple hooks and libraries that you can-- like,
just a Lua dot c, or whatever it is--
you reference that file in your engine, and then you can easily just
call back and forth between scripts and pass variables back and forth
to the Lua runtime.
It is pretty simple of a language, I would say.
It's kind of the analog to what C is for compiled languages,
with just a very small set of features.
But it allows you to very flexibly do whatever you want with it.
And just pretty easy because of that.
And so I think all these factors have sort of
made Lua the de facto scripting language of the game world, so to speak.
But that's not to say that you can't use other scripting languages.
You certainly can.
You can use JavaScript, you can use Python, you can use Ruby.
You can use compiled languages and scripting languages
if you're going to put in the effort.
It's up to you, ultimately.
Andre says, I've started using Vim months ago
and haven't used anything else since, mainly
because I don't know how to exit.
Yeah, that seems to be a common problem.
I remember when I first fired up Vim, had the same problem.
I believe it's command x to save and exit.
But honestly, I never use it.
So I'm not 100% sure.
Jabkochason says, what is Vim, a code editor?
Yes.
And I probably have it on my machine.
Vim main dot Lua.
So it looks something like this.
So I'm literally looking at the main dot Lua we were just looking at.
I have no settings for my Vim on this account, so it looks very plain.
It's just adopting the style of my terminal.
But you can get a bunch of fancy features with Vim.
You can have line numbers, you can have syntax highlighting,
you can have a bunch of cool plugins and stuff.
I don't have any of that.
And you can see at the very bottom, that's
what I'm typing to actually get out of Vim.
So colon x is to escape.
And there's a bunch of other stuff.
I never use it.
If you want to actually edit, I think have to type I for insert mode.
And then you can type.
By default, you don't get to do that.
But it's essentially a command prompt or terminal CLI text editor.
So it's super popular for being able to SSH into a server
and edit something on a server that you need to do.
Basically, it's something that you wouldn't
be able to do on that server is use vscode,
so you kind of need a CLI text editor.
Hence why Vim is certainly popular amongst certain communities of DevOps
and IT folks.
Bhavik_Knight's got a couple of shortcuts there in the chat--
QL without saving.
QW with saving.
That's the first thing I learned when I started using them.
Let's go to function.
Check letter.
Send the key code.
Check letter key.
Yes, we're going to be doing something very similar to that actually.
So we will see that very soon.
I always use nano.
I actually use nano as well.
Nano is a little bit easier, less of a learning curve.
Oh, Adamantine says, my apologies.
Sorry.
I couldn't tell whether you were joking or not.
No, it's a funny joke.
But certainly, some people do.
The reason that I took it seriously is there
are people that are brand new to programming
that might not know that Microsoft Word is actually not intended for source
code editing and might cause issues.
And because you're new to programming, you
might not understand why Microsoft Word's not allowing you
to do the things that you need to do.
And so it's certainly important to talk about.
[INAUDIBLE] says, I like Microsoft Word.
I like Microsoft Word, too, but certainly not for text code editing.
Damnerel says, not anymore, because the commands in Vim
are referring to not using it, I'm guessing.
[CLEARING NOSE]
Excuse me.
I have a little sniffy nose.
I use Nano as it has commands attached at the bottom
so I don't have to remember.
Yes, yes, true.
I've been waiting days to say this.
I have a love-hate relationship with Lua and hence the O with the umlaut over it
very, very clever pun.
Traditionally, Lua was used in game dev because it was so easy to use with C
and C++ compiled binaries that actually recompiled them correct.
Sashikant, can you please make a stream on building a FPP game using Unity?
FPP, first person platformer?
Is that what you're referring to, Sashikant?
Not using Emacs in 2019, says MojoDojo101.
As somebody who is getting into, or at least has been interested in Closure,
the Closure community is super, super passionate about using Emacs.
So I might actually learn Emacs when I get back into that.
But yeah, aside from that, it's fairly niche, at least,
unless you grew up using Emacs or did it professionally
back when it was more popular.
Bhavik_Knight, is Rust as fast as C?
I don't know.
I haven't looked at the comparison.
I imagine slightly less performant, because it does a little bit more.
I don't know if it's all compile time.
I don't know a whole lot about it.
But I know it does a lot of compile time safety checking.
I don't know if it also does more runtime safety checking, in which case
it'll be less performant.
Spacemacs.
I have not seen Spacemacs.
LuaJIT gives you a pretty much free performance upgrade without any hassle.
Yes.
I believe Love also comes with LuaJIT.
Can we start Hangman?
says Whipstreak23.
Yes.
Yes, we can.
First person shooting game, says Sashikant.
Let me think about that.
Because that would be actually pretty easy to do, a basic one.
We can certainly take a look at that.
OK.
So we have a window going.
And this is why I can't read the chat too much, because I
know I'll just get sidetracked forever.
I apologize.
I want to read everybody's comments.
But I can only do so much.
I can only bite off so much at a time.
So we have our window.
I can press escape to close the window.
It still says untitled up at the very top.
So just so that everything looks completely nice,
you can do what's called love.window.setTitle.
Notice that now the top bar says Hangman.
So love.window.setTitle.Hangman.
And why don't we draw--
so let's kind of sketch out what I want it to look like.
I kind of want it to have--
here in the middle, we're going to have like the Hangman here,
and then the word here.
Or maybe Hangman here, and then the word here.
And then at the very bottom, I want to have all the letters of the alphabet,
and then have them all color coded.
So if somebody has tried to type in, for example, E,
but the word doesn't have E in it-- it's a wrong letter--
not only should a piece of the stick figure like pop up on the screen,
but we should also get that E to be turned red, such
that we have feedback that, OK, that letter is actually not correct.
So I think that will be super important.
And if they got a letter correct, not only should it show sort of here
below the Hangman, but we should also have the letter in green.
So all the letters are going to need to be associated
with some sort of like correctness, like tried flag, tried is true, or maybe
like a status flag, where status is not tried, failed, and success.
And those map to different colors, basically.
Do I need to have Love installed in order
to run games others wrote using the Love language?
So Love itself is not a language.
Love is a runtime.
It's a program that you download.
And yes, you will need it.
You will need to download from Love2D.org
the version for your operating system.
And then you can click and drag folders with a main.lua in them, which
is what we have here in our editor.
See, we have the main.lua.
So any folder with a main.lua, you can click and drag that onto the love.exe
or love.app that you download from the Love2D.org website,
and that will allow you to run a Love game.
So the language itself is Lua, and the runtime, the program, is called Love.
All right.
So let's go ahead and draw I guess all the letters of the alphabet
at the bottom of the screen.
So I'm going to go--
we want to do this in a loop, right?
We want to go through every single letter of the alphabet.
And so what we need to do is we need to iterate.
We need to go from A to Z effectively.
And in order to do that, we can't really say--
I guess we could say--
I think we can do this--
for underscore letter in "ABCDEFGHIJKLMNOPQRSTUVWXYZ."
Getting some alphabet practice today on stream.
And this needs to be in pairs.
I'm not 100% sure if this will work.
We might need to convert A to Ascii, and then iterate up into Z in Ascii.
And I have to look up exactly how that works.
But why don't we go ahead and just--
I want to do this.
Now we can do it like this.
So if I go to Lua, and I say for underscore letter in pairs of ABC
do a print letter.
And OK.
So it can't-- so it doesn't iterate over strings.
So strings aren't innumerable like tables are.
So in this case, can you--
I thought you could iterate over strings.
Maybe not.
Is it not the case?
Can you not iterate over strings?
I do text manipulation so rarely in--
OK.
So you can't iterate over strings in Lua.
So what I'm going to do is I'm going to--
basically, the way that string, the way that Ascii
works, the way of what Ascii is, is every character, every text character,
has an underlying integral value.
So in this case, A, I believe, it's either 97 or 65.
I think capital A is 67, and lowercase A is 95.
Something like that.
Yeah, 65, 66, 67.
Oh, yeah.
Jabkochason says, that's why I asked him if he's willing to do JS games.
Easy to distribute.
Yeah, it certainly is easy to distribute.
There is castle, which we've looked at before, which is super cool.
So if you type in playcastle.io.
This is something that my friend Charlie through Expo and his friend Nick
have been working on.
This is super cool.
It allows you to download games in Lua off of GitHub.
So this is a nice way to distribute games.
I have to remember the exact usage of the program, which
I haven't used it in a little while.
But that's a nice, easy way.
They're developing it to make it all the easier to distribute Love games.
So definitely check that out.
OK.
So what I want to do is for i is equal to--
and then we have to figure out what Ascii is.
I don't remember offhand.
The Ascii for capital A is 65.
OK.
So basically, this thing is called an Ascii table.
This is how you can tell what the actual string character is
represented as underneath the hood.
This is important if you're in C programming especially,
but you see it all over the place.
C and compiled languages, you often will need to know this,
depending on what your goal is.
But the character A is actually represented
underneath the hood as the value 65.
And this is just a different way of encoding the same information.
Because underneath the hood in a computer,
you can't actually store like a character.
You can only really store numbers, ultimately.
You can store numbers binary.
You can only really store binary numbers.
And so you have to encode--
pretty much everything that you ever want to represent in a computer,
you have to encode it as binary, as a number effectively.
And this is sort of the first sort of step that a lot of students
get when they figure out this transition,
the way that computers work, and how things are stored in memory.
So A is the value 65.
And sequentially, it goes all the way to Z.
And there's a bunch of other characters in here.
Every text character that you've ever seen
has an encoding of some kind, some number that equates to it, including
all the emojis you've ever seen.
Those all have a number, too.
But those are a thing called Unicode.
We won't talk about that.
Basically, more bits that go into storing a value.
But A is 65, and it goes all the way down to Z, which is 90.
And then we also have all the lowercase values.
So a, lowercase a, like I said earlier, is 97.
So interestingly, the capital letters go before the lowercase letters.
And between them are a few symbols here.
But lowercase a is 97.
And then lowercase z is 122.
So we need to basically iterate over the entire alphabet.
And what we can do is we can say for i is equal to--
what was it?
Capital A is equal to--
well, actually, no, because we need to store this.
We're going to get input as lowercase letters from the love.keypressed.
And eventually we want to be able to map lowercase letters to--
we want to be able to say when they type B, I want that to become b in the text.
So what we need to do, actually, is we need
to start-- we need to look at the lowercase letters,
not the uppercase letters, because I want-- these are effectively
going to map to whatever we press on the keyboard.
We're going to do a comparison in an if statement.
And it's not actually going to be equal to the capitalized version.
So if they type a on the keyboard, because they're just typing literally
regular a without shift-A, that counts as a different character than capital
A. The two are completely different values.
So I'm going to say 97.
So capital A is equal to 97.
Capital A, Ascii, right?
There may or may not be a better, more clever way to do this.
But this allows us to have a nice little talk about Ascii.
And yep, Pamauj says you should do a loop using an integer representing
the Ascii for each letter.
Exactly.
That's what we are getting to.
And then JPGuy is in the chat.
Hey, JP.
Good to see you.
OK.
So for i is equal to capital A Ascii.
Sorry, lower a, lowercase a Ascii.
Lowercase a Ascii comma, and then this is how
you say I want to iterate over a range.
You specify the upper bound of the range.
So in this case, I actually want to iterate over the--
all the way up until lowercase z.
So we've got to figure out what the value is for that.
So the lowercase z value is 122.
So I do that.
And then I say lowercase z Ascii.
So we're starting at lowercase a Ascii.
That's what i is going to be.
And then we're going to iterate up into lowercase z Ascii.
PackOfPandas says, what IDE are you using?
We are using VS Code, Visual Studio Code.
Super great editor.
You can also use Atom.
You can use Sublime Text.
You can whatever you want.
VS Code is the editor that I personally like at the moment in the editing
landscape, so to speak.
OK.
So until that, what we want to do is I want to say love.graphics.print.
And I'm just going to print this across the screen.
So what I'm going to need to do is I'm going to need to space them
apart by some values.
So I can say local x is equal to-- and I'm just going to start at 0.
And then I'm going to increment this.
Every time we draw a character, I'm going to say x is equal to x plus,
and then we'll say 32.
Is it going to fit?
Yeah, that'll fit.
And then I'll say, print.
And then I think in order in Lua to get a number there's a special function.
So lua number to string is we may just be able to use the to string function.
I honestly don't remember on 100%.
So here's a great resource by the way if you're ever not sure.
And I don't do a whole-- this is why I'm looking up the documentation, because I
don't do a whole lot of sort of Ascii manipulation in Love 2D typically.
But you can go to the Lua manual.
So Lua programming manual.
And it's the 5.3 reference manual, I think.
It's not the most recent version of Lua, but it's the most recent manual
that I think they make for free.
And it will take you through the entire landscape of the language
if you want to.
So every single piece of the language.
It's not a big language either.
And you see all the libraries, too.
Both the actual C API.
So how you integrate Lua into your engine.
And also the Lua functions themselves, what you actually
can call from the Lua source code.
And so what I'm interested in was just being able to take a number
and turn it into a string in Lua.
So I'm just going to sort of skim this documentation here and see.
There should be a pretty easy function to do this.
You specify a character in a string also by its numeric value
for the escape sequence DDD, where DDD is a sequence
of up to three decimal digits.
Interesting.
OK.
So 97 would be slash.
OK.
So slash-- so it's forward slash, and then three numbers, right?
Oh, but how would I do that with the lowercase a with a variable?
Let me see.
Number to string behavior.
To string.
I think it'll be more appropriate to say Lua Ascii to string.
OK.
String.byte.
OK.
So there's a string library.
Interesting.
This looks familiar.
It's been a little bit since I've seen this.
String.char.
String ABCD.
Coercion.
String.char.
OK.
So I think we should be able to string.char.
And then the character, in this case, it would be i.
So let's try that.
And then love.graphics.print takes in not only the string
that we want to print, but also the x and the y that we want to print it at.
So I'm going to say x, and then 0.
So if we print this out, let's see if this works.
Oh, it does.
Awesome.
So it's kind of tiny.
It's a little bit hard to see up there.
So to make it a little bit bigger, I'm going to say, large font is equal to--
sorry.
I'm going to do a little bit better.
I'm going to say, local large font.
And then I'm going to say, large font is equal to love.graphics.newFont.
And then I'm going to take in a--
I thought you could also just give it a size, and that would work.
32.
Will this work?
Love.graphics.setFont, large font.
Yes.
Excellent.
So let me go ahead and keep up with the chat here.
So Brenda kindly provided earlier before I could see it, string.char,
string.char, string.char.
Some people will pronounce it.
I think of it as "care" or "car," but it doesn't matter.
But yes, string.char was the-- string.char, string.char,
string.char, all the same, did indeed work.
So now we can see we have A, B, C, D, E, F,
G. It's all a rather large size compared to what we saw before,
but we have all our characters that we care
about from the left going to the right.
And they're all being drawn every single frame.
So everything that gets drawn to the screen,
it gets drawn in 1/60 of a second, and it's all being done in here.
So this bit of code gets executed every 13 milliseconds approximately.
So we're actually doing this constantly over and over again.
But it looks like it's static.
But it's actually being rendered over and over again.
But yeah, that actually worked pretty smoothly.
I think we can start this off actually a little bit more in the center.
So I can say like 126 maybe.
See if that's a bit more center.
Maybe 180.
I'm not going to be specific about it.
190.
But yeah, that should work.
That looks about centered.
And then I'm going to actually draw this at the bottom of the screen.
So I'm going to say, window height minus 100.
And now it's being drawn sort of where we eventually
want it to be when we have the Hangman and the word
that we're looking for at the bottom.
But see, now we have all of the characters
that we wanted drawn to the screen.
Let me make sure I am keeping up with the chat here.
Which editor Visual Studio code is the source code editor
to develop Microsoft for Windows, Linux?
Michael S.
Yes, correct.
I think you're sending that to somebody else.
PackOfPandas, is this a more recent language, Lua? you say.
No, actually, Lua has been around for a long time.
It's a-- the framework Love is kind of new-ish, I think.
I don't know how long it's been around exactly,
but it's a great 2D framework that I discovered a couple of years ago.
I know it's been out for longer than a couple of years.
But it's awesome, really love it.
I teach with it.
I think it's excellent for learning.
Lua the language, as Andre points out in the chat,
is very popular with a bunch of other game engines.
But in our case, we're using it for Love, which is a free 2D engine.
It makes sense.
Haven't dipped my toe into any game dev.
Looks good, though.
Yeah, game dev is super awesome, definitely explore--
see what's-- check the landscape out.
I said landscape a bunch of times fairly recently.
Damnerel says, I need to go.
Till next time.
See you, Damnerel.
Thanks for coming.
You guys don't have a twitch chat bot like Nightbot or a self-made bot?
No, not yet.
We can look into doing something like that, though.
I'm actually not too familiar with the things that bots can do.
But it's something that I see a bunch in like larger channels.
I'm having problems installing Love 2D on Ubuntu.
Any help?
I'm a new Linux user.
So I don't have a ton of experience installing it.
And if anybody in the chat has installed Love on Ubuntu.
I did it one time for testing purposes a while back.
And I do remember that it was a little tricky,
because we need a specific version.
But I think you should just be able to get the PPA.
And I'm not a Linux user.
So I'm not 100% familiar with the process of installing stuff.
But you should be able to just download whatever
this is, whatever the binary is.
And then if you go to the wiki, and then go to I think it's Getting Started,
they have a whole section on how to run games for different operating systems.
So they have a Windows, a Linux.
So here's a bit of Linux, some terminal commands
in order to get you set up with actually running the executable,
and then you run the executable, and then provide a path to--
which is Love.
And then you write the path to where your game folder is,
or a Love.app or a dot Love zip.
But you don't need to worry about that too much.
You just need to worry about where your actual folder with your main.lua
is, and then you run Love, and then provide the path.
But yeah, definitely try that.
See if that is of any assistance.
And if anybody else has installed it in the chat, that would be very helpful.
Adamantine, how to install version 0.10.2?
So if you go to the page that I showed earlier, which was the front page,
there is an other versions section over here with the Other Downloads.
So Love2D.org, and the Other Downloads--
Other Versions section.
And then here you can see all the prior versions of Love
starting from 11.2 going all the way down to 10.2 and beyond in history.
So just download the version appropriate for your operating
system that's 10.2 compatible, and you should be on your way to go.
David's in the chat.
Everybody has beaten me to saying that.
So hello, David.
Thanks for joining.
How would you go about game developing on JavaScript and/or React?
Any advice?
AlexGabrielov.
I don't have a ton of React experience.
I know it's possible, but I probably would
aim to do something like Phaser instead of React, because React I don't think
is as much catered towards game development.
Phaser is very much focused on game development
and is closer in paradigm to what Love is, and is probably the framework
that I would teach in if I were to teach a JavaScript game course.
But the last time I checked, the documentation was still a bit,
like I said earlier, a little bit incomplete.
So I'd have to take a look and see if it's still good.
But this is a great framework.
Version 2, I remember it was very nice, a lot of features.
More features, a very robust framework, more so than Love,
I would probably say.
But definitely check that out.
What else do we have here?
Oh, we have a special guest.
Speak of the devil.
Not only do you guys get a chance to see him on chat, but also in person.
How's it going?
DAVID: Good.
Thank you.
I just wanted to wave hello in person.
I said hello online, but I was just around the corner.
So it seems a little silly.
COLTON OGDEN: Oh, we became very yellow.
I think the cameras on--
DAVID: What did I do?
COLTON OGDEN: The camera's, I think, is on an auto setting.
DAVID: So I should leave?
COLTON OGDEN: So we're aliens now.
DAVID: All right.
Is there anything I can do to fix?
COLTON OGDEN: No, it's OK.
As soon as I think you leave, it will just readjust to my skin again.
DAVID: OK.
Thanks, everyone.
Nice to see you.
COLTON OGDEN: It just points out how much tanner you are than I am.
DAVID: There we go.
Bye.
COLTON OGDEN: Let me make sure I'm all caught up with the chat here.
It says, if you're OK with Love 2D 11.1, it's
available in the official repos for Ubuntu 18.04.
Yeah.
And Andre, I think, has more experience with Linux.
So definitely try that out.
If you're not taking the games course, then you can certainly do 11.1.
And everything will work fine.
And I'm actually using 11.1 now.
But the games course, all the code base is in 0.10.2.
They updated to 11 while we were in the middle of the course.
And so rather than course correct, we stuck with 0.10.2.
But if you can get it on your system, it's as simple as plug and play
at that point.
It's just I know Linux is a little bit trickier than like Mac or Windows.
You can add Nightbot, for example, in Add Commands.
Then your viewers can type in something like !Editor find out what editor
you're using.
It takes like five minutes to integrate, and your mods can add commands for you.
Interesting.
Let me look into that, because I am actually not super familiar,
but I think that would be very useful.
What happened to your skin?
Yeah, yeah, yeah.
We were looking very much like The Simpsons.
Master Yoda is supposed to be green.
Skin is white again.
How tan is David?
He's not like super, super tan, but certainly more than me.
I'm very pale.
So that's why.
And the camera is set to auto color correct.
We can fix that for the next stream, but my skin, it's tailored to my skin.
And since I'm very pale, it gives me a little bit more darkness, I think,
than I normally have.
It's just that I look sup--
I don't look like as white as this background basically.
But as a result of that, when David comes in here and it balances out,
it just becomes very orange and very silly.
So that's photography, live photography.
Anyway, where we were at was we got all the letters drawn onto the screen.
So not very exciting.
But it's a pretty big first step, pretty big important first step.
What we are going to need to do is, remember,
we want to be able to have not only the letters drawing onto the screen,
but also each letter needs to have a color associated with it to tell us
whether we've guessed the right color--
or sorry, whether we've guessed that letter already,
and whether it's a wrong letter or a correct letter.
And if we haven't guessed it, it should just
stay white like the letters currently are right now.
So this will give us a chance to talk about how
to set the current active color in the Love 2D application.
But I think before we even need to do that, we should
start talking about how to draw the actual stick figure, and then the word,
and then load a word at random.
Then we can get to all that information first.
What is the deal with M and N?
Oh, I see.
It's because M, I think, is a little bit more right-heavy.
It's a longer letter horizontally than the other letters are.
And L is very not so.
Because L is just a vertical line, and it has nothing to the right of it,
essentially, it looks like M is pushed over.
But in reality, it's kind of a symptom of L being short, M being long,
and this font in particular exaggerating that.
It would look very different depending on which font you're actually using.
The space to take up on the screen exactly.
Why is there no space between the letters M and N?
That is, again, the font, related to the font.
How about not show the letter rather than change the color?
says Pamauj.
We could certainly do that, too.
Yeah.
Yeah, we could do that.
But when we do get to--
when somebody does guess a letter, we still
need to probably tell them whether or not the letter was correct or not.
And so we will need to render the color a different-- the letter
a different color as a result.
And you can also envision a game where you
have two tables, maybe correct letters and incorrect letters,
and you sort of draw it out that way.
But then you have to split your attention between the two
and sort of visually see, oh, this column has these letters.
This column has these letters.
I just want to know whether I've tried to type M already.
I'm looking there.
Instead, if you have them all laid out as one row of the alphabet,
you immediately, because we all know the alphabet
sort of in the back of our heads, you can see it in one place.
So just a little bit easier.
When's the next stream?
says Jacob.
Probably on Wednesday.
And it'll probably be a typing game.
So a continuation off of this.
And then soon, possibly Friday, if not next week, we'll do an HTML stream.
And then in the weeks to follow, all the undergrads are returning.
So Nick and others.
I know Emily Hong is a CS50 teaching fellow who's
going to be coming in to do a web scraping stream at some point.
Veronica is going to come back to do another Python stream.
We have-- I mean, David will be doing streams.
We might get Brian to do a stream.
Kareem might do some streams.
So we have a lot of streams in the future.
But everything is-- because the undergrads are on vacation still,
it's kind of in flux at the moment, and schedules are being figured out.
But yeah, Wednesday is probably the next stream.
Letters guessed are shown on the screen instead of all letters.
If is there in the word, it is green.
Otherwise, red.
Yes, exactly.
Otherwise red, or white, if we haven't typed anything, because we want to--
again, we want to see what letters we have
guessed wrong versus the letters we've guessed right,
and then the letters that we haven't even tried.
Colton's holiday is shorter.
A little bit.
But I still got a very long vacation.
Web scraping sounds interesting.
Yeah, it's super cool.
You can analyze the HTML in code, and then sort of figure
out where things are.
I need more JS.
That's what I'm learning.
So please, LOL, says Jabkochason.
Yeah, we'll definitely do some more JS stuff in the future,
because I know that's something the undergrads
and myself all would like to do sort of more tutorials on.
So we'll take a look at some of that.
And I might lead the HTML stream, too, and then I
might segue that into JavaScript stuff if everybody likes JavaScript.
So let's draw the actual stick figure.
So I'm going to create a few variables.
So let's say, local guessesWrong is equal to 0.
And we'll say-- because we want to start off with no stick figure at all, right?
So we're going to assume that we haven't guessed
anything wrong at the very beginning.
We've guessed 0 times incorrectly.
So no stick figure will be drawn.
But in the draw function here, I can say, if guessesWrong is greater than 1,
then love.graphics.circle, and then we'll make this a line circle.
So you can draw two different circles.
You can draw a line circle, so just literally a line, just a hollow circle,
like you would draw using a piece of chalk or using your pencil.
And then fill is the other mode.
And that just draws it filled with whatever color
you're currently drawing with.
We're going to do a line circle.
Everything's going to be line drawing in this case.
Love.graphics.circle line.
And then I forget offhand the rest of the--
x, y, and then a radius.
Right.
OK.
So the x and the y are actually-- for circles,
it's a little bit different than rectangles.
Circles are actually drawn from the inside out.
And so we need to specify the center of the circle in this case.
So I'm going to say, virtual--
sorry.
Not virtual width.
Window width divided by 2, and then 100.
And then the circle is going to be, let's say, 64 pixels big.
That's the radius.
So it'll actually be 128 pixels diameter, a 64 pixel radius.
Let's try and set guessesWrong to 1.
Sorry.
This should be greater than or equal to, not greater than.
And then I'm going to set this to 1.
We'll draw this.
So as we could guess, we do indeed have a circle being drawn on the screen.
It's being drawn in the middle, the exact middle,
because the center point is where circles are drawn relative to.
If you watched prior streams, then you've seen though we've drawn sprites,
and we've drawn rectangles.
And those are all drawn relative to the top left corner.
But circles are different.
That's just an implementation detail of Love 2D.
It's probably easier for them to program it that way.
Circles don't have an x, y top left, necessarily, because they're circular.
They don't have a box border.
You could envision a box, an invisible box,
that sort of goes around the circle.
And you could theoretically design your API to work that way,
but they decided not to.
I'm going to say guessesWrong is equal to 0.
I'm going to test--
I want to test all the pieces of the stick figure being drawn.
So we're going to draw the head first.
So I'm going to say, draw head.
And then I'm going to say, draw body.
So if the guessesWrong is greater than or equal to 2, Love.graphics--
now here's another one-- so love.graphics.line.
So this is another important function for drawing lines.
It takes in an x, y to where it starts, and then an x, y to where it ends.
And this allows you to draw any kind of line you want,
a straight line or a diagonal line, an arbitrary size.
You just need to know the x and the y for the start and the end point.
And it'll figure out how to draw it for you.
So I can say, love.graphics.line.
And that's cool.
Actually, you can continue passing point positions
to the love.graphics.line function to draw what's called a poly line.
So that just means a line segment that's arbitrarily--
it goes into arbitrary positions.
You can sort of draw shapes that way.
We're just going to draw individual lines.
So two pairs of points.
Yeah, two pairs of points.
So in this case, I want the body to be--
if I comment this out, and then run this.
Whoops.
This needs to be set to 1.
So I want basically the line for the body
to be right here at the tip of the circle,
and then I want it to go down to like maybe right about here.
So I'm guessing that's about 100 pixels or so, 100, 150 pixels.
And then the body, the arms can go out here like that,
and then the legs can go kind of down here like that.
So I'm going to say, first, I'm going set guesses to 2 just so we can test
this to make sure that it works, right?
We haven't actually guessed wrong twice.
And if you're curious, in order to comment out
multiple lines or any single line, you can hit command or control-slash
on your keyboard in VS Code and in other text editors.
And that's how I'm doing that.
So if I say, love.graphics.line, and this
is going to be in the center of the screen for the starting position
and the ending position.
So it's window width divided by 2.
So we started the center of the circle at 100,
and then it goes down 128 pixels.
No, sorry, 64 pixels, because that's the radius size.
So it'll actually start at 164.
Or at least it should start at 164.
Sorry.
No.
It should start at--
yeah, sorry.
164.
I got my parameters confused here for this function call.
So if I say 164, and then I want it to go down.
It's going to be the same x position, because it's
going to be a vertical line.
So the x isn't actually going to change for the second coordinate.
It's going to go straight down.
So the same x position, right?
Just a different y position.
And then it's going to be at, let's say, 264, 100 pixels long, 100 pixels down.
That's where the ending-- this is the ending x, y, and this
is the starting x, y right here.
So I can draw this.
That's a little on the short side.
So I'm going to say 364 maybe.
There we go.
That looks pretty good, right?
So we have the head, and then we have the body rendering successfully.
Now, let me make sure I'm up to speed with chat.
Can we name them as wrongGuess1 and wrongGuess6?
I'm not sure what you're referring to, ForSunlight.
If you want to elaborate on that.
We definitely don't need to store this as variables, separate variables.
This is very similar to JavaScript.
It makes me happy.
Yeah, it does look very similar to JavaScript.
We can abstract it when guess is wrong.
We can just call based on that number.
Head-wrongGuess, body wrongGuess, et cetera.
Well, we don't need to keep separate variables
for this, because it's just going to increase a counter every time they
get an incorrect guess.
And because we're keeping track of this counter,
we can basically just check to see if the counter is equal to 6.
And if it's equal to 6, we know that it's a game over.
So we don't have any real need or reason to keep
six separate variables in this case.
But I can see how semantically that might sound appealing certainly.
Let's draw the right arm, draw the left arm, draw the right leg,
and then draw the left leg.
So I'm going to say--
I'm basically going to copy this a bunch of times.
And then this is going to be 1, 2, 3, 4, 5, 6.
We could base it-- we could do a for loop.
We could say for i is equal to 1 till 6 do,
and then check to see is it greater than or equal to 1,
is it greater than or equal to 2, greater than or equal to 3,
or greater than or equal to i.
And if it is, then draw this, this, this, this.
It doesn't really save us a whole lot of sophistication to be quite honest.
And everything is very-- all these drawing functions are very different.
And so there's not really a--
oh, now I see what you mean.
So if you want to abstract draw head, draw arm, whatever as functions,
yeah, you could theoretically do that.
I'm probably not going to do that, just because they're only one line each.
It's not really that great.
And we're not going to get much more complicated
than this for the actual drawing of our stick figure.
What we could do, certainly, is we could copy all of these,
and say, draw a stick figure, and then make a function like that called
drawStickFigure.
Because all of these kind of go together as one sort of package, one box,
so to speak, this makes sense.
And so now we've made our love.draw smaller,
which sort of should keep track of all the drawing of our game.
But we haven't made functions that are a little bit too small in my opinion.
This is great, though.
This is kind of like the ideal max length of a function, probably.
And it's hard to really to stick to this is as a truth.
It's easy for functions to get kind of out of hand
depending on the sophistication of your logic.
And certainly, some functions are harder than others
to abstract out in a very modular, compartmentalized way.
But this is a pretty decent size.
And this allows us still to reference guessesWrong in the local
that we made at the very top level of our program.
So we'll just keep it like this.
This seems pretty good.
We can draw the body.
We're going to draw the right arm here.
So what we're going to do is I'm going to say
I want the right arm to just kind of start
halfway down the body of the stick figure that we just drew.
And just so that we can test everything and make
sure everything is rendering appropriately,
I'm going to set guessesWrong equal to 6.
So this will be when they've lost the game
and the full stick figure is being drawn.
We're going to do it there.
So guessesWrong is equal to 6.
And then--
Shouldn't we start from higher to lower values with an if check?
says MarekB101.
Not necessarily in this case, because we're going through--
I mean, I guess you could do it either way,
but I don't think you really get much of a value out of it in this case.
I think it's kind of up to how you want to think of the problem.
But I'm thinking of it from head to toe, I suppose.
And so that's why I'm thinking top--
you're still going to the same number of if checks ultimately.
So I don't see a particularly compelling reason to do it,
unless you want to elaborate on why.
I think they're both probably equal.
If you do do it from 6 to 1, then you're going
to reverse the order of your body parts that you draw,
because if they've gotten one guess wrong, then the head should draw,
and then the body, and then the arms, then the legs.
And then you can complete the stick figure.
It's kind of weird to draw the stick figure from feet up.
The first statement will always be true.
Not necessarily.
If the guess is equal to 0, then it's not going to be equal to true.
If we start at 6, then that's going to be false, then false, then false, then
false, then false, then false as well up until 1 or whatnot.
So it will be about the same.
Unless I'm missing something obvious, but definitely at the moment,
I don't think that that's necessarily the case.
So window width divided by 2, 164.
And this is all probably not great, having this 64 and this 100.
So I'm actually going to say circle or head center x, and head center y.
And then I'm going to put these up here.
So head center x is equal to 100.
Head center y is equal to--
sorry.
That's the offset.
Head center x-- is that true?
No, that's incorrect.
Head center x.
Head center y is equal.
This is head center y.
And then head center, and then head size is equal to 64.
My bad.
Head center y, and then head size.
So we'll do that there.
Keep everything a little bit cleaner.
So try to avoid a bunch of-- because this could get out of hand.
We're already starting to get out of hand a little bit.
We have 164 here.
So what we can do with this is we can say instead
head center y plus head size.
And then this will be--
this is the second point.
And so what we can do here is body length should be 200 or so.
So we'll say body length is equal to 200.
And then head center y plus head size plus body length.
So it's more verbose.
And I'm actually going to indent it, or make a new line just so we can see it.
But at least we have words and not a bunch of numbers floating around.
So it's just a little bit better practice to do it this way.
So we have the body there.
So the body hasn't really changed, but we've just made it a little bit more
readable.
Arguably, maybe less readable, because there's so much of it here.
But not as sort of random all over the place.
Somebody reading the code is going to be like, what's 264?
What's 3?
What's 164?
What's 100?
What's 64?
I don't understand.
Now at least everything kind of is like, oh, OK, I should draw the x,
y at window width divided by 2, and then the head center y plus the head size.
OK.
That makes sense.
So where the center of the head is plus its size.
OK.
I can see that.
Yeah.
Because we want it to be, obviously, at the bottom of the head, right?
Alamanesa-- Alamaniaseef-- am I pronouncing that right?
Ali-- Alamin--
Alaminasif.
Sorry.
Alaminasif says, hi, Colton Ogden, first time joining.
Hello, Aliman-- or Alamin.
Thank you very much for joining.
Sorry I had such a hard time pronouncing that word, that name.
Shouldn't we use elseif?
Independent if will be checked even though the value is already checked.
If we do an elseif, then we will skip drawing the rest of the body parts
after we get to one guess wrong.
So that's why we need multiple chained ifs, not elseifs.
But excellent question.
Bella_Kirs says, a switch would be OK.
Yeah, a switch would be cool.
I don't believe Love has a switch statement.
It could be incorrect about this.
But even if we did a switch, not Love switch, Lua switch.
Even if we did have a switch, so they do have a sort of a switch style thing.
If we did a switch, we're still doing one thing at a time, right?
We're still doing only one piece of the body that we would be drawing.
If it were 6, if it were 5, if it were 4,
if it were 3, if it were 2, if it were 1.
We need to check each one.
We need to check to see whether we're at six.
And if we're at six, we draw everything.
If we're at five, we draw everything except for one thing.
If we're at four, we draw everything except for two things.
So we still need to do multiple steps depending
on if we're at a different point.
Oh, I see.
We don't have to do a break, Bhavik_Knight says.
Yes!
That would be one way to do the switch behavior.
Yeah, exactly, we would do a--
would that work?
Let me think.
If we did-- yeah.
Yeah, you're right.
A reverse ordered switch without break would work.
That's correct.
It's a little bit too much at this point, I think,
and because Lua doesn't actually have a formal switch statement,
I think we'll look over that.
But in theory, if you were doing this in JavaScript
or if you were doing this in C or something,
yes, a switch statement without breaks would function well in this case.
And Brenda says, there is no switch in Lua.
That's correct.
There are ways to sort of get that behavior
as we were just looking at in Lua.
I'm not going to spend too much time on it.
A fall-through, says Andrej.
Yes, that's exactly right.
For some reason AutoMod wanted me to--
was questioning whether Bella_Kirs's thing was a bot or not.
I apologize, Bella.
Starting from case six I think without the break statement is correct.
Yes.
That would be a clever way.
That's essentially what we're doing here sort of, but in the reverse direction.
But yeah, the same logic applies.
And that may be what--
what was the name?
I apologize.
Who was saying that?
Marek, MarekB was saying something along those lines.
That might have been what he was thinking,
or he or she was thinking when they suggested that.
And that would be-- in that particular implementation,
that would be the correct way to do it.
Apologies.
I have not been keeping up with the followers.
So ErnieOak, BollywoodBrogan, and Alaman--
Alaminasif-- again, I struggle with that name--
Alaminasif, thank you very much for the follows today.
Appreciate it.
OK.
So let's fix up these last few drawing statements here.
So drawing the right arm.
It should start at the--
instead of the y level at head center y plus head size,
we want this, the y position of the starting point for this,
to actually be a little bit farther down.
So it's actually going to be body length divided by 2.
Add body length divided by 2 on top of that.
So it will be right at the bottom of the head,
and then down halfway down the body.
And then the arms, we're just going to make them go--
we'll make them go downwards.
We'll slope downwards.
So we'll say we want the ending point to be--
it's going to go to the right and down a bit.
So we can say window width divided by 2 plus--
let's just say head size for now.
And then the y position of this is going to be, let's say,
this same thing that we did before.
Oh, whoops.
Did I screw this up?
Oh, right.
Because I forgot to take out the other parameter when I replaced it.
And then we'll add onto this.
Let's just add head size to that as well.
So we're going to add-- it's effectively just adding 64 pixels.
Yeah, we'll do that.
That should be fine.
And then does this work?
Oh, that's way too low.
So let's make it a little bit higher.
So plus body length divided by 4.
And that's OK.
So if I do this, yeah, that should be fine.
I think that's good.
And we can actually copy this here.
Well, rather this.
Sorry.
This.
And all I'm going to do is reverse the y of the arm,
the second coordinate of the arm.
And because of that, I'm going to--
sorry.
The x.
I'm going to minus.
I'm going to do minus head size.
And so it does that.
So it's effectively mirroring.
So I took the right arm code, and instead of adding the head size
to the x position, we subtracted it.
And so that made the second point, instead of going to the right,
it went to the left.
So the other way.
And it reversed the way the camera is seeing it.
Legs point down.
Hands point up.
But it's a hanging man.
Don't you think that the arms would go down, not up?
That seems a little bit weird to me, doesn't it?
I mean, we can certainly do it, but it doesn't seem quite accurate.
Then again, we're not actually hanging him.
So maybe it's OK.
So if we did that in that case, it would actually
be minus for these two and minus for these two.
And it's a little bit awkward at this point, because the hands are so--
they're like right in front his face.
So why don't we multiply this by 2, and do that?
How's that?
Does that look good?
A very happy, very energetic Hangman.
Our Hangman will have lost all his will to live, so his arms are limp.
Yeah, he's not a fan of the font we chose.
The M and the L are messed up.
He lost his will to live.
Yeah, we can actually copy--
let's copy this code again for the right leg.
Sorry.
This code.
And let's do that.
So the right leg is going to be lower.
It's going to be at the very bottom of the body.
It looks like he's surrendering.
Yeah, a little bit.
He's not surrendering.
He's being hung.
That's all right.
We'll keep it kind of fun.
He's not being hung.
Hanged is the correct, I think, the correct grammar for that.
It's a weird word, a weird English word.
Let's copy these.
Draw the right leg.
So his right leg is going to start not at head center y plus head
size plus body length divided by 4.
It's actually going to be at body length.
The same with this.
And then this will be for the y.
It's actually going to be plus, and plus, and then plus, and plus.
That's weird.
OK.
Why did it do it like that?
He's jumping for joy.
So he went from surrendering to jumping for joy.
Interesting.
Why?
Oh, because it needs to be body length, not body length divided by 4.
Whoops.
There we go.
That's better.
That was great.
If it's going to be fun, he could do The Bangles "Walk
Like an Egyptian" pose, Andrej.
I'm not even sure what that is.
It's devolving at this point.
But we have a stick figure who's surrendering.
We'll say he's surrendering.
He or she is surrounding.
It's gender neutral.
I am just trying to give dramatic effect, says Bhavik_Knight.
Yeah, that was hilarious.
It's been great making this stick figure.
But we have a fully drawn stick figure.
We're getting really close.
Turing_k, thank you very much for following.
Appreciate it.
You don't know that song?
No, I don't.
I apologize.
I will listen to it later, though.
Remind me if I haven't by the next stream.
The Bangles, "Walk Like an Egyptian."
OK.
I have very bad music knowledge, like I tend
not to do a whole lot of branching out, at least when
it comes to like maybe outside of the realm of EDM.
In the realm of EDM, I know a bit, and like,
oh, I used to listen a lot of metal music in the 2000s.
So I knew a bit of that scene.
But I don't do very broad strokes when it comes to music.
I'm much more of like a deep diver kind of person.
So yeah.
Myaocat, are you listening to metal?
A little bit now.
I haven't listened to it for years.
But I've been listening to Dream Theater again, which I'm a fan of.
But yeah, my music kind of has been switching back and forth between metal,
metal videogame music and--
metal videogame music and EDM a bit.
Turing_k says, is that Lua?
It is, indeed.
And we're using the Love framework as well.
You can go to Love2D.org to download it.
And it's super nice to use.
Metal is too much for me.
Very loud, says Myaocat.
Yeah, I'm not in the mood for it all the time either.
Her IQ is high, not age, says ForSunlight.
I'm not sure what that's a reference to.
Oh, [INAUDIBLE].
It was a reference to [INAUDIBLE],, right?
Yeah, I'm young.
Here IQ is high, not her age.
Yes, exactly.
OK.
So we've drawn the stick figure.
That's great.
We have it at six guesses.
So we know that when they have guessed six incorrect times
that it works correctly.
So we're going to go to zero guessesWrong and no stick
figures being drawn at all.
The next thing that we want to do is I want
to create a table of words that's effectively a dictionary.
And I'm going to create just a list of words from A
to Z in that they start from-- they start with each letter of the alphabet
just so that we have a diverse dictionary.
And I want to make them somewhat longer words.
And some of them should be obscure.
But if anybody has suggestions, definitely toss them in the chat.
Let's say, bombardment for B, catastrophe for C, detrimental for D.
I'm keeping these somewhat sophisticated just so
that they're not super easy to guess.
Elephant for E, fictitious.
That's a good one for F.
Open Sesame.
Nusrat_Jahan says, hi, first time joining.
Hello, Nusrat.
Thank you very much for joining.
Appreciate having you.
Turing_k, I apologize if I didn't say thank you for following.
Thank you for following.
Robert_Springer says, fox.
That would actually be pretty funny.
Just a one three letter word, fox.
Just for Robert, we're going to do fox.
Gregarious, I like that as G.
Bar Baz, ForSunlight.
Heliography.
Wow.
Heliography.
I didn't know that was a word.
For all I know, maybe it's not a word.
Maybe Asli just messed with me.
Maybe it's a made up fictional word.
I, indoctrination.
That's the longest one so far.
H, I, J. What's a a good one for J?
Hackintosh, says Myaocat.
Asli is a translator.
I'm sure she knows a lot.
Yeah, she probably does.
J. Why am I having such a hard time thinking
of words that start with the letter J?
Jelly Bean.
K, kleptomaniac.
Heliography, a device for signaling by means of a movable mirror that reflects
beams of light, essentially sunlight, to a distance.
Oh, nice.
Like an Indiana Jones kind of thing.
Oh, man.
Bhavik and Andrej both have the same idea there.
That's probably-- that looks like it has just about
every letter in the alphabet, which would actually be pretty funny.
Hey, I've got a question, says Turing_k.
Sure, shoot your question.
K, L. Lemonade.
Why not?
L, H, I, J, K, L, M. Microscopic.
Procrastination.
That's great.
I like that, CesarCXBR.
L, M, N. Neurobiology.
N, O. Off--
I always forget how to spell this.
Is that how you spell ophthalmology?
Procrastination.
P, Q. How about quintessential?
Because that's one of CS50's words.
The Speller PSET from CS50 has--
oh, man, the longest word.
Right.
OK.
That goes to show you how much I remember about the Speller PSET.
Nusrat_Jahan, thank you very much for following.
Appreciate it.
Q, R.
I think he's using OBS for streaming.
What is he using for the cut out of his upper body?
OBS.
So that is just two different video feeds.
One is my laptop, and then one is going from a camera into the computer.
And in OBS, you can put two video sources on top of each other.
So I can move them around as I want to.
But you need a capture card in order to take input from a camera
and to get it into your computer.
Reverberate and ragnarok.
Reverberate.
Well, actually, no.
Asli already donated a word.
I'm going to say ragnarok, just so that--
I mean, it's a--
I don't know if it's technically an English word.
I know it's a Norse word, but we'll keep it.
Ragnarok.
Kotlin, Lua, Matlab, NASM, Oak, a bunch of programming language words.
All good words.
Q, R, S. Stupendous.
Q, R, S. T for telepathy.
T. U for unanimous.
V for victorious.
A lot of "ouses"--
stupendous, unanimous, victorious.
Immediately.
Oh, immediately is actually pretty good.
OK.
We'll replace that.
We'll replace indoctrination with immediately.
Victorious.
T, U, V. W for--
Warmongering.
Sure.
W. X for-- xylophone is the one that everyone chooses.
So we'll just do xylophone.
Oh, xenophobia.
That's a good one.
Xenophobia.
X. Y for yeah.
I know like no words that start with Y. Yell.
I mean, yellow's so small and plain.
Yell.
Yo-yo, Translucent50.
I like the name.
Yak, yolk, yak, yaourt, yacht, yatch.
These are all too--
I want a nice, good, long solid Y word.
Yesterday.
I like that.
Yesterday.
Kudos to Melfein for that one.
Yellowstone is good, too.
Z for zygote.
I'd quit from the beginning if I played Scrabble with you guys.
Superb vocabulary.
Yeah, there's a lot of good words in the chat.
All my troubles seemed so far away.
Zeitgeist.
Oh, zeitgeist is excellent.
I like that.
OK.
We have a dictionary.
This is kind of like Speller.
A dictionary of words, and one of them is going to be chosen at random.
We're playing against the computer effectively.
This is not a two player game.
We want to be able to play this.
We want to be able to play this in such a way that we can play by ourselves.
So let's see.
The word needs to be chosen at random.
So I'm going to say-- so this is a table of words.
It's just a table of strings being used like an array.
I'm going to say, local word is equal to, and then words at index
random dot--
sorry.
Math.random, and then number of words.
So math.random is just a function that will give you a value between 1
and the number you pass into it.
In this case, we're passing in the length
of words, which is going to be 26.
So we're going to get a random value between 1 and 26.
And one thing that we need to do when we start our application, whenever
we do randomization, to prevent it from doing
the same values every single time, which is not really random at all,
we seed the random number generator.
We've talked about this in prior streams if you're not familiar.
We're going to basically tell our random number generator, which is math.random,
we need to say, seed the random generator.
Give it a starting value of some random number,
and give it OS.time, which is just some really long length in milliseconds
that our computer is keeping track of all the time.
So the current time in milliseconds.
And as a result of that, the word will always be random at this point.
It'll be different every single time we boot up our application.
Let's create a function called drawWord.
So drawWord is going to draw the actual word
that we're trying to guess in the middle of the screen below our stick figure.
Are you an undergrad or grad student? says Turing_k.
I am neither.
I am an employee at the university.
I went to community college for a couple of years,
but I do not have a degree in anything, actually.
I was singing "Yesterday" by The Beatles.
Oh, my god.
Colton doesn't know any famous songs.
You are correct.
You are correct, Asli.
I'm terrible with-- and I was actually thinking.
When I said earlier that I'm terrible with songs,
I was thinking Beatles in my head, because that's
a band that everybody knows, that I do not know anything about.
Time for cakes, says ForSunlight.
Hey, Colton.
Blah, blah, blah.
I may have the weakest vocab here, says Bhavik_Knight.
You probably don't.
It's probably weaker than mine.
I mean-- sorry-- mine is probably weaker than yours.
I did not mean that.
I meant to say mine is probably weaker than yours.
Yours is better than mine.
That was a fail.
Really impressed with your vocabulary, especially on the fly, says Asli.
Oh, no, that was probably because I've implemented something like this before.
So a lot of those words were probably at the top of my head.
Maybe secretly I have a dictionary of to the side that you guys can't see.
It's just right here.
So I just have a thesaurus.
Flaming chat clap, says MojoDojo, Turing_k.
Did you finish high school?
I did finish high school.
I do have a high school degree.
That's the beauty of programming.
You can teach yourself how to program, and you don't need an education.
An education is good.
I would recommend people get an education.
But my education has mostly been vicarious.
So you do what is best for you.
I am 27.
Yes.
He'll be 28 in February.
Yes, I will be 28 in February.
I do have a high school degree, but it's worth nothing, maybe
just for the toilets, says Myaocat.
Yeah, pretty much.
An inspiration for online learners.
Yeah, no.
What matters is your skills, and how, to quote David,
"how you are relative to yourself at the end of your journey."
So definitely keep learning forever.
OK.
So I defined a function called drawWord, but I haven't actually-- oh, sorry.
I called a function called drawWord in my update function, or rather
my draw function.
But I have not implemented it.
It does not exist yet.
So we're going to do that.
Function drawWord.
And does the word get chosen?
No, it doesn't.
So we're going to say a local word up here.
So I'm doing this so that every function has access to it.
I'm just not initializing it until we're in love.load.
So I'm saying--
That would explain his lack of music knowledge.
Yeah, because I didn't get an education, my music knowledge
is just absolute trash.
My friend said, beyond degree, they are hired because of soft skills.
Yeah, that's more or less going to be more valuable,
I think, for a lot of places.
Certainly not every place.
Google and Facebook and Microsoft will probably
expect you to have a degree of some kind.
But for startups and a lot of other companies
that are not the big entities, you probably
can get by just by being talented.
Or not talented, I should say skilled.
But yeah.
So drawWord is going to literally iterate over our string,
and just draw every single character.
So what I'm going to do-- and I could've sworn
when I did this before I did this by iterating over a string.
So I have to remember exactly how I did that.
Did I do that with a string, iterating over it?
Because it's been a while.
I thought you could iterate over a string in Lua.
Iterate string Lua.
Oh, right.
Yeah.
Yes.
Totally forgot.
This is a weird thing.
It's about the weird thing that Lua does.
You have to call a--
you have to do what's called string sub.
Well, it's not string sub.
You have to call a sub function off of a string object.
So I'll show you.
So in this case, our word is going to be stored in word.
So I can say, for i is equal to 1 until-- is that how they do it?
Yep.
Until the the length of word do.
So this is going to be from 1 until however long our string ends up
being, which would be from like--
I don't know what the shortest word was.
I think it was three characters.
We did one that was three.
Yeah, fox.
So it's fox.
It's going to be from 1 to 3, or it'll be 1 to 12,
or whatever other ones, the length of a word that we chose.
So from 1 until the end of the word, the length of the word,
we're going to get the character that's actually there
at that index in the string.
So local c is equal to word sub at--
I believe it just takes in i to i, right?
Sorry.
i to i, just like that, which will be 1 to 1, 2 to 2,
depending on what i actually is.
So this will be the individual character there.
And we can draw this.
So I say love.graphics.print.
And then we're going to actually get the c, the character
in c, the local that we created.
And then I can just say local x is equal to,
and then let's start drawing it at like window width divided by 2 minus 180.
Again, not terribly good to have magic numbers like this.
Window height divided by 2 plus 2 is 240.
And then print c at x, y.
And then x is equal to x plus 32.
Xenophobia.
Hey, that actually is like right in the center.
That's amazing.
Roughly, I would say.
Not where we want it to be drawn, though.
So plus 120.
Catastrophe.
And see there it is.
Random every single time.
And it's going to always start here at the left.
And I don't think I'm necessarily going to worry about centering everything.
This is just literally drawing it from that left side first.
But it's not going to be centered.
It's not going to be completely centered.
Maybe if we have time, we'll talk about centering.
We'll talk about how to pad it programmatically
to figure out the length of the word.
It's going to be a little weird, because this isn't a monospace font.
So it's not always going to be perfect.
I think there might be a function that will give us the size of a word.
I think there is actually.
So it wouldn't be terribly difficult, but we're also
not printing the word as is.
We're printing each individual character.
The reason that we're printing each individual character
and not just printing the word out onto the screen
is because we want to only render the characters that we've correctly
guessed.
That means we're going to need to store them somewhere.
So we have to keep track of where the letters are, right?
So when we first start this up, this should actually
be a bunch of underscores, right?
Because we have never actually written-- we
haven't guessed a single character yet.
So it's inappropriate for it to write the word out.
It kind of defeats the purpose.
We know what the word is.
It's catastrophe in this particular example, or immediately here.
And again, the M is just really wacky with this font.
But that's OK.
You can always choose another font, whatever font you want.
You go to dafont.com.
You can choose some arbitrary cool font that you like.
Monospace fonts will behave a little bit better than non-monospace fonts
when you're doing things like this and separating things out
by sort of uniform intervals of space.
So let's go ahead and say, I'm going to have a word,
and I'm also going to have letters guessed.
Just like that.
And what this is going to do is it's going to--
actually, yes, this will be fine.
So lettersGuessed is going to be a table.
And it's going to be empty at first.
And then whenever we actually guess a character,
it's going to index into the table at that character
so we can instantly look up and see whether it
exists, whether it's in the table.
It's basically going to do lettersGuessed,
bracket, whatever character, A, B, C, D, all the way to Z equals true.
And that will allow us to determine whether that letter exists,
and whether we've guessed it already, I should say.
So I'm going to--
not only that, but I also want--
you know what?
Even better, if we can keep all the information together
in our table for all of the letters, and whether they're correct,
unguessed, or not correct if they're false.
So I can say--
we're going to do something like this.
We're going to say, we're going to do exactly what we just did, iterating
over the letters of the alphabet.
So A, B, C, D, E, [MUMBLING].
So this is the alphabet.
I am going to keep it as a string.
And I'm going to say, for i is equal to 1 until the length of alphabet.
Sorry.
Capitals.
ALPHABET do lettersGuessed i.
Sorry, sorry.
Local c is equal to ALPHABET sub i, i.
Again, this sub thing, basically sub just gives you a substring of a string.
You get a start index and an end index.
In this case, i, i will be the same.
So on the first iteration, i is going to be equal to 1.
So it's going to be sub 1, 1.
When you sub 1, 1, it just means, give me the substring
that's from character 1 to character 1.
And so that's a.
If we were to do this at 2, this will be 2, 2.
So i is going to be equal to 2.
So sub 2, 2.
That's going to be from index 2 until index 2 in the string,
and that's the substring b.
Just b, just the second character.
On and on for the length of alphabet, which is 26.
That's going to get us in local c on every iteration
of our loop every individual character.
So I can say then here lettersGuessed c is going to be equal to false.
So we haven't guessed that character yet.
Do I want to do false or do I want to do--
we can do even better than that.
We can say local unguessed is equal to 1.
GUESSED_RIGHT is equal to 2, and GUESSED_WRONG is equal to 3.
So what I'm doing here is this is kind of the idea
of an enum in other languages that you might have seen like Java.
But I'm basically creating these constant values
that are going to map to numbers that I can then assign to each letter here.
And in this case, I'm going to say unguessed.
So I'm basically doing--
so iterate over alphabet, setting each letter as unguessed for word, right?
So this will go over the entire alphabet in our lettersGuessed table,
and just set everything as unguessed.
And then what we can do is we can reference this later,
and we can say, OK, is letter A unguessed?
If so, render it white.
Is it guessed right?
If it is, render it green.
And if it's guessed wrong, then render it red, effectively.
And so this is the framework upon which you're
going to build to get all the letters rendering correctly.
And then, yeah, Myaocat gsub function for replace.
Yep, that works.
Nuwanda, also learning everybody's name, teaching and commenting
to chat at the same time, et cetera.
Fonts are pretty--
Monaco fonts are pretty good, says Bhavik_Knight.
Good to know.
Are we going to change it with an underscore or space since it is used?
Are we going to change it with underscore or space since it is used?
Yes, we're going to take a look at that in just a second.
You have to make sure if in Lua you can compare, like in C,
a character with its Ascii number.
In this case, we're going to be able to compare exactly using equals,
I believe.
It should be just fine, because we're going to substring.
You can compare strings as equal to each other.
So we're going to compare if one individual character is
equal to another individual character.
And what we're actually going to do is we're
going to compare whether an individual character is
in our lettersGuessed table as being unguessed,
guessed right, or guessed wrong, and then do some logic based on that.
And ForSunlight says, that's cool!
Color over.
Yep, that's exactly what we're going to do.
TheDuckThough, says hello.
Hey, TheDuck.
Good to see you.
If you don't have Unicode characters, convert string to byte array.
Yes.
What if you have multiple letters?
Well, we'll see that in a second.
So I have the table.
Everything should still run.
Correct.
Kleptomaniac.
The first thing that we should do is I want to draw the word,
but I don't want to draw the letters if they haven't been guessed yet,
because then that defeats the purpose.
We know the word right off the bat.
So what I'm instead going to do is I'm going to say if lettersGuessed--
remember, this is the table that we just filled dynamically
with unguessed earlier, right?
Every single index is now--
basically, the table is a table full of a A, B, C, D, E, F,
G. They're all equal to 1, which is unguessed.
We did that in a for loop.
I can say now, if lettersGuessed at c is equal to unguessed,
then what I want to do is--
I can do a couple of things here.
I can either set c equal to underscore, or I
can do an if statement for drawing.
I'm going to do that.
I'm going to say c is equal to the underscore.
And lo and behold, now the word is being drawn just
as a sequence of underscores, not as an actual word.
Now what I want to do--
what we need to do is actually look at how
we can start changing this value to be not unguessed, but guessed
right or guessed wrong.
Because if it's guessed right, we should draw it as red.
Sorry.
If it's guessed wrong, we should draw it as red.
If it's guessed right, we should draw it as green.
And if not, we should just draw the underscore, right?
But the alphabet as well needs to be drawn in a different way.
The alphabet needs to be drawn with red and green and white.
Now, currently, it's fine as it is, because all the letters are
going to start off as white, because we haven't guessed any characters.
But pretty soon when we start adding input and being
able to map that input into bringing up letters visible in the word,
we're also going to need to change whether the letters at the bottom
are red or green, because if they're guessed right,
they should be shown as such, and if they're guessed wrong,
they should be shown as such.
Getting key presses.
You can get two key presses at a time.
You can't get two key presses at a time.
Or rather, you can, but it doesn't make sense.
It has to be resolved in some way, either not allowing that input
or arbitrarily deciding on which one it is.
Correct.
Multiple occurrence will be highlighted too when we finish the function.
Yeah.
Two or more equal letters, Cesar, yeah, it's two or more equal letters.
That will be resolved pretty shortly during the actual rendering
of the word.
And we'll see that in a second.
But first, let's actually start changing this table
to not only have the letters be unguessed,
but to have them be guessed right or guessed wrong.
So what I'm going to do is this is all belongs
in the love.keypressed function.
So I can say--
this is something you have to use iteration over.
We have to check to see whether we pressed
every single letter of the alphabet from A to Z. So for i is equal to 1
to the length of--
again, we're going to use ALPHABET do.
Local c is equal to ALPHABET sub i, i.
So again, this is going to get each individual character from A to Z.
And then we can say if key is equal to c.
So if the key is equal to A, B, C, D, E, F, G, blah, blah, blah,
then we have to check to see, is this letter--
not only did we figure out that we've pressed it,
but we need to check to see if it's in the word.
And if it's in the word, then we need to set the letter in the table
to guessed right.
If it's not in the word, we need to set it to guessed wrong if it's not already
set to guessed wrong.
So we can say--
let's figure this out.
So if the key is equal to c, which means from A to Z, then if key
is equal-- sorry.
If lettersGuessed c is equal to unguessed,
then this means that we haven't checked it yet.
We don't know whether it's right or wrong.
If it's right or wrong, then we don't even want to call this code.
We've already either added a part of our Hangman to the screen
and done that and gotten guesses wrong incremented,
or we've already added a letter to our word,
and therefore we don't need to change anything in the table.
The only situation in which we need to actually change anything
is if the letter is unguessed.
And it'll be unguessed by default.
How can I hack Fortnite?
I have an iPad, says TheLastKek.
It's going to-- just Terminal, some Chrome.
Just go to work, you know?
JavaScript, the Chrome Developer Tools.
I heard Microsoft Word is an excellent text editor for hacking Fortnite.
I would do it from kernel mode.
There might be some anti-cheat in place, says TheDuckThough.
Yeah, it's highly-- unless you're already a pro, then in which case,
you might actually be able to do it.
I certainly am not qualified to do that.
I don't know much at all actually about hacking executables.
I know there's a lot that you probably need
to do in terms of like tracing memory addresses and stuff and poking around.
But I trust they probably make it fairly difficult.
Bhavik_Knight says, when a character is guessed in the word,
shown in the letter, and marked as guessed, color change to green.
Same for letter guessed not in the word.
Increase the counter and draw the figure.
Yep, exactly.
So we're getting to all of that stuff very shortly here.
The first step is we're going to actually need to update our table.
And so this is effectively kind of like our database,
this lettersGuessed table.
This is kind of like all of our-- it's practically
the core database of our game.
We just need to keep track of the state of every letter, whether we've tried it
or not, and whether it's wrong or not.
And then another part of the database is, of course, our dictionary of words.
And that's all static stuff.
And then the word itself.
And that's effectively all the data we really need.
And the most important piece is really this lettersGuessed table,
which has the state of every individual letter, whether it's correct,
and whether it's not, and whether it's unguessed.
And we'll see in a second how everything kind of ties to this for the rendering
as well.
For now what you should do is if it's unguessed,
we want to check now to see whether that letter is in the word.
So we're going to say local letter in word is equal to false.
We're going to assume that it's not in the word.
This will just make it a little bit easier.
And then if we find it, we're going to set it to true.
And at the end of checking if it's true, we can set it to guessed right,
and if not, guessed wrong.
And then the rendering code will all reflect this.
So what we want to do is we want to iterate over the entire word now.
So we've iterated over the alphabet.
We're getting through each letter We're over the alphabet in the situation
in which we've typed in a key.
When we find the key that we've pressed, we then want to iterate over the word.
TheDuckThough says, what are you doing though?
You'll see very shortly.
Just the citizenship though.
Paying until, hoping, it is not popularization.
Find the solution and pass it along.
That will save a lot of money.
Interesting.
I think I am out of the loop on that conversation a little bit.
So what we're going to do, we're setting the letter.
We're saying basically, is the letter in the word?
So not only have we pressed the letter.
Not only have we pressed H, for example, but is the letter in the word too?
Because we can press the letter, and it doesn't matter if it's not in the word.
It does matter if it's not in the word.
That means that it should be a red letter,
and we should get a mark off of it.
But we also need to figure out whether it is in so
that we can update the rendering of the word itself,
and avoid drawing more of the Hangman, right?
So I'm going to say, for j is equal to 1, and so the length of word--
so this is just iterating over the word itself, the word
that we've chosen to be our Hangman word.
And then I'm going to say local word care.
So I need to be a little more specific, because we already used c up here.
So the wordChar is going to be equal to word sub j, j.
And if c is equal to wordChar, then letterInWord is actually true.
And this is really all we need to do.
And then after that's all done, after we have determined whether the letter is
in the word or not, we can say if letterInWord, then what we should do
is change our database, so to speak.
We say lettersGuessed c is now not unguessed.
We did guess it.
We guessed right, because it's in the word.
Else, so in this case letterInWord is false.
We should say lettersGuessed c is equal to guessed wrong.
And now this will update our database accordingly.
This has been pretty much all the input checking that we really need to do.
Everything else will update as needed once we update the rendering code.
So let's update the rendering code.
So what we want to do is--
and this will be mostly draw word here.
And also draw alphabet.
Let's make another function.
Let's say drawAlphabet.
Come down here.
Sorry.
One other important piece that we need to do
is if the letter is not in the word and we got a wrong guess,
then we need to say--
what was the variable that I used?
guessesWrong.
We need to increment that.
So guessesWrong is equal to guessesWrong plus 1.
And yep, Bhavik_Knight mentioned that, I think.
Can we do a ternary for that?
Yeah, we could do a ternary for that.
Although, it's a little bit more complicated now
that we've added a second bit of code here,
because there's this statement as well.
So it's a little bit bulky for a ternary.
So probably not.
Probably not for this case.
But yeah, good intuition.
This is the drawAlphabet code that I copied earlier.
And we can actually do is make this a little bit cleaner.
I'm going to say, for i is equal to 1 until the length of the alphabet
do local c is equal to--
I can't type-- alphabet sub i, i.
And then we're going to print c.
Does that work still?
Yep, it works perfectly.
Now, we want to update the actual drawing of our word,
because the word currently doesn't actually--
oh, does it actually?
Yeah.
So if we guess wrong in this case, it'll still actually draw the correct letter.
So we-- is that the case?
Is unguessed-- actually, what we need to do
is just say if not equal to guessed right.
So that will fix that.
Because currently there was a slight bug where if it was guessed wrong,
it would--
actually, well, it would never be guessed wrong,
because it would never be equal to the word.
Yeah, I don't think it actually could ever exist that way.
So I guess it doesn't really matter.
But we'll just say if it's not equal to guessed right.
Yeah, we'll just keep it equal to guessed--
not equal to guessed right.
And if you're unfamiliar to this, tilde equal is the way to say not equal.
And to the people talking in chat, there is indeed not a plus plus or a plus
equals in Lua, unfortunately.
It's quite unfortunate.
But one of the sort of minor shortcomings of Lua, in my opinion,
and also some of the verbosity with the end statement and whatnot,
and the then, and all that stuff.
But altogether, I really like Lua as a language.
It's very simple, and it comes very naturally
if you're coming from C. It's kind of like a C-JavaScript hybrid.
But yeah.
Because Lua is so weird, it doesn't even have semicolons.
Yeah, I'm OK with it not having semicolons, to be quite honest.
Coming from somebody who really enjoys programming in Python,
I could do without semicolons.
So anyway, let's go ahead and draw the actual alphabet correctly.
So the thing is now we should actually be able to draw--
we should be able to guess the characters for our word.
So if anybody wants to guess.
And maybe I'm incorrect about this.
But if anybody wants to guess the letters that are in this word,
definitely let me know.
So M.
M is wrong.
We have the head up there, though.
So it's keeping track.
An E. Two people said E. Oh, it ends with an E. So we have progress.
This is looking good.
A. OK.
Oh, there are two As.
Hmm.
T.
I wonder what word this could be?
O.
Hmm?
I think I have a pretty solid guess as to what this is.
We've seen this word a couple times, actually.
H. C.
Yeah, there we go.
Indeed, catastrophe.
It works great, though.
And see, I can spam the other letters that are incorrect,
and we get our full stick figure.
So it kind of works.
It's good, right?
We don't have a game over, which we need to have.
Once we do hit six characters, we should make this a game over.
And the letters of the alphabet at the bottom
aren't rendering-- aren't changing colors to let us know, hey, is it right
or is it wrong?
We should probably fix that.
But we're on our way.
We're getting close to the end.
So let's go ahead.
I'm going to go to my drawAlphabet.
And so this is where we want to do the actual choosing of the color.
And I'm proactively going to just say love.graphics.setColor 1, 1, 1, 1.
Again, I'm using version 11.
In version 11, colors are in the form of floating point values from 0 and 1.
In version 10 and before, it's in RGB from 0 to 255.
So just be conscious of that if you're using 10.2.
It's one of the minor-- it's one of the largest--
I should say the bigger differences between 11 and 10.2.
I haven't looked at 11.2.
I should look at that and see if they have any good features.
But one of the more prominent features is the changing of RGB values,
the way that they're encoded.
So the next thing that we want to do is change the colors of the letters
when we type them.
So I'm going to say, if c--
sorry.
If lettersGuessed c is equal to guessed right,
then else if lettersGuessed c is equal to guessed wrong, then.
And if it's equal to guessed right, then it
should be-- let's say it should be green.
So I'm going to say, love.graphics.setColor 0.
1 is for the G. 0, 1.
So RGB alpha.
So full green, 0 red and blue, full alpha.
Full green, full alpha.
And then for the guessed wrong, it should be full red, 0 green, 0 blue,
full alpha.
So love.graphics.setColor 1, 0, 0, 1.
So again, let's play--
uh, whoops.
I screwed something up.
What did I screw up?
Oh, sorry.
There is no elseif.
There is an elseif, but it creates a new block.
I had this issue before.
Elseif should actually just be one word like this.
So watch out for that.
"lettersGust" is not a word.
lettersGuessed is a variable, though.
So once again, let's play together in the chat
if anybody wants to "guest" any--
wants to "gust" any letters.
S. OK.
Oh, S is wrong, and it's red.
Isn't that beautiful?
A. A is correct, and green.
Wow.
That's so cool.
Everything worked sort of on the first try.
Uh-oh.
O is incorrect.
M. Oh, M is correct.
Notice M is green.
This is satisfying.
E. E is good.
And there's two, actually.
Two Es.
N and T. Let's try that.
N, T. There we go.
A.
Oh, we've already guessed A. It's green.
It's correct.
Oh, A with a symbol on top of it.
Is that what that is?
I can't see very well.
Chad's kind of far away.
That's funny, though.
I. Oh.
I we already guessed.
Did I spell this wrong?
Because that would be hilarious.
Unless I'm forgetting.
Oh, no.
Right.
No, it's correct.
Detrimental.
There we go.
We win.
And a couple of things that we should also think about.
We need to keep track of when we have won.
That's important.
We need to keep track of also when we lose.
So these are two things, two big parts of the game.
So these are actually in the draw--
in the keyPressed function, we can do this.
So if it is an unguessed letter, then this
will be the only time at which we really trigger a game over.
Oh, it's always going to be on a key press.
This is CS50 on Twitch.
Yeah.
And it's an awesome time playing with everybody too.
That was a lot of fun.
Don't remember now.
Yeah.
Detrimental.
Detrimental was the word.
OK.
So the point at which we trigger the game over
is always going to be in the keyPressed function.
So this is where we're going to add basically
whether we've guessed the full word or whether we've
gotten up to six guesses wrong.
And if we get six guesses wrong, it's a game over.
Will it break if I input A with an umlaut or a--
I can't see if that's an umlaut.
It probably would break, because it will look to see in the dictionary
if that exists.
And it won't exist in the dictionary.
It's got a different Ascii value.
Well, maybe actually.
Maybe not.
Maybe it wouldn't break.
I'm not sure.
I actually don't know if it would work with that character.
No, it just detects A. I'm pressing Alt-A,
which should bring like the Danish A, or whichever
that is that has the little curly thing on top of it.
But Love doesn't detect that.
It's just a detections Option and A. So that's an operating system level input.
If you're using a keyboard that is from another country that
has native support for that, you might be able to test that and see.
I'm not sure.
Try pressing a number.
OK.
Interesting.
A number.
Nope.
Numbers don't do anything.
So it's actually safe for numeric input.
Nice.
Because it's not going to be-- it's not detecting that letter
at that index as unguessed, because it's not going to be in that table.
We didn't populate it with that value.
So it's not going to be true.
So it saves us a little bit of debugging, which is nice.
Anyway, let's figure out whether we've gotten
to a game over, which is going to be here,
where we increment guessesWrong to 1.
So we can say if--
whoops.
We can say if guessesWrong is equal to 6,
then let's just determine that we have a game over flag.
So I'm going to say game over is equal to true.
And if we are in game over, we shouldn't actually
be able to input any of this stuff.
We shouldn't be able to check for the alphabet at all.
So I can say, if game over--
I should say, if not game over.
And then all of this needs to be indented.
Whoops.
Not that indented.
And then else.
And then in the situation that we are in a game over,
it's going to say-- it should say game over kind
of big in the middle of the screen in red text maybe.
And then what I want to do after that is basically
check to see if the key is equal to space, then I want to restart the game.
So that involves basically doing this again.
So setting word.
Basically, what I should do is create like an init function that
just gets everything up and running.
So let's just create an initGame function.
And we'll do this.
So again, we need to refresh our sort of database
of sorts that has whether each character is guessed right, guessed wrong,
or unguessed.
We need to do that.
guessesWrong is going to need to be set to 0.
And word is going to need to be set to a random value.
So I can actually just put it there.
And then I can set it to that.
So create a new word.
Set our guesses to 0.
Refresh the alphabet database.
And then we're just going to call the initGame function
from within love.load.
So we've sort of modularized that aspect of our game.
And so now what we can do is we can just check to see if key is equal to space,
and then initGame again here.
Rather than copying and pasting all of that initialization stuff
that we did up above, just put it in a function,
and then call the function over and over again.
State machines are boring.
Let's go functional, says TheDuckThough.
I think it wouldn't do anything.
I agree.
Blah, blah, blah.
I was thinking of using an API to retrieve from dictionary.com.
Oh, that would be fancy.
Certainly possible.
But yeah, overkill, says Andrej, at least for this example.
Oh, for the state machine.
Yeah, the state machine is a little bit too much for this.
Then play every day and learn a new word.
Yeah, that's true.
That's true, actually.
It would be much more interesting if it were--
it'd be harder to predict, because eventually you're
just going to know all the words.
You're going to have them memorized.
And then you'll just immediately know given a certain letter.
Oh, excuse me.
A certain letter.
I hate yawning on stream.
But getting the-- if you see a certain size,
then you wouldn't-- then you'd be able to sort of predict what it would be
in advance.
And that would kind of defeat the purpose of having a challenging game.
So much better, ultimately, if we did have
a database, or a large dictionary file, or an API, or something like that.
My C version used the dictionary from CS50 Speller.
Yeah, that's totally good as well.
We could do that, something like that that iterates over a file.
Maybe when we do the typing game next stream,
we'll load a file full of words from maybe CS50 Speller even.
And it'll just pick words from that randomly, just load them.
That'll be, I think, much better.
Let me go ahead and get the actual game over logic here.
So game over.
initGame should also set game over equal to false.
And actually, we can just do this ourselves if we go over to initGame
and we say game over is equal to false.
And another thing that we need to do is set game over to--
we just need to at least like declare a game over
appears that is accessible amongst all of our functions.
Otherwise, it'll only be local to the functions that we reference it in.
It'll actually be an undefined symbol, because we hadn't declared it anyway.
No, that's not true.
It would just be a global variable in this case.
Not super useful, not super great.
Cool.
So that's good.
The game over itself needs to be rendered.
So in our draw function, we can just do that in our draw function.
So it can say if game over, then-- and we'll make it kind of nice.
So I'll say, love.graphics.rectangle.
And we'll start this at 64, 64.
We'll set this to virtual width divided--
and also, this should be fill.
Sorry.
Fill.
64 in, 64 pixels by 64 pixels, until virtual width minus 128
and virtual height minus 128.
So it's going to be kind of centered.
And then love.graphics.printf game over.
And actually, love.graphics.setFont.
A huge font.
love.graphics.setFont large font.
And we need to create what huge font is.
So we're going to do that up here.
Where is that at?
Right here.
Huge font equals love.graphics.newFont at 256.
No, 128.
So it's going to be pretty large.
And then we're going to say this should be-- it's going to be printf.
So we're going to center it.
So I'm going to say it's going to get virtual width--
sorry.
This can be at 0.
Virtual height divided by 2 minus 64, becuase it's a 128-pixel font.
It's going to be the span of the--
not virtual, not virtual, window.
We don't have a virtual width and height in this code example.
But we usually do in prior streams.
So I've gotten slightly mixed up from that.
So window height divided by 2 minus 64, which is half of the font size.
And then we're going to say, it's going to fill the window width.
And it's going to center along it.
So when we hit game over, we have to set the colors correctly.
So I'm going to say love.graphics.setColor.
It's going to be kind of a really faded gray.
And then this is going to need to be white.
So do that.
There we go.
So we get a game over, a big game over box
in the middle of the screen, which works great.
And then press Space.
Everything gets completely reverted back to how it was before.
So we can resume.
So game over, space.
It goes back to the start of the game.
What I should do actually is say, love.graphics.setFont to a large font,
which I already actually do.
And then I'm going to copy this line here.
And I'm going to say, "Press Space to Restart."
I'm going to draw it plus 64, and see if that--
there we go.
Cool.
So it's got a nice little "Press Space to Restart" message there now.
So it's a little bit clearer what we're doing.
So nothing terribly interesting.
Just drawing rectangles and text and changing colors.
So all pretty mundane, pretty easy basic stuff.
But pretty important stuff.
Now, the other part of the game--
I thought there was one more thing we needed to do.
Was there not one more thing?
We have the game updating.
We have game over.
tykkoArt, thank you very much for following.
Appreciate it.
I don't think it's easy to implement is the main strong point,
but they're super useful because they're robust.
Of course, it depends on implementation, but the idea
is that you can have only one state at a time,
and the transitions can be controlled.
Yeah.
Yeah, that's the beautiful thing about state machines.
They're very simple so they can be used in every game when there's a start
screen and complicated gameplay.
Yeah, it's just a little bit too much for this example.
For more complicated games, we'll definitely use them.
But there is the downside of the state machine
in that now you have to create a class for every single state
that you want to have in your game.
And so for something like this, the code base, the full code base,
is, I mean, still somewhat long, 216 lines.
But it's not like 500 lines, which I think
is closer to what we were getting with Space Invaders.
So for that, we definitely needed I think
that abstraction layer separating things out
into individual componentized states.
I think that's useful.
In this case, it's not as useful.
Not as useful for illustration.
You should definitely get the material theme for VS Code.
Material theme.
Interesting.
I'm not sure what that looks like.
What does that look like?
Material theme VS Code.
The most epic theme for VS Code.
It's got a lot of download.
Do you get pictures besides just this one?
It's hard to see what it looks like.
2.5 million people can't be wrong.
598,000 installs, 2.5 million downloads.
It's pretty cool.
I'll take a look at it.
Thanks for the recommendation.
Maybe there's better images on Google.
Material theme VS Code.
Oh, this is just the Atom-- oh, is it the Atom theme?
Oh, yeah.
Yeah, it's all right.
I can dig it.
I like the VS Code theme that I have currently.
Although, it is a little bit kind of plain, I suppose.
So yeah, I can see.
I can see.
If you don't-- or if you like bright colors,
the scarlet protocol from the cyberpunk theme.
Yeah, I'll definitely take a look at all these.
These are all nice.
I do like a good theme.
We use states in React, too, right? says ForSunlight.
I think the goal of React is to use the opposite of states and more to keep a--
I guess maybe not React itself.
But I know that in React in the functional world, state is bad,
but I guess a state, a particular state, or at least a global state that you
can toss into what are called--
what are they called?
What's the word for it?
Reducers or transducers, I forget.
Basically, functionalize the aspect of a state, and make it usable in--
like you would pass it as a parameter to objects
and manipulate it like any other variable.
I think that's the goal of React and a lot of functional frameworks.
But don't quote me on that.
My goal this year is to get a little bit more familiar with React,
and maybe ask me later.
And I'll give you more informed insight.
Redux is used for states in React.
Again, I'm going to have to defer this conversation to the future
when I am a more educated person on React.
Unfortunately, I know not that much about it in my personal use.
But it looks super cool.
I'd like to get better at it.
I think that's everything for Hangman.
I didn't think I was missing anything.
We have the game over.
We have all the letters.
We have the words changing every time.
Everything kind of fell into place pretty quickly.
Heliography.
Oh, victory.
That was the last thing we needed to do, right?
Let's do that.
Let's fix that.
I totally almost forgot about that until right there
when I finished spelling heliography.
Shout out to Asli for the donation of that word.
Let's see.
What would be the best place to put this?
Again, it's going to go into our keyPressed function.
And if it's guessed right, this is kind of where we need
to figure out if it's guessed right.
So I guess we could just do a local game one, and kind of have the same idea.
So this is somewhat sloppy, I suppose.
But we could just do, if game over, or game one.
And then here we can do a ternary statement.
So we can say, gameWon AND Game Won, OR gameOver.
So this is the way you do a ternary statement in Lua.
So you'd just basically have a Boolean expression.
GameWon AND, and then the value you want to return if it's true.
And then OR the value you want to return if it's false.
This is the question mark colon that you see in other programming languages.
Lua doesn't have its own version of it, but this is essentially the same thing.
And so this allows us to use the same code,
but we're just going to use a ternary statement to change the text.
Sorry.
This should be game over text, not the variable.
OK.
So we do that.
And then what's the other variable that we need to do?
If not the gameOver and not gameWon.
And then, again, initGame, we need to set that also to gameWon
is equal to false, right?
And then where we actually set gameWon to true,
that's going to be in keyPressed.
So that is up here.
So what we need to do is for--
so we basically-- kind of what we did up here, we're going to say,
for j is equal to 1 until the length of a word do if c is--
sorry.
We do local wordChar is word sub j, j.
Then we say if j--
rather, if wordChar is equal to--
no, no, no.
If lettersGuessed, wordChar is equal to-- or is not equal to guessedRight,
won.
So what we do is we need to say local won is equal to true,
and then we're going to assume we won.
And then when we find the letter that's not guessed right, then
obviously we didn't win.
So we're going to change the flag to false.
So we're going to say won is equal to false.
And then at the end of this loop, we can say
if won then gameWon is equal to true.
Otherwise, just keep it as it is.
We don't need to worry about it.
So let's try that.
Guess the word.
So C is not right.
D is not right.
E, L, M, I, A, T.
Ugh, I'm doing terrible with this.
Oh, it's xenophobia, I think.
Yeah, yeah.
See, this is because I know the alphabet.
There we go.
Game won.
OK.
Cool.
Awesome.
Press Space to restart.
And let's game over ourselves.
Game over.
So everything works.
Everything's great.
We got Hangman all up and running from scratch.
I'm going to commit.
I'm going to get rid of this.
Clear, ls.
Make sure we're in the right spot.
Get status.
Cool.
Get commit.
And Final, or complete, I should say, version.
And then it's push.
So now I'm pushing to GitHub.
So if you are not already looking at the code or if you're already not--
you don't have the repo handy, go to Coltonoscopy--
or github.com/coltonoscopy/hangman-stream.
And there you can download all the code that we just looked at.
So there's just literally a main.lua there,
but it has the entire application.
So you can run this program.
And you'll get the exact same-- assuming you're running version 11,
you'll get the same behavior that we demonstrated on stream.
So let me take a minute now to just make sure I am up to speed with the comments
here.
It's easier to transition from one state to another in a complex game
using state machines.
Yeah, that's correct.
Easy to read, write, et cetera.
It's a very common design pattern.
For example, Unity uses them internally for animations.
You have a graphical representation of states and transitions.
So you can easily set up your own animations and transitions
between them, et cetera.
Yes, exactly.
You can make a game where you have to move a robot in a maze
to detect the wall or the road ahead of the robot and move accordingly.
Yeah.
I ran into them in Unity, but just wanted
to know what I was gaining from them exactly.
They're also great for what Bhavik_Knight mentioned, as in to have
various games states as an aside.
If you're interested, Irene and I implemented
a game Colton's done in Love 2D in his course, Breakout, in Unity,
and we actually used an animation controller as the game's state machine.
Yeah, that was super awesome.
Include the link, Andrej, so other people
who maybe click on it if they haven't seen it already.
Better design, easier to maintain code, as Andrej mentioned.
Yes, indeed.
States are abstractions.
Yes.
An abstraction on the different states literally that your game or a character
can be in at one time, and the behavior or rendering
logic that should change as a result.
Everything is an abstraction if you are not going in there with a jumper cable.
Yes, pretty much everything is an abstraction, for sure.
Are you using Bin/SH?
Not judging.
I think so.
Yeah, I'm not using Z shell or any other fancy shell.
For some reason I've never thought to try and use more than just regular SH.
But I'm sure there are plenty of reasons that I should.
I just have not looked into it too much.
Asli is saying you guys are impressive, in reference to Andrej and Irene.
So this was Hangman.
We did it from scratch, and in 2 and 1/2 hours.
So it wasn't a terribly long stream.
Didn't hopefully put too many people to sleep.
I was pretty confident we'd get it done in less than three hours.
It's not as complicated as Space Invaders.
Everything is drawn with lines and shapes and text.
It's pretty easy.
A little bit of string functions that we had
to look up that I had not remembered, the sub function.
But once we had that in place, everything was easy peasy.
Link to the Git Hub in the article somewhere in there, too.
So have at it if you want to poke around,
says Andrej, in reference to the Unity project.
Yeah, super cool project.
I remember that medium article.
I think we talked about it on a prior stream as well.
Next stream, so most likely on Wednesday,
we will have a typing game that I have to think about.
I'm not 100% sure what I want to do for it yet.
I'm thinking there's a bunch of different kinds of games.
There's like a typing test that we could do.
I mean, someone could enter a block of text.
That could let us talk about word wrapping and stuff
like that, which would be pretty cool.
And then at the very end, it could calculate their speed.
So how fast they were able to type a game, or type a letter.
I implemented a typing test of sorts as a project for the summer version
of the games course that I taught.
That just displayed an individual word at a time.
And you would have to type it.
And it was kind of similar to this in that it
highlighted certain letters as red or green,
and it was actually a lab that we used.
So I could probably do that from scratch, actually.
That was pretty cool.
It just chose random words from a dictionary.
And then you could sort of use it as a typing
test, because it would tell you how many words you got right at the top.
It's not quite like the same thing as a typing test,
because you can't forward look and anticipate things and build sentences
in your head that you can then type.
You're going to have to reactively program-- or reactively type.
And the words are longer, typically.
So it's a little bit more challenging, a little bit different.
So a pretty cool game.
I like that idea.
So we can maybe do something like that.
I think that that is something that I would like to demonstrate.
And then to Sashikant's point, thank you so much for the amazing stream.
Consider the idea of an FPS game in Unity.
For sure, definitely.
We did something like that as Portal for my games course.
It would be cool to do maybe like a kid friendly FPS example.
I would have to do some research and mess with it a bit
before coming on the stream and doing it, because I don't use Unity daily.
I don't use it that often.
And I'm also not really in the Unity space at the moment.
I've been doing more in the vein of web and 2D game stuff.
But certainly in the future, it would be a fun thing
to dissect and take a look at.
Bela says it was fun.
Thanks, Colton.
Thank you for coming.
Appreciate it.
Glad you enjoyed it.
This was awesome.
It was nice that it got finished.
Less than three hours, easier to concentrate, says Asli.
I agree.
Hsin_Wen says, thank you, Colton.
Thank you, Hsin_Wen.
Glad to have you with us.
Thanks for crediting me for the idea, even though I'm not sure
if I deserved it.
No, you definitely deserved it.
I appreciate it.
And anybody that's in the chat, as Sashikant is doing, definitely
provide ideas.
The ideas that are more feasible, I'm more likely to implement more quickly.
Certainly large scale projects are harder
to undertake and to do in a stream or two.
But if it's something fairly bite-sized for a few hours,
we could certainly do that.
Scramble, Bhavik_Knight says, user, user.
That's an interesting idea.
Something like that would be pretty cool.
That's a real typing test.
Reactively typing, says Asli.
Yeah.
See, reactively typing, it's kind of, yeah, kind of
in that vein of more challenge.
But yeah.
Rubik's cube in 3D, says Bhavik_Knight.
I still have to think about how to do that,
because that's a little bit tricky.
Making sure that the things are all in the right state,
the cube is in the right state, and doing rotations,
and making axes change depending on whether you've flipped--
you basically dynamically reassign rows and columns to different axes.
And it's a bit weird.
But it's definitely possible.
Anything is possible, it's just a matter of time.
Time, energy, and dedication.
Typing test where at random there's typos inserted into the text.
That sounds like a real typing test to me.
Fatma is taking the easy way out, says Bhavik.
Oh, yeah.
My comment is equal to everybody else's comment.
Yeah.
But I much appreciate it.
No, Andrej.
Are you the devil?
says Asli in reference to his comment about typos.
Unreal Engine, says TheDuckThough.
My laptop could not run Unreal engine.
But otherwise, it'd be really cool to try out.
Unfortunately, Unreal Engine is ridiculously hard to run on a MacBook.
But maybe if I get an upgraded MacBook at some point that's strong enough.
But I don't think even the more recent MacBook
Pros can run Unreal Engine and stream at the same time.
4:00 AM.
I'm going to crash.
Thank you once again.
Thanks, Sashikant for coming.
Much appreciated.
Good night to you.
Asli didn't comment about Colton's hair for a while now.
OK.
I need a haircut.
I've been saying that for weeks now.
Colton, can you reward your regulars with stress balls or goodies?
says ForSunlight.
Hey, maybe.
Maybe certainly.
I have to figure out a way in which to do that.
Maybe I'll set up a G Form or something.
Yeah, Blueprint is a nightmare for streaming, I guess.
Yeah, it's not that Blueprints are a nightmare.
It's just that the engine is so--
it slows the computer down drastically.
It just has these ridiculous resource limitations.
But Blueprints would be cool.
I mean, it's not as CSy as anything else that we do.
It's visual programming.
It's like Scratch more than anything else.
But it would be cool.
It'd be interesting.
I'm not opposed to doing it.
But it won't be anytime very soon.
I know that much.
Maybe not the most awesome, but pretty awesome.
That would be the most awesome thing ever.
Yeah, well, definitely, I mean, we have some stress balls.
All right.
So if anybody has any last questions before we terminate.
On Wednesday, I'm 95% sure, unless this room is booked,
or unless anything else comes up, that we'll have us a typing test
stream, and then soon an HTML stream.
And then soon a bunch of other streams, and a bunch of other people.
I'll try and get David back in here again.
He did the last stream on Docker.
It was an awesome stream.
Do a little transition back to a wider shot here.
You don't need to see my laptop anymore.
The Hangman stream repository.
Thank you again, everybody, so much for coming as always.
All the regulars, and all the new folks that have come.
And if you're watching this on YouTube, thank you so much for viewing.
We stream every week on twitch.tv/CS50TV.
And if you aren't subscribe to our CS50 YouTube channel as well,
definitely do that at the buttons down below.
And catch some of the other awesome shows and videos
that we produce besides just the Twitch channel.
Is the finite state machine thing happening at some point?
I'm not sure what your referring to.
Are you talking about like a thing that David
was teaching when he was talking about finite automata,
deterministic automata?
Because I'm not sure.
I'm not sure we were doing a stream on that.
Have a nice day, Colton.
Everyone was singing your praises about your soft skill at some point,
but you missed it.
Oh, shoot.
Well, thank you so much for everybody that thinks I have amazing soft skills.
My skills are very lackluster compared to many
of the other very talented, very smart people that I work with.
But I try my best to keep up.
Live coding is definitely good for reminding me
how many things I don't know.
I'll tell you that.
You are the one.
Thank you very much, ForSunlight.
Appreciate it.
We are here.
You mentioned FSM stream at some point.
I'm not sure if that's a plan.
I'll talk to him about it.
See if maybe he does have something in line for that.
I think he wanted to integrate it into one of his other streams.
And he ended up doing a little whiteboard demo.
But I'm not sure about a proper stream on it.
Yeah, we'll see.
I'm not sure.
A lot of this we kind of do week to week.
We kind of figure out based on what people's interests are,
and what they have done, what they know, and what people want to see on stream.
We'll figure it out.
Cool.
All right, everybody.
Thank you all so much once again.
This was CS50 on Twitch.
This was Hangman.
My name is Colton Ogden.
And I will see all of you on Wednesday.
Ta-ta.