SPACE INVADERS FROM SCRATCH (PART 1) – CS50 on Twitch, EP. 17


COLTON OGDEN: All right, hello world. This is– oop, you’re
a little cut off there. This CS50 on Twitch. My name is Colton Ogden. I’m joined briefly by– DAVID MALAN: David Malan. Nice to see everyone again. COLTON OGDEN: Today we’re doing– well, first of all I should say happy
Thanksgiving, happy late Thanksgiving. Hope you enjoyed your holiday if you
were celebrating Thanksgiving here in the US or abroad. We had a bit of a weekend
here but we’re back. We’re streaming today. I just came back. I’m a little tired. I don’t know about you. Did you enjoy your Thanksgiving? DAVID MALAN: I’m very rested,
ready to start the day. COLTON OGDEN: Ready to start the–
you have the hackathon this week. DAVID MALAN: Indeed. COLTON OGDEN: CS50 Hackathon. DAVID MALAN: CS50’s all
night hackathon, 7:00 PM to 7:00 AM later this week on campus. COLTON OGDEN: Yeah. So that’ll be a good time,
an all nighter with IHOP and a bunch of other stuff. Today on Twitch what
we’re going to do is a from scratch implementation
of Space Invaders. Did you play Space
Invaders when you were– DAVID MALAN: I did. When I a kid this was
the state of the art. Space Invaders probably came out a few
years before I really got into games, but this was high tech. COLTON OGDEN: Yeah, this was– oh, and
thanks Jumpjump123 and Lifedevourer22 and DZsniper. I saw that you guys followed before the
stream began, so thank you very much. But yeah, so we’re going to do a
from scratch using Love and Lua, just kind of like how we did
Snake and how we did Memory Game, and what was the– we did one
last one that I can’t remember. Having a brain fart. But yeah, so I’m going
to jump to my laptop. DAVID MALAN: I’m going
to jump out, but I’m going to hop into chat
later and stay in touch. COLTON OGDEN: Cool, cool. Thanks a lot. DAVID MALAN: Good too see everyone. COLTON OGDEN: All right. Oh, and this is funny. You’ll like this, by the
way, before you leave. I made the mistake, and everyone
else from Twitch can enjoy this. I’m wearing a green shirt. So I am wearing an
invisible shirt today. DAVID MALAN: Oh, this is great. So we could actually
see things through you. COLTON OGDEN: Yeah, exactly. A little bit less screen coverage
of me, more of the screen. DAVID MALAN: Such a professional. OK, on that note. COLTON OGDEN: But yeah,
that was a funny thing I realized when I was coming in
here to set the green screen up. Let me just say hello to everybody
before we actually begin. I know we had quite a few people in the
chat prior to everything starting up. So, [INAUDIBLE],, Bavich_knight,
Forcelnight, Fatma, Brenda, Realcuriousqe, thank everybody who– all the regulars I see are here. Nishthegamer, hello! Bavich_knight, hello! Rajeshcanonrk, I think I
have seen that name before. Correct me if I’m wrong. Good to see you. Cloudxyzc definitely has
been here before, hello. Nuwanda3333 is [INAUDIBLE] and Goal1. So thanks everybody who is already here. So yeah, Space Invaders! This is going to be fun. So, Space Invaders we actually taught
in the games course that I teach, GD50. It was a project that we implemented. We ended up scrapping the
project idea from the course for the second iteration of it just
because it was a bit too much work. But it’s a great game because
it’s similar in some ways to Breakout which we
teach just prior to that, because it’s kind of this
vertical oriented game where you play as a
spaceship that shoots up towards the top of the screen. And Breakout is a game where you’re
a paddle that moves left to right and you bounce a ball back
up to the top of the screen. So I sort of feel like the two games
were sort of related in a sense. I think certainly the folks that
implemented Space Invaders probably played Breakout and were inspired. And Breakout I do believe was
implemented by Steve Wozniak although I’m not 100% sure on that. So let’s do a quick old Wikipedia
and just verify whether that’s true. Breakout the game which is here– so it’s by Atari. I know that he implemented
the Apple II version. I’m not 100% sure if he– oh yes, Steve. So he did design breakout for Atari. And then he implemented
it for the Apple II. And from what it says here, it was a
big influence on the actual architecture of the Apple II. So gaming has a huge influence in the
history of personal computers as well. Inolove19 watching from the Philippines,
thank you very much for tuning in. I would like to read your
comments [INAUDIBLE].. I’ll try to comment as much as I can. What did I miss? I opened and David was
already leaving, says Aslee. Yeah, you missed– unfortunately he made
a brief appearance and you missed it. But surely we’ll get him on stream
again, maybe next week even. Jebcochasin says, what are– I apologize if I’m
mispronouncing that name. It could be Yobcochasin or Yobcochosin. What are we going to do today? We’re going to implement
Space Invaders from scratch. So if you’re unfamiliar,
in prior streams we’ve used a framework called
Love2d and a language called Lua. So you can download the framework
Love by going to Love2d.org. So I’m just going to go
straight to that main page. And for whatever operating system
you’re using you can download it, if you’re Windows, Mac,
Linux, or otherwise. And you can download prior
versions, newer or older versions. It’s a super nice, super
easy to use framework that gives you a lot of abilities
to do drawing and input and sound and all kinds of other stuff. So we’ll be using that. I’m sort of going to be assuming that
you’ve maybe watched the prior streams. But we’ll still take it
fairly slow so that folks that are tuning in for the
first time can follow along without too much difficulty. But definitely if you haven’t downloaded
the framework yet, download it here. It’s going to download an
executable that you will then use to run game code. And if you go to the wiki page
which is at the top right, you go to this getting started page. This getting started page
will tell you, depending on what operating system you’re
running, how to actually run your game. So if you’re on a Windows
machine for example, usually the easy way would be
clicking and dragging your game folder onto the executable or the shortcut. But there are other ways to do it. If you’re on a Linux
or a Mac machine, you can alias the location of the actual
executable file and then call that. I have it set up so that in
my terminal, for example– I’m going to clear this– I can just type love dot like that. And that will actually
call the love executable and run it with dot, which is the
current directory that I’m in. So if I’m in a directory that has
a main dot Lua, this will work. It won’t work right now because I’m
not in a folder that actually has that. So by default, if you just
type love or type the path to where it is on your machine
and you have it actually there, you should get a box that looks
something like this with a balloon– if you’re running 11.1, with a
balloon and a scrolling background. So that’s Love. That’s sort of the basics
of how to actually find it and get started with it. Thanks for this game. It’s one of my favorite
games, says Goal1. Yeah, it’s an awesome game. I love the Breakout pset
of old, says Bavich_knight. Yeah, it was a great pset. And I remember, I contributed a
little bit to that pset as well. That was right when I started
working for CS50 roughly. We had a laser part of that
pset if you remember that, and that was the part
that I contributed. Hi everyone’s, says Lintzpotaguara. Hey, Lintz, thanks for joining us. Taking CS50, this is my first
time watching your stream, says Jacobchaussen. Yes, thank you very much for joining. So typically what we do is, we
have a bunch of people come in, people that work with
CS50, myself included. And we usually implement something
from scratch from the ground up or we’ll take a look
at something and we’ll cover a broad overview of that subject. For example, Nick Wong has come
on to talk about Linux commands and machine learning. And we’ve had Veronica
talk about Python. David’s come on to talk about regular
expressions and going from C to Python. So we cover a bunch of stuff. I focus on game development so if you
like games, yeah, game programming, tune in to my streams. And I also co-host with
everybody else that comes in to sort of give a little bit
of a conversational feel to the stream. And I notice the camera shot
is a little bit lower, too, today so you can actually
see the top of my laptop. You can see I have an Inn
and Out sticker representing my home state of California. Virtual office hours, says Fatima. Yes, very much so. Hanscost, hi everyone from Italy. Thank you so much for joining us all
the way from Italy– super awesome. Every time somebody in the chat
says that they’re from some place abroad, someplace that’s
not in the United States, it’s just such a cool feeling to
know that everybody around the world is tuning in– especially
considering how late it probably is over there right now. Although maybe in Italy it’s not so bad. I think in the Philippines,
or was it somewhere else, it was like 2:00 AM or 3:00 AM
typically for a lot of these streams. Curase is from Italy as well. Jakobchaussen just signed up, yeah. Thank you so much. First stream ever on Twitch, wow. We got some new people in today. This is exciting. All right, so Brea– not Breakout. Breakout is the game that we
were comparing Space Invaders to. We want to actually take
a look at Space Invaders. Thank you very much,
Fearblaise, for following. So, Space Invaders was I think
one of the first big arcade games that came out. And this was around the era where
arcade games were kind of like the games to go play. There weren’t really
very many home consoles. Although in 1978 you did have the Atari
2600 which was a very big home console. But just prior to this
for several years there were very much not any console games. It was all arcade games. So if you wanted to play Pong
for example, or other games– typically Atari was the
big contender in this era, although other companies came out. Whoever made PacMan, I forget
offhand, that was a huge one. PacMan was Namco. And that was in– oh, that was in 1980 actually. I apologize. So that was actually afterwards. But this era, the early
’70s until the ’80s and going into the ’90s even a bit,
was dominated by arcade machines. But as the ’90s came about, arcades went
the wayside and now arcades are very rare and almost like novelty– not novelty. They’re the opposite of novelty– antiquated. And therefore they have this
particular unique value to them. But this era was very arcade dominated. So Space Invaders, if
we can get a screenshot. It looks something like this. It’s a little bit hard to see. But essentially, as I
sort of described earlier, you have this ship at the bottom
which is this guy right here. And these things right
here are defenses, barriers you can hide behind,
bunkers or barricades. And your goal I guess is, you’re
defending Earth from an alien invasion. And that’s what all
these aliens up here are. So there’s five rows
of, it looks about– what is that? Like 10, 11, 12– 1, 2, 3, 4, 5, 6, 7, 8, 9, 10– 11 aliens per row. So 55 aliens, give or take. And they sort of go around the screen
left to right in this formation. And they gradually progressed
towards the player. And your goal is to shoot them. And if you take any damage from
them, as by colliding with them or by getting hit by one of their
laser beams, you obviously lose a life. And you get some points every
time you destroy an alien. And so they just come in waves. You clear the waves. It’s this loop of defending
Earth in this abstract form from an alien invasion. Hello from Morocco, says Elias. c4reni– Estonia! That’s the first time I’ve seen
Estonia, I think, in the chat. So c4reni, thank you very much. Georgia, not the state. Hey, guess what? I customized the prompt
after that stream with Nick. I welcome all the new people
tuning in says Bavich_knight. Oh, awesome. Yeah, yeah, that stream was super cool. Definitely watch that
if you haven’t already. And tomorrow Nick is coming in to talk
about setting up a web server with AWS. So if you enjoyed that
stream with me and Nick, definitely tune in tomorrow for that. That’s going to be super cool. Fearblaise, hello from Estonia. Hello, Colton, is there a vacant
job in the CS50 team, says Gaston? Unfortunately there is
not per what we’ve talked about before in the stream, Gaston. So currently there is not. If there is one, there will
probably be a notification on the CS50.harvard.edu website. Jacobchaussen, thank you so much for
following, tuning in and following today. Game history lesson, yes, a little
bit, although my dates sometimes are a little bit skewed because
I don’t study it too reliably. But certainly that rough– I get a rough sense of it,
you know, a rough history. Bavich_knight, Unix
prompt customization, I was patiently waiting for
that in Linux basic stream. I do remember that. I do remember that, sorry. That stream was heavily
dominated by awesome tangents. But yeah, there were a lot
of cool paths we went on. But sometimes it took us a while
to get to some of the things that we wanted to talk about. Redhat236, this is really cool for me. Thanks, Redhat, I appreciate it. And Isotv, finally CS50 time again. Yes, the holiday break was long. The winter break is going
to be kind of long as well. But we have a couple
weeks of streams set up for all of you, so
definitely tune in for that. So, Space Invaders. So, we know what Space Invaders is. So now our goal is to figure
out how we want to implement it. I’m way too zoomed in right now. So, the way that we did this
in the games course– and this is completely from scratch. I’m not using any source code
to reference or anything. We’re just going to completely
implement this from scratch. So if you have ideas as
we’re implementing this, definitely chime in with them. We can collaboratively do this. But I’m not using any
sort of backup code. We’re doing it completely from scratch. But I have a sense of
the things that we’ll need to do, the pieces that we’ll need
to integrate in order to make it work. The first thing that we need
to take into consideration is the fact that this game is
designed to be a vertical game. So the games that we have
looked at so far are horizontal. And we’ve been implementing them with
a 16 by 9 aspect ratio more or less. So today what we’re going to do is
we’re going to actually implement our first vertically oriented game. And games now are not
typically vertically oriented because that would be– it’s not conducive to modern screens. The typical modern screen
is a 16 by 9 raster, meaning that the width to the height
ratio of the pixels is approximately 16 by 9, 16 to nine. So your typical 1920 by
1080 or 1280 by 720p, or many 4k resolutions or the
like, are typically 16 by 9. And you can get ultra wide monitors,
which I believe is 21 by 9. And those are the really
long width monitors, the opposite of what we’re
going to be implementing today. But the game that we want to do
today, since the nature of the game is vertical, just like
Breakout is for example, we’re probably going to want
to do a resolution that’s more catered to this sort of gameplay. And let’s see if they actually
have the resolution, which they do. So we can see here on
Wikipedia if we go over here, the specs are that the display
was a Fujitsu MB14241, which was the video display
controller that they actually had in the arcade machine,
the physical hardware. And it output at a 224 by 256 raster. And what this means is,
it’s going width by height. So normally nowadays resolutions
are wider than they are taller. But this was actually
taller than it was wider, which is why the second
number there is larger– 224 by 256. And so that’s what we’re going to do. We’re going to actually
use the resolution native to this game, the base
resolution, and we’re going to implement
that for our game now. But we’re going to put it in a
window that’s much larger than that so that it does– because if it were on our screen, 224
by 256 pixels, it would be pretty tiny. It’d be hard to see what’s going on. So we’re going to do what
we did in the last stream for tic-tac-toe, where
we actually create a virtual raster using that library
that I showed before, the push library. We’re going to say that that
raster is to 224 by 256 pixels. And then we’re going to
put it into a window that’s about four times larger than
that– actually probably three times larger than that
so it fits on the screen. And what it’s going to
do is, the window is going to be something like
approximately 700 by 800 pixels. And then it’s going to stretch
that to 224 by 256 raster. And basically it’s
going to have the effect of growing all the sprites
and everything in the game by three times its size. And that’s how we can achieve
the sort of retro look while also getting it
to fit on the screen and be playable and not super tiny. OK, let’s see. Apparently Tetris was made in 1984,
so after Space Invaders and PacMan, says Estley. Yes, yes, roughly around the
beginning of the NES era. And I believe it was super
popular for the Gameboy because they actually bundled
Tetris and the Gameboy together. And so that’s why Tetris is one of
the best selling games of all time, is because they take into consideration
that bundling and the Gameboy was just ridiculously high
selling console, handheld console. And so that’s sort of the history
of Tetris and why it also blew up. It was a perfect game, also, for mobile,
just given the fact of how addicting it was and how simple was and
how on the go it was, right? Only game I played was Tetris. I could not handle being eaten and
getting chased, so that’s Forsunlight. Assuming that’s a reference to PacMan. Yes, and PacMan is a game I would
like to very much implement on stream as well another day in the future. So we’ll take a look at that. I’m going to set up a project. So I’m going to go
into my Streams folder. I’m going to create; a new folder. So whatever operating system you’re on,
this process will look very similar. I’m going to call this Space-invaders. I’m going to open that up in VS Code, as
by just on Mac clicking and dragging it over to VS code which I have on my doc. And what that will do, because I
clicked and dragged the folder over, it’ll actually open it up in my
editor as a project, not just an individual text file. And if you’re unfamiliar with VS
Code, this is Visual Studio Code. It’s a pseudo IDE, so
it’s a text editor but it has some IDE features like debugging
and a really good plugin system. And it’s very heavily developed. It’s sort of the contender with Adam. And Adam is also a
very good text editor. Sublime is also another
very good text editor. Those are sort of the three big ones. So if you’re looking for a text
editor, VS Code and Adam are free. Sublime Text is sort of free in that
it’ll bug you with a prompt over and over again if you
haven’t bought it to register but you don’t technically have to do so. I prefer vS code, so that’s what
I’m going to be using today. It wants to install a helper
tool, so I’m going to deny that. And also a great thing about
VS Code which I’ll demonstrate is that it gives me the ability with a
certain plugin to just hit Command L, and that’ll load the game into– command L for Love, I guess. It has a integration with Love such
that it will load my project in Love without me having to go, say, to the
terminal and type Love dot every time, or go to my desktop and click
and drag the folder over to the executable, which is what you
would have to do in Windows if you don’t have a similar setup set up. So, I’m going to create a new file
on my project called main.lua. Folks that have been to the
stream already know this process. But new folks, this is the
entry point for a Love 2D game. I’m going to title it
with a comment block. I’m going to give it an author. I’m not the actual author of
the original game Space Invaders but I’m the author of this clone. So this is a comment block in Lua. So just dash dash square bracket square
bracket, just like the slash star in C or in JavaScript. And then I’m going to just
create a few functions. I’m going to command b to
get rid of my sidebar there. So these functions are functions
that are part of the Love framework. They are called by the Love framework. Every frame, or in the case
of Love.load, just once at the beginning of your application. And these are functions that almost
every single Love project will have. You don’t technically need a Love.load
load definition in your game. For a lot of games– well, some games– you
don’t necessarily need love.update, for example the tic-tac-toe
game we implemented last week. You can do it with
Love.update, or you can do it with Love.keypressed which is another
function that we will probably need. So Love.keypressed takes a key. And so these are kind of
like the base functions that are part of the Love 2D framework. These are functions that Love
2D will just sort of call. It’ll look for these functions by name. So it’ll see whether I’ve implemented
a Love.load function, whether I’ve implemented a Love.update function. And if I’ve implemented
them it’ll call them in a function called Love.run,
which is actually hidden but you can override it yourself. And Love.run basically
is just a function that gets executed as the main game
loop of a Love 2D the application. Ba ba ba ba, Bavich_knight says, Vim. Vim is another text editor
that you can definitely use if you’re comfier
with the command line. It’s got a bit more of a learning
curve than Adam or Visual Studio Code. But if you’re comfy with it you can do
a lot of really cool things with it. People upload what are
called their Vim RCs to GitHub which allow you to customize
how it behaves, sort of the shortcuts and the appearance of it. I’m not a Vim user but David,
for example, is a Vim user. So if you’re into that aesthetic
and into a more command line oriented approach to
development, definitely check Vim. Vim is a great text editor. So we have the main
functions for our game. The first thing that we talked
about was the actual setting up the resolution for our game. So that’s what I want to do. I want to create a virtual
width and a virtual height. And actually, because we’re going to
be doing things a little bit more– this is going to be a
little bit larger of a game. And I should preface this
whole thing by saying this might take more than one
stream because this game is somewhat complicated. Because of that, because it’s
going to be fairly complicated, I’m going to be a little bit smarter
about how I organize my code today. So rather than starting to
declare all of these constants, that’s why they’re capitalized. They’re going to be
values that don’t change. Rather than declare all of these
constants at the top of the main .lua file, which is sort of bad practice if
you just clump all your code together in the main .lua file, I want to create
a separate file called constants.lua. And this will be where I
can, as this name implies, put all of my constants, all of
my variables that will not change. And there isn’t technically
a constant semantic in Lua because Lua doesn’t enforce
constant variable assignment. But by sort of saying, oh,
these variables are capitalized and these underscores, as is the common
notation in most programming languages, we can, as programmers, sort of
mentally declare and associate these variable names with the idea
of those variables being immutable, meaning they shouldn’t be changed. And that’s sort of what you
should do as a programmer when you’re using a
dynamic language and you want to use these constructs that
are more common in other programming languages. You want to use proper
variable naming, right? So virtual width and virtual height–
so the virtual width and virtual height are going to be the height and
width of the arcade machine as it was developed originally, right? So the width of the arcade machine
was 224 and the height was 256. So I’m going to say the
virtual width should be to 224 and the virtual height should be 256. As you can see, that
means the width will be smaller than the height, which means
we’ll have a more vertical looking window when we actually load the game,
when we actually render the game. I’m going to take these declarations. I’m going to remove them
from main.lua and I’m going to put them in my constants.lua. And these variables,
because I haven’t specified what’s called local scoping on them by
writing that, this means that they’ll be accessible within any source
file, any main file, or any Lua file, that requires that source file. So for example, if I
say require constants, this will load all of the global
variables from the constants.lua file into my main .lua file. So it essentially has the same effect
as me copying these and putting them into here, effectively. SmartScreen is prohibiting the
execution of the editor installer. Also there is only a Vista
plus version, says Gaston119. Are you referring to VS Code? And then Bavich_knight
says, more modularized. Yes, more modularized. Modularization is a very good
virtue in programming generally. Making sort of building blocks
of your code and building blocks of your project in terms
of source code files, tends to make things easier to debug,
makes it easier for other people to work on separate pieces at a time. So you want to typically do that. For small projects like we’ve done
with tic-tac-toe and with even Snake and the memory card game,
those are small enough such that you don’t have to worry
so much about these ideas. But it’s good practice. Anything that’s larger than
100 or 200 lines of code, generally you want to think
about breaking that up into separate modules, a module
being a piece of code in a text file. But it can also mean
a class or a function. It just means building blocks that you
can assemble and use interchangeably. OK, so we’ve done that. So we’ve put our constants
into a constants.lua file. Another thing that I want to
do is, I want to actually make a window within a window height. So we have a raster. We have a– basically, you can
think of drawing to a texture almost, that we’re going to
expand to fit some window size, an actual window on our desktop. Because our window, we don’t
want to actually render a native 224 by 256 window onto our
desktop because that’ll be super small. We won’t be able to play it. I want to declare a separate window
width and a separate window height. And I don’t really want to
think too hard about this. So what I’m going to do is, I’m just
going to say virtual width times three. I’m going to say virtual
height times times. And what this will do, is the
window height and the virtual width and virtual height will always be
three– well, they won’t always be, but they will at the
start of our application be three times the size difference. So this will allow us to zoom
in while retaining the aspect ratio that we have established. Another thing we have to do
is, I want to use that library, that virtual raster library
we used last for tic-tac-toe, which was a couple weeks
back actually, called Push. And so if you’re unfamiliar,
the Push library, you can find it easily on GitHub. So Push library Love 2d,
it’s GitHub.com/ulydev/push. I happen to already
have it on my machine but you’ll see an image that
looks like this demonstrating how they’re rotating that high text. And it’s staying pixilated. It’s not interpolating. It’s actually being rendered at
this 50 by 50 pixel resolution while being zoomed in
so that we can actually see it like it’s a retro zoomed
in look on our machine, right? I’m going to use the version that
I already have on my machine, so it’s in my lib folder. I’m actually going to copy this lib
folder from the tic-tac-toe project. So I have a lib folder
with a push.lua in it. If you download this library
you’ll get a push.lua. That’s the file that you
want from that library. I’m going to copy that lib folder
over into my Space Invaders folder right now. So now in my Space Invaders project,
if I go back to here for example, I see I have a lib folder with push.lua. In my main I can say, at the very
top, push equals require push– sorry, lib/push. And remember, when you’re requiring
something in lua you don’t need to say .lua. It’ll infer that you’re
referring to .lua. So you can just say, lib/push or
constants, just the string constants, and that will have the same effect as if
you were saying require constants.lua. All right, now what I can do in
my Love.load function– remember, this function happens one
time at the very beginning of the applications running. I can say push colon setup screen. So, colon just means on the push
object, which we’re initializing here, so requires returning
essentially a table. But push, a table that has a
function in it called setup screen. And I’m going to say, push colon
setup screen virtual width, I’m going to command b to get rid of
that virtual width, virtual height, window width, window height. And remember, these variables
were in constants.lua. But because I required it, they’re
actually visible within my main.lua. I’m going to say full screen is equal
to false, Vsync is equal to true, and resizeable is equal to true. So Vsync just means it’ll
sync to your monitor so you won’t get screen tearing
if there’s any scrolling. It’s not really something that
we’ll have to worry about here. Full screen just means we don’t want
it to be full screen because that’ll be a little bit weird looking. And then resizeable just
means that if I want to resize it during the
games running, I actually can and it’ll resize accordingly. And if I go into my update function– sorry, not my update function,
in my draw function I can say, push start push finish. And whatever happens between start
and finish on the push library will get rendered at
this fake resolution. If we decided to draw something
without it being within the push start and push finish, it just
draw to the native window, the window that we’ve
declared was three times the size of virtual
width and virtual height. So anything that we want to draw at this
retro look, this 224 by 256 resolution, almost like we’re drawing
to a virtual arcade machine that we’re then rendering
to a proper window, we want to do it within the push
start and push finish function calls. And we can test this by saying
love.graphics.print hello– actually, we’ll just say Space Invaders. I think we’ve done hello
world already before. And if everything goes according
to plan and if I run this, I have a syntax error on
line 13 which is– oh, I accidentally put a period
there instead of a comma. Don’t do that. If I run it, now we see indeed our
game window is vertically oriented and taking up the majority
of my screen actually. Hopefully it’s not– I think it actually is just ending
at the bottom of the screen. So it be OK. That should be just the right size. I can’t tell if it’s super
visible on the stream itself but the text for Space
Invaders is actually blurry. It also doesn’t have a window
title and I can’t quit with escape. So those are a few things that
I probably want to add to it. If you notice, if you’re running
anything with this push library and you notice that the text is blurry
or anything that you draw is blurry, that’s because you have filtering
enabled on all of your textures. So love.graphics.setdefaultfilter
nearest and nearest will fix that. So that’ll set the filter
of anything that you render to the screen, or anything that
you load and then render to the screen after this function
call, to nearest neighbor filtering meaning that
it will be pixilated. Jebcocheson, if you are using VS
Code make sure that you have the– let’s see, where is it? This is the extensions. The Love 2D support by Pixelbite Studios
will allow you to command-L or Alt-L if you’re on a Windows machine. But you have to have the Love
binary in a specific place. Wherever you do have it, if
you click on the cog menu here you can actually– oh, the
cog menu doesn’t work there. If you go to the settings, which is– I don’t think you can access
the settings from here. It doesn’t look you can. So you actually have to go to
your preferences, settings, and then go to your
extensions down here. It’s a little bit because
I’m running at seve– my computer is at 720p so everything
is a little bit zoomed in. But eventually you’ll see Love 2D. Oops. And the Settings menu is also
super jammed full of stuff. Let me see, where is it? CSS– oh, right here, Love 2D config. You’ll see that there is a– ba ba ba ba– a default location
that it will expect it in. If you just have it in your
applications folder on a Mac it should work normally. If you’re on a Windows, it sort
of expects that Love exists at C:/programfiles/love/love.exe. So that’ll be where, I
think by default if you just get the installer for Windows,
it’ll install it there. And on a Mac, just make sure that
it’s in your applications folder. So applications and then Love.app
whatever it’s named by default. And then it’ll know that
it’s there and it’ll work. But yeah, that’s how you get it to work
in Visual Studio– in VS code, sorry. If you’re on a PC, you can
do the same thing in VS Code. But if you want it to
run at the command line it’s a little bit
complicated with Power Shell. You can click and drag your folder
over to the shortcut on your desktop but it’s a little clumsy. So I’d probably recommend
getting this configured, downloading Love, installing
it through the installer, and then using the alt L shortcut
with the Pixelbite extension. So definitely take a look at that. Now let me zoom back in a little
bit just so that everything is a little bit clearer on the stream. Actually, is this still
clear, still relatively clear? Because it’d be a little bit easier
to fit code onto the screen, I think. So let me know if that’s
still pretty visible. That bottom left gear stuff
on VS Code is Settings. Right– oh, right here, yep. The code right here– or, the settings right here. But yeah, that’s how you
do it on Windows and Mac. Awesome, Jacobchaussen, if
I’m pronouncing that right. I apologize if I’m not. Glad you got it working. Seafloorrenny says, it’s OK. OK, but basically now I can hit
Command L. And now it’s more pixilated. On my preview of the
stream it looks the same as it did when I ran it without
filtering, maybe a little bit crisper. I’m looking at a somewhat
small preview of it. But you should have seen a difference
with the default filter function call, so definitely set
that if you haven’t already. A couple of other things that we can do,
Love.window.settitle to Space Invaders. And then, in love.keypressed
I’m going to say, if key is equal to escape
then love.event.quit. So love.window.settitle
as its name says just sets the titles, so the title bar of
your application so when you run it it doesn’t say untitled, which
just looks a little bit sloppy. And then this live.keypressed
function will fire every time you press any key on your keyboard. So you can define the behavior that
you want Love to sort of determine when you press a key. You can check which key it is
but he’s using an If statement. So if the key is equal
to the string escape– all keys are given a string value,
so for example any of the letters, the individual letters
or numbers on your key, would register as that particular key. Space, enter, return, tab,
alt, option– all these keys have a string value that you can call. I’m going to say if key is equal
to escape, then love.event.quit. And that will have the effect of, when
I run the game I can press escape. Also notice that the top of the
window has the Space Invaders. Asley says, still looks
pretty blurry only to me. Perhaps a different font
would be less blurry. Yeah, so what you’re seeing is
the aliasing in the default font. So it is blurry and in a sense. It’s not filtered blurry, so it
doesn’t have the actual fined tuned– or that, not fine tuned, but it doesn’t
have a higher resolution blurriness to it. What you’re seeing is the individual
pixels are just different colors. But you are seeing individual
pixels now at a zoomed in level. And yes, that’s because this font does
have different color pixels to give a smoother appearance, or
more rounded appearance, when you’re actually viewing it at
a native resolution on your monitor. So it’s not conducive
to zooming in but it is more appealing to look at when
you’re viewing it at a smaller level. So yes, we do want a different font. And we can do that, as we did
last week, by going to dafont.com. So we go to dafont.com
and I go to pixel fonts. You can browse a lot of these in
pixel/bitmapfonts section right here. You can browse all kinds
of cool different fonts that are all pretty retro looking,
and all their different licenses are here on the right. So you can see some of them
are 100% free, for example. Some of them are free for personal use. You can’t use it in a
commercial project but you can use it for your own projects and
not worry about getting into trouble. Some of them are public domain. Some of them are– all of these are
actually pretty generous. Some of them are not free and you
have to actually pay for a license. This one here looks like a
retro sort of Western font which is actually pretty cool. So if were to make like a pixilated
Red Dead Redemption or something, that would look nice. I’m going to choose a font that makes
it look kind of like NES font, I think. Something like Press Start To P is
pretty good– press start to play. Let’s see, what’s a good font? So, Space Invaders has sort of this– well, I guess that era, the Atari arcade
era, had a sort of vectorized look. So the fonts were all
kind of angular looking. So something like this would
actually be pretty– or not this, not Visitor but– well, I guess Visitor. Visitor would be pretty appropriate. It’s 10 pixels. I kind of want an eight pixel font. 04B03 is actually a pretty good font. I kind of like that one. That’s one I think I actually
used a lot in the games course, because it had a nice look
and it’s eight pixels. Pixel Aerial 11– so on the last one,
I thought I saw on an NES looking one. I think I might want to use that one. So, which one was it? Was it this one? No, this is pixel mix,
free for personal use. It was Minecraftia, very
appropriate, eight pixels. Retro Computer, Press Start to Play– we’ll do this one. So the Press Start to Play
one, I think that one’s good. So I’m going to grab that one. Oh, it looks like I
already downloaded it. So OK, that’s good. I might have actually used it last time
in the last stream for the tic-tac-toe, actually. Fonts, 8-bit– oh, 8-bit
and Press Start to Play. Yeah, I think I did use it last time. So, in my Space Invaders folder
I’m going to create a Fonts folder. I’m going to then paste that font
in there, the Pressstart.ttf. You’ll get a ttf file from dafont.com
typically when you download a font. And so that’s just the file that
you need to have to use that font. And then if I go into
my project, I can say– after I do the filter, set the filter,
because if you do it before the filter your font will be blurry,
I can say gfonts– or, I’ll just say gfont equals
love.graphics.newfont and then fonts/pressstart.ttf. And then I can say,
love.graphics.setfont to gfont. So the lowercase g is
another semantic sort of token I’m adding to
the symbol of the variable to basically tell me that
that’s a global variable. I should know that whenever I see
gfont, it’s accessible anywhere in my application. And this is to help me from
clobbering different variables and using global
variables unintentionally, or using local variables as
global variables unintentionally. So whenever you use a
variable that should be accessible throughout
the whole application, try in a dynamic language
like Lua, typically try to use something to differentiate it,
to make it clear that it’s global. So that lowercase g is
intended for that purpose. Whoa, this stream just reset for
some reason– or the chat reset. I accidentally went backwards. And because I went backwards, I
got rid of the chat in the monitor that I’m using to the side. So I’m going to use my other monitor. Ba, ba, ba– Space Invader, the
editor fonts are fine. Out of interest, how much do you
prepare in advance for these streams and how much of this syntax do
you know by heart, says Isotv. So, for a lot of these games streams–
so, it depends on the stream. So, for the Unity one I did
a lot of prep in advance to make sure that I
understood what I was doing and all the different corner
cases that I could run into. And it turns out I still ran into a few. Thankfully Andre and Irene are
typical regulars in the chat and they kindly helped me
out with a couple of things I stumbled upon unexpectedly. But for a lot of the
Love and Love 2D stuff, I actually don’t do much prep in advance
because I’ve done a lot of this stuff before. So Space Invaders, for
example, I programmed before in the spring for the
games course that I taught at the Harvard Extension School. And for tic-tac-toe and for
memory game and for Snake, they’re simple enough games
that don’t really require a whole lot of thinking in advance. Now, there were some
situations where I did stumble upon an algorithm or a
piece of the algorithm that I had to think about
a little bit on stream. But I think that also there is a
double edged sword in prepping and not prepping. So, by not prepping you
do run into those cases where I don’t have the
code in front of me so I don’t necessarily know
what I’m going to run into and I don’t necessarily know
in advance the algorithm and I don’t have something
as a crutch to fall back on. But if I have a strict
script to follow, then I have no real opportunity
to go off on a tangent or to explore a different
way of doing things or to take suggestions for the
chat or to change fundamentally how the game is working because
if I do that, then the game has strayed potentially away from
the original goal of the stream. And that won’t work super well live
and be a super conversational system. So the intention for these streams is to
be much more conversational and casual. And so for a lot of these, there is
nothing really prepped in advance per se, aside from some research
and for the Unity stuff I typically tend to do a bit more prep. Now, for certain streams, like
David does a lot of prep in advance and we have more of an outline that we
follow a little bit more rigorously. And for some of the other streams
we’ve done it’s been that way. But mine are a bit looser. So, thank you for the question. Yeah, because I’m getting the
same error on line seven saying there’s unexpected syntax
near the parentheses. I only wrote commas. Unexpected symbol near traceback
in the function require. Function [INAUDIBLE] function
XP call main net seven. Post your code on pastebin, I’ll
take a look, says Twohourstrike. Line seven, push setup screen– so make sure that setup screen is
getting a capital S for the second S. Virtual [INAUDIBLE],, virtual width,
window width, window height of– you do have a redundant comma
there in your function calls. So at the end of window height
you do have an extra comma. So that’s what Twohourstrike said. Search Space Invaders
on dafont, says Karalse. Sure, let’s do that. I actually didn’t think to do that. So, with Space Invaders– oh, that’s cool. They have a font that’s
actually made out of aliens. So that’s interesting. That’d be an interesting way of
actually making a Space Invaders game, would be only with fonts. It doesn’t look like it would be
necessarily possible because it doesn’t like they give you the spaceship. I guess you could construe the third
alien as a spaceship, in a sense. But yeah, that’s a cool font. Thanks for tossing that in. You’d use that font instead
of sprites, Karalse. Yeah, in a sense we could. But the problem with
that is that then we have to worry about drawing
these sprites, the text objects, in sort of weird– first of all, we’d have to
call love.graphics.print. And we would have to know which
character maps to which sprite. So we’d have to say– it’s probably something like
0, 1, 2, 3, 4, 5, 6, 7, 8, 9. So we’d have to say, love.grapics.print,
the string 0, 1, 2, 3, 4, 5, 6, 7, 8 or 9. And then we have to give
it an x or y-coordinate in much the same way that we would have
to do with a actual graphic object. But no, it could work. And we could get coloring through it. But I don’t think this is an
approach that you would typically see outside of a console game. So if you were, say, implementing
this at the CLI like this, then it would kind of make sense– or I guess a– well, I guess maybe it wouldn’t work
necessarily for a typical shell. But you could emulate a shell in Love 2D
as by something like a roguelike game. And rogue like will do this
a lot, where for example– let’s go, if we go to Images, roguelike. So the typical roguelike
is an ASCII game. Your typical classic
roguelike looks something like this, where all of the game
is actually rendered using text, using ASCII text. And nowadays, roguelikes can be
implemented using Unicode text as well, and that’s a much more flexible
option because then you’re not limited to just– how many characters is in ASCII? Is it 127? I don’t remember offhand It’s
either 127 or 256, one of those two. Or actually, it might be less. It might be 7-bit. I don’t remember offhand. But you can only render a very
limited set of characters in ASCII compared to what you could do with
a Unicode text file, for example. But yeah, you could do something like
this, run this and make a virtual shell and then have those guys move around. It’s just a little bit strange. I don’t know if I would typically–
you could technically do it, but it’s kind of a roundabout
way of getting that behavior. It’s much better to actually
use sprites, I think. I would imagine that would be
a much better way to do it. What is an EOF error? Says, EOF is expected near end. It means that it’s finding the End Of
File without an end statement, I think. You are not ending your function or
an if statement with the end keyword. So notice that for every if statement,
like we only have one if statement now. But notice that I have an end
keyword that ends this if block. So every if block needs to
have an end at the end of it, to sort of be the start
in the end syntax. And whatever was within that is
the body of code that gets executed if this if condition is true, right? And every function similarly
has an end keyword to tell Lua, this is the start of
the function and then the end means that it is
the end of the function. If you don’t have a
matching start and end– 128 ASCII says. OK, so it’s a sort of limited unsigned– what would that be? Yeah, 7-bit– 7-bit unsigned. If you don’t have an end key for every
function, then that’s a syntax error and you’ll get an EOF issue like
you tossed in the chat there. You could use that font as sprites. Those are seminars, prepped
and planned, says Fatima. Yes, yeah, those are seminars. And to a degree these are
kind of similar to seminars in spirit, just a little bit looser
and a little bit more conversational. Raw, live coding, yes. I think it means you have
redundant ends somewhere. Perhaps– oh, and that’s true too. You can get an extra end and
get an error similar to that. I don’t remember the syntax
differences between the two issues. But yeah, one of those two
is likely the situation. Mkloppenburg– oh, and Andre, perhaps
the font could be used in text. For example, instead of kills you could
have an alien character or something. Yeah, that’d be cool. That’d be cool. Mkloppenburg, be late to
the show and of course I won’t be able to watch everything. Will watch it later on. Keep up the good stuff, Colton. Thanks, Mkloppenburg,
for tuning in as always. Hope you tune in on YouTube afterwards. So kind of like curly
braces, says Isotv. Yes, exactly like curly braces. Lua does not have curly
braces, which is nice because I’m not a fan of curly braces. I’m also not a fan of the end keyword. I’m actually much more of a
fan of the way Python does it, with enforced blocks,
indentation blocks. I think that’s a much
cleaner way to do it. But Lua is still nice enough of a
language where it’s not a huge deal. But typing these end keywords
can be a little bit too much. And also the function
word, I just think Python does things a lot better
in a lot of ways, so function being deaf and not having ends. You do need colons in Python, which
is something, an extra bit of syntax. But it’s a very small thing
so it’s not a huge deal. And then end would be like a semicolon? Yeah, kind of. The end is a little bit more
like a closing curly bracket, you could think of. OK, so we’ve been at
it for a little while. And now that I reload
the game we see that we do have Space Invaders being rendered. It’s a bit large. It shouldn’t be that large. And that’s because by default
Love assumes that we want our font to be, I believe, 16 pixels. So if I just specify eight
pixels when I actually create the font in the
love.graphics.newfont function call, it will make it much smaller. So now it is indeed an
eight pixel size font. Is that eight pixels? Yes, I do believe that is eight pixels. So, similar to how we had it before– I apologize if I keep hitting my mic. I don’t think I am. I think I’m hitting my jacket. But now the font object is
smaller, it’s not supermassive, and we can get on with the actual
implementation of the game, of the moving around and
the aliens and whatnot. So the way that I liked to do it
for the games course that I taught was, I kind of liked the
randomization approach to it. And so there is a sprite generator– and I don’t remember offhand,
actually, which website it was. It’s not a CSS sprite generator. It’s like a retro sprite generator. Had to look for it. I don’t remember the exact URL offhand. Is it this one, the Ludum Dare one? Could be this one. Sprite generator– oh
no, this is the Java one. There’s a sprite generator
that’s an actual web application. So sprite– pixel sprite generator– pixel art sprite generator maybe. Is it this one? Nope, not this one. I apologize. I might have to find the URL for it. Where is it? There is a URL that
actually makes aliens. Oh, I think it’s a robot
sprite generator, maybe, or alien sprite generator. Crap, where did it go? This is used to be like an instant
top of the Google results search. I might cheat and go back to the– so I have the source code for the
actual Space Invaders that I did. I should. Dev– it’s not in summer. Crap, where was it? [INAUDIBLE] project zero–
that wasn’t a project. I apologize. I’m going to find this. We’re going to find this. Sprite generator, alien–
is this going to work? I hope they didn’t remove
it off of the website. Ba, ba, ba ba. Kind of embarrassing. They had a whole website that was– retro pixel art sprite generator. Forsunlight saying hello, everybody. Any good sprite generators out there? So this is why prep is sometimes good. This was like a top Google search
result. I have no idea where it went. Randomized sprites– no, not ALTTP. Is it this one? Here it is. OK, so I just had to
type randomized sprites. So, sprite generator wasn’t good enough. But this is what it is. So, it’s a website,
IMG.uninhabitant.com/spritegen.html. I can toss that link in the chat, or
I can at least write it in the chat. Unfortunately I’m not in the
chat logged in on this account. So IMG.uninhabitant.com/spritegen.html. So you go to that link. You can generate your own sprites if you
want to generate them and follow along. Do I like these ones? These ones are pretty good, right? And these aren’t zoomed in, are they? Zoom level one, size 16. Do I want 16 or do I want eight? So this is cool. You can actually customize all of
the parameters for the generation. So down here– oh, and you can
choose the color palette, too. And by the way, color palettes
are a huge thing in sprite art. If you’re not familiar, color palette
is basically a limited set of colors that you can draw from
to create your sprites. And this was a physical limitation
of hardware back a long time ago. Nowadays, it’s obviously not. You can do whatever color you want. But if you want a
homogeneous, if that’s– I always don’t know if it’s
homogeneous or homogeneous. But if you want a
homogeneous/homogeneous look to your artwork, you can define a– oh, Realcuriousqe, the video is about
30 seconds behind the chat for me. Let me type this in. It’s already there. Yeah, I’m just ahead
of the curve, you know? Just, that’s just how we do it. But no, palettes are a
limited set of colors. So you have eight colors,
16 colors, 32 colors. Generally the smaller number of colors,
the more distinguishable the art is but the harder it is to make
things look the way you want. But these are all very
famous color palettes that you can choose from–
so NES, for example, Gameboy. Dawn Bringers is a very huge palette
in the online sprite art community. So he has several different
palettes of 16 and 32. We used the Dawn Bringers
palette in the games course that I teach, Commodore
64 being another one. And Arnie’s is another
really famous one, actually. Arnies and Dawn Bringers are sort
of at odds with each other, I think, so they sort of compete with each other. I like Dawn Bringers. Colors per sprite, so this is colors– not three colors total but
just three colors per sprite if you want to limit
the number of colors that each individual sprite can have. It’s a cool limitation. I’m going to say four colors. Background color index
zero, that’s fine. We’re going to say the
size is going to be– do I want eight pixel aliens or 16? Chat, do we want eight pixel
sprites or 16 pixel sprites? You’re logged in your Google
account, says Bavich_knight. Yes, I am. It always happens to me too,
[INAUDIBLE] blah, blah, blah, blah. Eight, eight– this is around
the world, bits traveling. Fatima says yes, eight. So we’ve got three people saying eight. Whole time it was my internet problem. It was all in the streams,
says Bavich_knight. Yeah, the stream will take about– it depends on how far
away you are, I guess. Here directly in this room
it’s about two seconds. Between here and another place kind
of locally, or within the states, it’s typically seven or eight seconds. And I imagine super far away it’ll
be probably closer to 15, 20 seconds. Yeah, New Zealand, 30 seconds. So we have four people
saying eight pixels. So I’m thinking eight pixels probably. So I’ll go ahead and
make that eight pixels. And I think I actually did that
for the Space Invaders game that we implemented for the spring. So I think it’s apt. Let’s just make sure
everything looks good. No scalar, zoom level one,
16 tiles, four pixels apart– and I think that that is– actually, do I want spacing? No. Zero pixel spacing, I want
to be able to slice these up. All right, let’s generate. Whoa, and that is tiny! OK. So, if I save that image,
save that in the right place. Go to streams, Space Invaders. I’m going to create a new
folder here called Graphics. And then I call this aliens.png. And I just went wit whatever this
first result is, and a lot of these are going to look a
little bit weird probably. So Space Invaders, graphics, aliens.png. Let’s open that and let’s
zoom in, see what we got. It’s sort of like the
lottery because we have– wasn’t the original Space Invaders
entirely black and white, says Realcuriousqe? I think it was. I think it– well, not black and
white as much as it was, I think, black, white, and green? Let’s see. Space Invaders– black,
white, and green. So yeah, essentially,
I guess, 2-bit color? We’re not going to go
quite that low, I think. We’re still going to add–
make it look visually cool and have different sprites. But yeah, I think if we were
going to adhere 100% strictly to the game and its limitations, we
would use just black and white sprites. These are looking OK. Some of them are a bit– there’s not a whole lot of
detail, is the only problem. They don’t look like aliens. We could make some of these work. Like this one, for example, right
here, this one could work, right? And this one, actually this one? This one looks almost exactly
like the Space Invaders alien. This one looks really good. No read, Colton, I have to leave. Will catch up on YouTube
[INAUDIBLE] the day [INAUDIBLE].. OK, Fatima. See you later, thanks for joining. The green was a filter on the
screen though, as far as I know. Oh yeah, that would make
sense actually, because it was within a limited portion
of the screen down here. That actually makes perfect sense. So yeah, in that case
then it was 1-bit color. Yeah, they don’t look like anything. Jacob saying, let’s do 16. Yeah, probably. I’m thinking that too, probably. There’s just not a whole
lot to work with here, so 16 probably makes sense, right? Sadly. I mean, we could make it work. There’s a few of them that do
look OK, like this one looks OK. This one looks like it
actually looks like a UFO. This one looks OK. Some of these look like ships. This one looks like a sideways UFO. But I think it would
get much better results. So, tell you what. Let’s generate another one. Let’s go back to the website. Let’s go over here. Let’s go and say size 16. Now, the only problem
with this is because we’re running at such a low
resolution, these 16 size sprites are going to bee pretty big. So what we could do is, we
could render the game at– could you take a screenshot of
the font and use that as a PNG? Oh, we definitely could. We definitely could. If we wanted to do that
way we absolutely could. I personally think it’ll look a lot
more fun if we have a different sprites, and we can do some cool stuff with
randomizing the aliens this way and it will look a
little bit less boring. But yeah, you could absolutely
do that if you wanted to. The only problem is, then you’re going
to– the screenshots are going to be, because I’m taking a screenshot on
my Mac, which is a retina display– well, right now it’s a 720. It’s going to be super, super big. It’s going to probably be
like 200 pixels per alien– 200? Well, maybe not 200. Depends on how small I create it. I can create it pretty small but
it’s not going to be an even size. So at the very least, I’ll have to
go into Asprite and then downsize it. And by downsizing it, I might
artifact it– not artifact it, but I might distort the sprite
in a way that it doesn’t retain its actual crisp original look. So typically that can be
kind of tricky to work with. But yeah, you could get it to work. And with a little bit of touching
up manually you could make it work. I think it’s a bit too
much work, to be honest. I think it’d be easier to find just the
actual original Space Invaders sprites, probably. Let’s try this. Let’s save image. This is a little bit
more interesting, too. We can actually create our own aliens
and figure out which ones we like. What I like to do is randomize it. So I get something like this and
then just make them all random. So that way we don’t
know what to expect. Aliens16.png. And so now if I open
this, and I zoom in– so, a million times better. All of these are pretty distinguishable. I mean, you do get a lot of
them that look kind of samey. Like, they all have sort
of this mothership look to them, this sort of weird hive look. But they all look pretty
unique and interesting now, compared to the eight pixel ones, right? 16 is too detailed. You could even make an image out of
the font by drawing it on the screen and then using love.image.newimage,
new image data. Yes. Yeah, yeah, yeah, you
could do that, absolutely– draw effectively a pixel or
texture data on the screen and then make an image out of it, yep. That’s actually a great way to
do your own custom randomized sprite generation, by
drawing to a bit of image data the extra individual
pixels and then creating a sprite from
it that you can then draw in otherwhere– in other places. Otherwhere being a new
word that I just made up. But do we think it’s too detailed? Jacobchaussen says it’s a
little bit too detailed. I hate to spend a little
bit too much time on this. But this is also kind of the
fun part of game development, is choosing the assets and laying the
artistic, the creative design out. So it’s not something that we should I
think definitely pass over altogether. Themetaleagle, hello. Hello, good to see you. Thanks for joining. But if we think that 16 is
too detailed, let me know. We can maybe try 12. We’ll try 12 pixels. We’ll see what the
in-between looks like, right? So 12 pixels, generate. I’m going to save this. And then we can vote one more
time on what everybody wants. So we have aliens12 now. So we have the aliens12,
12 pixels by 12 pixels. I’m going to give everybody a
chance to take a look at that. Some good ones in here, definitely. Oh, the sprite sheet
Brenda tossed in the chat. Oh, yeah. So, that could work, Brenda. It would be a little
bit tricky because we’d have to manually go into an image
editor, determine the exact pixel coordinates, and then–
we’ll cover this, but we’re going to have to
generate what are called quads. And if you’ve followed GD50 before you
might be familiar with this already. But basically, a quad
is a rectangular portion of an image that defines, when you draw
that image, the exact portion that gets drawn to the screen. But we would have to manually go
through this and figure out the quads. And if the image is larger than, say, 16
or whatever we’d have to scale it down to draw it to fit our screen well. JPguy, welcome! Good to see you. Borrow a phrase from Westworld, it
doesn’t look like anything to me, says Andre. It seems like a lot of work. It is a bit of work. But we talk about this in– I did a seminar on Mario. C4renny, eight for the minion aliens
and 16 for the top level boss. Is there an actual boss in
the original Space Invaders? I don’t remember offhand. I don’t know if we’d have
time to implement like a boss behavior versus the minions. That be cool feature. If we do it over
multiple streams we might be able to add something like that. It doesn’t look like there is a– oh, there is right here,
the mothership I guess? That’d be cool. That’s a cool idea. Let’s put that on the
potential to do list. These look like they’re– actually, the base sprites
look like they’re 12 by 12? I think they’re 12 by 12. So, the 12 by 12 might
be the most appropriate. But yeah, see eight for the minion
aliens, 16 for the top level boss. If we’re going to make a top level
boss I’d probably make it even larger than that, to be honest. Probably make it like, maybe 24 by 24? It’s a good suggestion. That’s pretty cool, actually. I personally think the
12 by 12 is pretty good. Can the chat tell me what
they think, what they like? And I actually haven’t watched
Westworld so I’m not familiar with it but I’ve heard great things about it. So, just to ABC, this is
the 12, this is the 16, so a bit larger and a bit more detailed. Give everybody a chance
to take a look at that. And then this is the eight pixel
one, which I just called aliens. So the eight is a bit small. It’d be great if you’re making
like a Gameboy game or something. I think that would look pretty good. Majordafat, no Westworld
spoilers, please. 12 by 12, yeah, Asley
says says 12 is good. Brenda says 12 by 12 looks good. Jacobchaussen says– I’m assuming that
he or she is referring to the 12 by 12. I don’t like colors. They seem so saturated. I think it’s because they’re
all so zoomed in, yeah. When we see it in the actual game I
think it’ll look a little bit better. Twohourstrike, I vote for 12. All right, it seems like
12– yeah, Andre says 12. Yeah, 12 is the way to go. OK, so we got that setup. We’re good. Let’s go ahead and let
me get rid of this. The– oops, sorry. So, we know we want our sprite
sheet then to be the sprite– whoops, my microphones
got caught on the table. We know that we want the sprite sheet
to be our 12 pixel by 12 pixel one. So we’re going to use that. We’re going to load
that as an image file. And that image file we are then going
to chop up into pieces so that we can render the individual aliens because
if we were to just draw the image file to the screen as it is, that is
going to result in just drawing this big collection of aliens
on the screen which isn’t going to be productive for anybody. So let’s go ahead and
do a couple of things. First thing I’m going to do is,
I’m going to create a new folder called Source, S-R-C.
This is going to be where I put all of the Lua files besides
main.lua, including constants.lua. So I click and drag
constants.lua into there, which means now I have to
require src/constants, not just constants because it’s not in the
same level as main.lua anymore. Within source I’m going
to create a new file. I’m going to call this dependencies.lua. And this file is going to
be the file where we keep all of the libraries and image data. Basically it’s going to
function as a require and assets file module that we can
then include in our main.lua and we don’t have to require constants
and all of the different classes that we might end up writing and all the
images and sounds and all that stuff. We’re going to put that all
into the dependencies file. So I can say push equals require push. I can say require src/constants. And then I can say, gtextures– and remember, that lowercase g means
it’s going to be global– gtextures equals, I’m going to make it a table. And now a table– so this
is where we get into where curly brackets are used in Lua. A table is a sort of data
structure that functions as a– you can make it use as an
array, you can use it as a dictionary, a Python
dictionary, or a hash table so you can associate keys with values. It’s a multi-purpose data
structure and it’s also the backbone for how you get
classes and objects to work. Un3okapi says, hey, sorry
to interject but I just wanted to say I really appreciate
and enjoy these Twitch sessions. Thank you for taking
your time to do these. Thank you for joining. I appreciate that you’re tuning
in and that you are enjoying them. But the tables are used for
basically putting data together in a data structure. Oh no, NASA just went live! Which stream should I watch? Put them both up. Why not? I mean, have a little
bit of outer space. It’s appropriate because Space
Invaders takes place in outer space. So I feel like the two
sort of go hand-in-hand. Un3okapi, cool hair, dude. Thank you. Appreciate it, thank you so much. OK, so gtextures equals– these empty curly brackets is
going to be our table definition. So what I’m going to do is, using
this symbol, or this– sorry, this square brackets syntax, I’m going
to say this is going to be my key. The key is going to be aliens equals. And then I’m going to say
love.graphics.newimage graphics/aliens.png. And what this has done is it’s
created a table where I can put data, and it said the aliens string is
going to be associated with this love.graphics.newimage object, this
image, located at graphics/aliens.png. So now if I do something
like gtextures aliens, that’s going to be a direct
reference to that image object. c4reni, thank you very
much for following. So that gtextures is now
a table we can index. Just like arrays, you can
just index them by their keys. So this is indexing that
table at the key aliens. If it were used as an array where the
data does not have a key to associate with every value but rather it’s
just storing data continuously, you can index it numerically
like you do with arrays in C– 1, 2, 3, 4, 5, et cetera. But we’re going to be using this
gtextures table as a reference to all of our texture data. And another thing that
we want to do is, I’m going to create a table called gframes. And this is going to have a reference
to gtextures aliens, 12 by 12. This is going to have a reference
to the result of a function called generate quads, which we
haven’t implemented yet. That’s our own function. And this function takes
as arguments a texture So in this case it’s an image data object. So in this case a reference
to what we just looked, the gtextures aliens image data,
and then the size of the sprites located in that texture, in
this case 12 by 12 pixels. And in order for this
to work I also need to require src/util, which
we have not implemented yet. But this is where we get into
talking about sprite sheets. And we haven’t actually talked about
sprite sheets yet in Lua and Love. But sprite sheets are
exactly what these are– essentially just image data put
together in one texture, one PNG file, as opposed to having individual
textures which we looked at, for example, in tic-tac-toe. And we didn’t even
use textures in Snake. And we used individual textures
also with memory cards. It’s easier to do it
this way because we don’t have to actually split up the textures. You programmatically, like
we’re going to do in a second. But it is a bit unwieldy. For example, if we wanted to
do it that way with this and we wanted to have the same
number of aliens available, this would be whatever this is– I think it’s 14 by whatever this
is, 1, 2, 3, 4, 5, 6, 7, 8– 16, 1, 2, 3, 4– yeah, it’s eight by eight– sorry, 16 by 16 sprites which is– I don’t even know that is offhand, I
don’t know my 16 multiplication tables. But it’s a lot. It’s like 200 something sprites. And that would mean,
200 and something png files in a directory somewhere in here. So rather than do that and have
to manually go into my source file and say, OK, that’s one
texture, OK, so alien2 is going to be love.graphics.image
graphics aliens2, it’s much easier to be able
to just have a single texture and then split that up programmatically
into what are called quads, or sprites in a lot of frameworks and environments,
and be able to draw those separately. Be able to draw this image data but
specify a quad, specify a sprite, and then only draw that
specific piece of the texture. And it will have the
effect of, as if we had 200 and some odd individual
textures that we’re using. But we’re only using one. We’re just making it look as if we
have multiple different sprites. Let me make sure that I’m
back in the stream chat here. OK. You know what? You’re totally right, says JP. Yeah, well, you know, you’ve got to
have a little bit of outer space. Never hurt anybody. OK, so I know that I want this
function to generate these quads. First, let’s do a sanity check. Let’s go into love.draw. Instead of drawing Space
Invaders, let’s go ahead and say love.grapics.draw
gtextures aliens, because we can make a
reference to that image data so I can just call it within there. Right, I haven’t called the– so, I put
all of this into my dependencies file. So I could say it require
dependencies, like that. And source dependencies, I
apologize– src/dependencies. Push is not found. Did I mess that up? Oh, I did– lib/push. Sorry, util not found because I
haven’t created the util file. Lots of little bugs here. But now this should work. So if I go into main.lua and run it– god, generate quads also doesn’t work. OK, function generate quads end. There we go. So that was somewhat painful. But you can see that we’re drawing
the texture to the screen as is. And that’s not the effect that we want. We want to draw just
individual sprites at a time. And I’m also making a reference
to the wrong sprite sheet. We agreed we were going
to use the 12 pixel one. So I’m going to say
that we’re going to load not the aliens.png which is the eight
pixels, but the 12 pixel version, so aliens12. And when we do that, we can see that
they do look much larger on the screen. And they look like a pretty good size. I can sort of visualize
how this is going to look once we’ve implemented the– once we’ve actually split the
texture into multiple sprites and made it so that the enemies move
around we have a ship and whatnot. It’s going to look decent. We should also figure
out which one of these we want to be our ship, because
we will need a ship sprite. Which one of these
would be good, actually? If anybody has any
preferences for which ship we want to vote to be the one
that becomes our actual ship. This one looks pretty
good, for example– third row, last one. Toss that in the chat,
because we got to decide that. Oh, 16 by 16, 256. Yep, I should know that. That’s kind of embarrassing, actually. How do you iterate through the image
if the only information you have is that the quads should
be of size 12 by 12? So we are going to figure
that out right now, actually. So going into util.lua I’m
going to say utility functions. And then remember we
declared that we were going to take in a texture
and a width and height, right? And I’m trying to remember
exactly how I did this because I implemented this for the game’s course. And we could figure it out on the fly. I’m just trying to figure out if there
was any particular specific special way I did it. There really wasn’t. So, we’ll just figure it out as we go. So what we need is,
essentially what we should expect to be returned from this function
is a table, so a list in this case, of quads. And quads are just rectangles. So if I go over to– this is actually a somewhat perfect
time to do a little bit of fancy– sorry, draw.cs50.io. . We’ll do a little bit of
fancy drawing onto the screen. And excuse me while I grab my tablet
so I can actually do this properly. So I try to look for any
excuse possible to do this. But I have a handy dandy
Wacom tablet right here. And we’re going to use CS50’s handy
dandy draw tool, draw.CS50.io. I’m going to plug this in. This should just work. Take the pen out and
let’s do a little test. Is this working? Yep, perfect. So I have a sprite– or not a sprite. In this case I have some textures. I have aliens, right? And these individual aliens
are going to be my sprites. Blah, blah, blah, blah, blah. They all look the same for this example. But our goal is to take this
sprite information, this texture, and split it up into multiple pieces. And I would put this publicly
but I feel like I might get a lot of drawing and stuff on there. But if you want to use this
yourself, feel free to do so. In fact, we can set up a
draw.cs50.io/spaceinvaders. If you go to draw.cs50.io/spaceinvaders,
you will actually be able to see this on your screen. So anybody that wants to go ahead
in there and draw and mess around, feel free to do that. I’ll tune in there in just a second. But if you just go to just
draw.cs50.io on your machine without– if you go onto it
without specifying a URL, you will actually just get
a local version of the app so that anything you draw
is just on your machine. It’s not being broadcast anywhere. And Nikolai, scared cold
enough about draw.cs50.io. Yeah, that might be– we might have
a couple of non kid friendly issues with that. Fifth one from the left, fourth
one up, but the one you suggested looks good to. Fifth from the left, fourth one up? Which one is that? Fifth from the left, fourth one up. Are you talking about from
the top or the bottom? So this one? Fifth from the left, fourth one
from the top, this green one? Or are you talking about this one
right here, this yellowish one? OK, so 1, 2, 3, 4, 5, 1, 2, 3, 4. So, this one right here then. Oh, six– oh, this one? Oh, I see. Oh yeah, that would be cool. Yeah. Yeah, that would be pretty cool. We can make that one the alien one. JPguy, I should choose
Belgian looking space– I keep getting out of the
chat on my side computer here. American looking spaceship
near the bottom as well. American looking one at the
bottom, which one is that? Near the bottom. Which one was the American
looking spaceship, JPguy? How do you erase lines? Oh, how do your erase lines! So, if we go back to the– I’ve got so many devices and stuff here. Let me go to this and let me
put this on a separate screen so I can flip between
them pretty easily. So erasing, if I’m not mistaken
you click and drag from the bottom. Can’t see super well. Whoops. How do you erase, actually? Is it shift? Oh, it’s shift. Sorry, so shift– it’s a
little large, so be careful. So shift click will
erase, so I can do that. But I don’t want to do that right now. Do I dare look into the tab and
see what people are drawing? Whoa! Got a lot of erasing going on. So people have stuff
they don’t want to see. OK, I apologize. We’re getting a little bit distracted. Da, da, da, da. Brenda has a sword now to moderate. Oh yeah, that’s true. She does have a sword. And Brenda will use
it fiercely, she will. I know Brenda. It had some colors but I
miss looked, apparently. 11th of the bottom, fourth or third. 11th from the bottom– 11th from the bottom, 1, 2,
3, 4, 5, 6, 7, 8, 9, 10, 11. Wait, what? I’m not sure which one
you’re referring to, JP. But anyways, back to the
discussion of splitting up sprites. So, we have image data here. And a quad is essentially just– and if I can change color,
actually, that would be super cool. For some reason I can’t
change color super easily. Yeah, I’m not sure why I
can’t change the color. But if I could change the color– if Dan were here he could assist me. But essentially, a quad is just me
saying I want to take this chunk. I want to define a rectangle
that means this chunk right here. Oh and by the way, Maketsuk666
and Qaerasu, thank you very much, both of you, for following. And so this quad, so this is a quad,
also known as a sprite in many circles. Whereas this is known as
a texture, or an image. The texture or the image is the data
that contains the sprites that you’re trying to display on the screen. And what we have done so far is, we have
had individual sprites like this where it’s equal to both a
sprite and a texture because we were just drawing the
data as it is onto the screen, right? But we don’t want to do that when
we want to have all of these sprites together. We want to say, I specify a quad here. And it’s going to have an x and a y. So it’s going to be x equals
0, y equals 0, width equals 12, and height equals 12, right? Because we want to specify
a coordinate for the quad. And remember, everything is
top left oriented by default. So this quad here is at x,y zero– very top left. The width is 12 and the height is 12. Because all of our sprites in this
texture data are 12 pixels by 12 pixels tall. This sprite right here is very similar
except its x is 12, or rather– is it 12? Yeah, it is 12. Its x is 12 and its y is 0. And then this one is 24, this
one is 36, and so on and so forth until you reach the end of your width. And then you iterate per row as well. Every y, you increase the y by 12. So it becomes not zero but 12. And then you rinse and repeat and do
the same thing over and over again, generating all these quads. Go down to the next line and
do it over and over again. Now y is 24, x is 0,
and so on and so forth. Asley says she drew a masterpiece. Let’s see it. Oh, that’s– what’s that supposed
to be, Asley, please tell me. Oh, there’s a– OK. Man, I forgot how you scroll. Ugh. Does anybody remember
the scroll shortcut, because I actually don’t
remember what it is? Is it alt? I don’t want to delete the whole thing. I’ll feel terrible if I
delete the whole thing. Shift alt? Yeah, I don’t remember. I don’t remember the shortcut for
how to actually pan the image. But this is a– first of all, I appreciate the
artwork, thank you very much. I do see that there’s an arrow that’s
pointing to COL, which probably implies that that’s a picture of me. So it’s a beautiful picture. But this is the gist behind
how we algorithmically take a piece of texture
data and split it up into multiple sub sprites,
these little individual sprites that we can then draw like
they’re their own separate images. And so I’m going to go
back to the code here. And we can essentially think
of it as a two dimensional loop that’s iterating y by x. In much the same way that we would draw,
for example, a row of tiles, or sorry, a map of tiles along the x,y. We can do the same kind of
thing by splitting up the quads. It’s sort of the inverse of
drawing everything to the screen. But that’s how we can think
about it, just iterating row by row, column by column, until
we’ve basically extracted each quad and then put it into
a table that we then return back to main which
we can then reference when we draw an individual sprite. So, I’m going to say local quads
is equal to an empty table. And I know that at the
end of this function I’m going to return that table of quads. Jacobchaussen says zoom out. Can we zoom out? Oh no, it went away. What happened? Chmod777, thank you
for the subscription. Appreciate the name as well. OK, so I want to iterate
for every y and x. We can think about it the way that we
thought about drawing grids of tiles. So for y is equal 1 until, let’s say
local texture width, texture height, is equal to texture get
width, texture get height. And these are functions that you
can call on any image object. So no, we’ve declared
two variables called texture width and texture height. And we have called the get width and
get height function on the texture that we’re passing in, which
is going to be our texture PNG file that we referenced earlier. And then I can say local sprites wide
sprites tall is going to be equal to– and then this is where we can use
our actual width and height that we passed into the function, right? I can say, texture width
divided by width and texture height divided by height. And what this will do
is, it will tell me by dividing the actual
width of the texture by the size of the sprite, how many
sprites tall and wide the image is. So we have algorithmically figured
that out by using a function that Love has given us, which is this
get width and get height function. And we do have to specify the width
and height of the sprite itself. There is no real way for Love to
know how big the actual sprites are because it can’t look at the image
and say, oh, these sprites are 12 pixels by 12 pixels, or they’re
32 by 32 pixels wide, right? That’s something that visually you as
a human have to tell this function. And then the function
can then say, OK, now that I know how big the sprites
are I can iterate over it, I can calculate it, and
then figure everything out. So for y is equal to 1
until the sprites tall, do. Then for x is equal to 1
until sprites wide, do, end. And so this is iterating over every
row, first, so going through the row, and then going down to the next
row, iterating over every column, going to the next row, iterating
over every column, sort of scan line format the way that like
CRTs typically operate, if familiar. And so this is where we’re
going to have to actually create the quad that represents
that rectangle of our image that we want to store in our table. So, we would say table.insert. And so this is how you add
anything to any table in Lua. Table.insert into quads– I’m going to insert
love.graphics.newquad. And a quad– and this is a nice
thing about the Pixelbite plugin as well, is it gives you all this
documentation that you can see. It tells me that it
expects an x and a y. So this is where the top left position
is of the individual quad, which is important. And then it tells me it needs the
reference height and reference width of the image. And this has to do with
Open GL underneath the hood. I’m not entirely sure 100% how
that maps to this function. But basically, it maintains a reference. I looked at the source code
at one point and understood, but it’s been almost a year. But I can say, love.graphics.newquad. And lets just say I’m
going to need an x and a y. It’s not going to be actual x,y,
because those are just going to be 1 to whatever– 1 to 16 and then 1 to 16. But as placeholders I’m
going to put x, y there. And then I’m going to say, texture get– what is it? Is it get size, get dimensions? Lua– or sorry, Love 2D
image get dimensions? I think it’s get dimensions– yeah, get dimensions. Whoa, and that’s way zoomed in. And so what this does is, as
its documentation says right here on the wiki page, it
returns two variables– so that’s why there’s a comma
there– width and height. You call image get dimensions. In this case image is
capitalized as the object class, but it can be on any image
object, get dimensions. So I can say texture get dimensions. And even though I called
this new quad function, which takes in four arguments– notice
that it took four arguments, the x, y, the reference width, and
the reference height– because this function, the
get dimensions function, returns two variables we’re
actually able to populate a function that expects four
arguments with three values– the x, y that we’re going to
put in and then this texture get dimensions function call. Let me get– whoops,
didn’t mean to do that. I’m going to command B so we can
see the whole thing on the screen. Now, this x and y are not
the variables that we want. We want to actually figure out– so, back to the amazing
draw.cs50.io page here– we want to figure out where our x
and y are for each individual quad a we’re iterating through our array. So remember, they were
doing for y is equal to 1 until the number of
tiles tall– so that’s 1, 2, 3, 4, in this example case. And then for each of those in
a nested loop we’re also doing, for x is equal to 1 until the number
of pixels wide– so 1, 2, 3, 4– and then y is equal to 2, 1, 2, 3, 4,
y is equal to 3, 1, 2, 3, 4 on the x. For each of those we want to
determine what the x and y should be at that particular part of the loop. And we can do that by essentially
just multiplying by 12, because that’s the size of the pixels. So for our example our loop
is set to one on the x and 1 on the y, that’ll be the first index
that we’re at here because remember typically loops in Lua are one indexed. You can index them at zero,
but the typical trends are two initialized by one. You started at one
and then you can say– we could probably initialize it
at zero actually, for that loop, just because it’ll make
it a little bit easier. That way we won’t have to minus by
one before we do the multiplication. Normally you have to minus by one
before you do the multiplication when you indexed by one, because
everything in graphics is zero indexed but Lua is one indexed. So what we can do is, we can
say when our x is equal to zero and our y is equal to zero–
and I’ll change it right now, actually, zero and zero. What we can do is basically say,
love.graphics.newquad x times 12, y times 12. And then that will
give us the position– wait, quad, love.graphic.newquad,
x, y, and then it thought it also needed a size
of the quad itself, right? Am I getting that mixed up? Oh, it is. I’m sorry, there’s
actually six arguments. I was wondering. The function signature did look small. We also have to specify
the size of the quad, because just the position
is not enough information. We do need the size of it as well. And remember, magic numbers
are not good generally. So I’m going to replace this with
alien size which is something that I haven’t declared yet. So I’m going to go into
constants and I’m going to say, alien size is equal to 12. Remember, that’s how
you avoid magic numbers. Magic numbers are bad. Try to avoid them. It’s not always 100% necessary
depending on the context, but it’s usually good
practice– almost always. So again, alien size, alien size. I’m going to just make it easier to
read by putting this on the next line. So an x and y, a width and a height,
and the image dimensions, which you can just call with texture get dimensions. And you can kind of just forget
about what this is used for. You can look at the C
code and it maintains a point a reference to
the image data and does some other stuff underneath the hood. And that’s why it’s there. But you don’t really need
to worry about this too much to understand what’s going on. The important thing is that
you understand the x, y, width, and height of your quads. That’s the important bit. So we’re going to go into– and by the way, let’s also get
the x and y to work correctly. So I’m going to say x times alien
size and then y times alien size. And because we’ve laid out
our double loop like this and we’re starting at zero, when
we multiply by the alien size we will get a quad
that is at the right x, y because we’re doing it
in 12 pixel increments and we are making the quad 12 by 12
pixels as by specifying alien size, alien size for the width and the height,
and then texture get dimensions here. And then we’re inserting this new
quad into this quads table here. This quads table gets returned
by the generate quads function. And if everything goes according
to plan, I can go into here and say gframes aliens. So remember, gframes
aliens in our dependencies is getting the result of
this generate quads function. And then remember we
pass in gtextures aliens. And let’s also for good measure say– oh, you know what I did? Sorry. Alien size– I made a mistake. This should be not alien
size, this should be height. And this should not be– sorry. This should not be alien
size, this should be width. This should not be alien
size, this should be width. And this should not be alien
size, this should be height. The reason that we’re doing that– and it was a bit of a
brain fart on my part. The reason that we’re doing this is
that this function is general purpose. So now we’ve taken this function
from being specifically intended for alien splicing, alien
cutting up the image, to being usable for any
image that we pass in. And we can specify any width
and height and it’ll split it up according to those parameters. So that is the right way to do it. Here is where you actually
pass in alien size, where you actually call the function. So now we’re actually using it
for that intended specific use case of the alien cutting up. And I apologize. There’s a bunch of comments in
the chat that I will respond to. What happened there? OK, do that again. I will get to all those comments. I apologize. Just trying to make a little
bit of room since we are– this has been an hour and 40 and
we’re still a little bit behind here. But, this is effectively how you cut
up images and do it algorithmically in a way that you have all your data
lined up in a way that makes sense. Now, with the image
that Brenda showed us earlier in the chat,
which was a bit more– I have it on another computer. But, let’s see, where’s
the [INAUDIBLE] picture at? Brenda, if you wouldn’t
mind posting that– was it Brenda that posted that? It was Brenda, right? Yeah, Brenda if you
wouldn’t mind reposting that just so it’s on my other machine. I can click the link
I think– actually no, it wouldn’t work on that
because it’s not on the stream. Sorry, scratch that. I’m just going to go into images and
just look up Space Invaders Deviant Art. That should pull it up, right? Maybe not. Not seeing it in here. But if I can find something
that looks similar– so I’ll tell you what. I can show you the idea. A sprite sheet, if we look
at a spreadsheet that’s kind of all over the place. So by the way, these are sprite sheets. What we’ve been using is called a sprite
sheet, where a bunch of your sprites are put together in
one sheet, one picture if I didn’t already specify that. Trying to look for one that’s
got a bunch of different data all over the place, that’s not
uniform to sort of showcase this idea. I guess for example something like this. So this is a bunch of sprites
that are different sizes. So notice that these ones are
wide, wider than they are tall. But these ones are all– well, these first four, first
eight rather, are pretty uniform. But then these two are kind
of wider than the other ones. For sprites like these, and for
the link, if you look at the link that Brenda just posted in the
chat, it’s that same kind of idea. For any sprite sheet that’s
not uniformly laid out, you can’t do what we just did. You can’t algorithmically
define the individual sprites, the individual quads, because
they just don’t chop up evenly. They’re not along some sort of grid,
which we’re doing in our examples. These are on a very tight 12 by 12 pixel
grid, and these are on a very tight 16 by 16 pixel grid, eight
by eight pixel grid. This grid is essential to be able to
chop your sprites up algorithmically. And so if you’re doing this and you
have a bunch of are in your game, try to find a way to
put everything on a grid so that you can write some piece of
code to chop up your sprites for you and not have to manually lay
out where all the sprites are. This isn’t always feasible because
not all sprites are the same size. For example, even some certain
Mario sprites are different sizes. NES Mario sprites have different
sizes, different width and heights, and they’re laid out in sort
of different weird ways. And that is a kind of
situation where you have to manually lay everything out and
figure out where the slicing occurs, if not chop up your
sprites manually in advance and then load them individually. But yeah, for doing most
2D games, most sprite work, you can figure things out in
a sort of grid like manner. Now, before I get into
the chat I’m just going to make sure we got this working
in drawing to the screen. I’m going to go into main. And now down here where
I have the draw function, remember in passing gtextures
aliens as the image data. So I still need to draw the image. I’m still drawing the
image no matter what. The second parameter is
this reference to gframes aliens, which is the
quad table, remember. This table full of these rectangles
that have an x, y, width, and a height. And I need to index into
it because I can’t just draw the quad table as it is. I need to draw a specific quad. I need to tell the
love.graphics.draw function, draw the sprite with this quad. So draw like this window
of the sprite, right? And just for kicks I’m going
to say one, so the very first sprite which should be
this one right here. It can actually be kind of hard
to see, this purplish looking one, so I’m going to do the second one, so
number two, this bluish looking one– so, two. And if I run this,
fingers crossed, it works. Wow, I actually wasn’t
expecting it to work. That’s actually pretty amazing. Just because live coding
is a little bit much. But, it’s simple and it works. And now I will read all
the messages in the chat. And now, by the way,
if that’s not clear, we have the capability
to actually draw rows of individual aliens and our
spaceship, move it around, while only using one texture for
everything– which is also more performant for your GPU, by the way. So, sorry, chat. Got a lot of chat to catch up on here. OK, shift works. I drew a masterpiece draw.io. I think I did see that. We did see the masterpiece. Zoomed out 25% or so,
I think it got erased. I did get erased. Asley says, they couldn’t
handle my talent. No, it was very impressive. Actually, let’s see what’s there now. Is there anything there now? It’s all gone. Everything’s erased. That’s so sad. We had such an amazing
masterpiece there. It’ll be in the video for all of
eternity that we can look at it and appreciate it. Emoji is Asley– Asley says she’s the kappa face,
and Bavich_knight’s got the meat boy in there. Isotv– oh, and by the way,
we had a couple subscribers. Bubullah and Xoxoff, thank
you very much for following. Isotv, just like printing
the pyramid in Mario, yes. It’s very similar to printing
the pyramid in Mario. The same idea of taking two
for loops, combining them, and being able to do some operation
iteratively, some two dimensional operation. It’s something that you’ll see time
and time again in computer science. It’s something that you’ll see time
and time again in game development, whether it’s drawing
maps, splicing tiles, doing whatever– laying out rows of
enemies which we’ll do in the future as well. Charles, is Lua like JavaScript? Yes, in a lot of ways it actually is. It uses very similar prototype
inheritance model as JavaScript. It uses anonymous functions in this
very similar way to JavaScript. So, a lot of code that you
see, very promise like syntax exists in Lua just like
it doesn’t JavaScript, which you might get to in the future. Probably not in this stream,
but certainly in future. Don’t worry about it too
much right now, says JP, but I think the mic is crackling
a bit or suffering from static. Uh-oh, that’s not good. Hopefully I’m not brushing
up against anything. And I hope it’s not suffering
from too much static. Oh, and let me– apologies. Tell me if this sounds any better. Does that sound any better? I think I might have forgotten
to bypass the EQ, which should make my mic sound a little nicer. Dev, let me know. I have a compressor on, just to
limit the dynamic range of the mic, and that might be
distorting it a little bit. So let me know about that as well. Can it run in the browser like
JavaScript, access the dom, says Charles. It cannot run in the browser and access
the dom in the same way that JavaScript can. You can compile Love games and use
those in the web browser using what’s called Mscript in, which basically
takes your game and the Love binary, compiles it into a form of
JavaScript, and then executes it. But you don’t have dom
control with that either. Nicktheway says uptime. What is uptime? I have to figure out
what that is– uptime. Oh, is that how long we’ve been up? So we’ve been up an hour 53, I think? Still somewhat new to Twitch, so a
lot of these things are fairly new. And Nicktheway aptly just followed. Thank you very much for following. What mic are we using? We’re using a Sennheiser– what’s this called– EW100 G3 lav? I am not a production expert so I
could not tell you too much about it, but it is a lav. One day my lav– will you been
making some sort of platformer or a dungeon crawl anytime soon? Good question! I would love to make one
of those, either of those. I made a platformer for the GD50 course,
which by the way if you’re unfamiliar go to CS50.edx.org/games. So that’s the game of
course that I taught. I taught how to make a
platformer, a Super Mario style platformer with randomized levels,
using a very cool sprite pack. We didn’t cover dungeon
crawling and I personally am a big fan of dungeon crawlers. So I tink that’d be a really
cool project to work on. That would be a definitely
multi stream project. And this project itself is also going
to probably be multi stream, multi-day, just because it takes a while to– we’re covering a lot
of somewhat new ground today, actually, with
quads and stuff like that, which we haven’t looked at before. And I want to make sure that everybody
understands where we’re going and can follow along. Thank you, Onedaymylove,
following as well. That was a very funny sentence to say. Are the sprites on a black square
uniform with the background or are they on their own? So I missed five minutes and
couldn’t understand, Asley says. The sprites are on a
black background that we are going to make the same color
as that background in our game. And we’re going to do that
for the purpose of avoiding making that background alpha,
just because that color I believe with the limited palette is also a
component color of many of the sprites. I’m not 100% sure if that’s the case. But I believe that black color is part
of many of the sprite’s actual artwork. So we don’t want to necessarily
convert the black color to transparent, or do a fill transparency, because
that will make some of the sprites look a little bit wacky. So what we’ll do is, we’ll just make the
background of the game the same color as the sprite. And I think it already is. It might be slightly off color. And that will make it look like
we’re playing on a– that we’re drawing the sprites transparently. There isn’t really ever
going to be a case where they overlap anything
else so we don’t really have to worry about transparency. So it should be fine. But thank you for the question. It’s a good question. I missed 10 minutes, says Bavich_knight. It just froze. Sorry about that. Hope you’re able to go
back and scroll through it, or catch what you missed on YouTube. But we haven’t gone into anything
too intense because all we’re doing is just catching up on
the chat at this point. I am back, but your
masterpiece is gone, Asley. But I’m back again, Xoxoff. But it’s back again– oh, is
the masterpiece back again? I do not see it on my screen. I checked my PC volume. It was much louder than
what it’s usually at, that’s why I also heard the crackle. But at normal volume it’s
actually not even audible. Oh, I wonder if your speakers are
just distorting, because that’s possible– hopefully not. What did I do again to the mic? I added a compressor–
not right now, but I just bypassed– we have an EQ and a mixer. So I have a lab going into a mixer. The mixer is applying
EQ settings to the sound that I’m outputting to the stream. So basically, the sound is made up
of different bands of frequencies and the EQ is an eight band– I think it’s an eight band. 1, 2, 3, 4, 5, 6– it’s a seven band. So there are seven discrete
sections of frequencies that you can lower or accentuate,
accentuate or attenuate. And so EQ just takes out some
of low frequencies like the HVAC and accentuates some of the higher
ones for a more crisp sound. But there’s also in the software a
compressor to lower the dynamic range and also make up some of the gain. And so potentially it could
distort at certain points, although it shouldn’t be per
what I did to test the volume. Maybe if– Asley says she hears it
now, so maybe there is a little bit. So hopefully it sounds
a little bit better now. Otherwise, you can have a chatbot that
keeps track of the uptime, says Isotv. I’ll look into that. I’ll look into that. Still fairly new to Twitch, so there’s
a lot of stuff I should look into. OK, if you can all
hear the crackling I’m going to go into the
settings for the audio. And I’m going to lower the output gain. Tell me if that fixes it. So does that sound any better? Let me know. I just lowered the makeup
gain on the compressor. Brenda says, no sound issues there. Is there any way to separate sprites
completely from the background, says Asley. You would use transparency. So we’re not doing it in this example. But you would make your sprites with a
transparent background in some editor. A lot of games back in the
day didn’t have image formats that had transparent backgrounds. So what they would do is, they would– hopefully it’s not the mic itself,
because I just lowered all the makeup gain on the compressor. So it should have fixed any
distortion that existed. I’m not sure. I can potentially lower
that EQ, the upper frequency bands on the EQ and that might work. But yes, you would draw your sprite
with transparency in advance. But games in the past
didn’t have transparency. So let’s see. Like, some of these for example– see this drawing here, this
sprite image here of this gorilla? It has a background that’s
very different than any color that you find in the gorilla
itself, and this is deliberately so that there would be no clashing of
the background color with the sprite. And so what the game
would do is, it would check for any pixels that
matched some sort of color key and it would just not draw them. It’s sort of similar to how a green
screen works, I guess, chroma keying. But it would just
basically do an, if color is equal to blah, blah,
blah, don’t draw that pixel, but much more efficiently
than that using hardware. But that’s essentially how games
used to work back in the day. Now, the image format itself
can store the transparency value with what’s called an alpha
channel, the A, the RGBA. And that basically tells the– when open GL is rendering,
whether to draw it with the opacity or not effectively. In the middle column from the fourth,
bottom row, looks like a spaceship. In the middle column– 1, 2, 3, 4, 5, 6, 7, 8,
so roughly around here. Oh, this one? This pink cyan looking one? Yeah, that looks pretty good. I like that one. And I think someone else
suggested– what was it? Which one was it? It was another one of these. Crap, I forget the exact
one that someone mentioned. But yeah, that’s a good one. Crackling sound is still there. OK, I’ll try to investigate
the crackling sound afterwards. I’m not sure what it is. I apologize. Hopefully it’s not too distracting. Oh, and shout outs to NASA
for landing the Mars Lander. People in the chat are– I’m not following it right now,
obviously, but people in the chat are saying that it’s landed. So that’s awesome. You heard it today on
CS50 on Twitch as well. I’m going take a drink and
then we’re going to dive into drawing a bunch of aliens, and our
spaceship, and moving the spaceship. See the Snapple there
in the screen as well? Yeah, stay hydrated, chat. OK, so we haven’t done a lot of coding. We have done a fair amount
of new conceptual work. So today, the leap from going from
individual textures to quad generation is kind of a hard step for some folks. And being able to go over it slowly and
make sure everybody’s on the same page and being able to draw
through the algorithm, even though this now
looks like kind of a mess, it’s kind of important that
we understand how that works. So that’s why we took our time. But now we’re going to go into some
stuff that’s fairly straightforward– not as groundbreaking, I guess, or
as revolutionary as generating quads. But that’s a big piece that you’ll use
in probably any game going forward. Markv101, thank you for joining. Hello, good to have you with us. Next idea for your game, says
Andre, should be a Mars Lander game. What is that game? There is a game like that. It was in– was it just called Lander? Lunar Lander? Oh, it’s a video game genre. It’s not even an individual game. Oh, OK, it is an individual
game but it’s also a genre. Something like this. This is like vectorized landing
of the Lander onto the moon. Yeah, it’d be very appropriate for today
if we were doing something like that. I’d have to research how– because this looks
like it would probably use a different collision formula. It would have to actually calculate
the vector angle, the– no, actually rather the surface
normal of a vector of– sorry, the normal of a– the individual normals of
the terrain, the terrain vectors, and the surface normal. Basically if you have a surface,
imagine my hand is a plane, the surface normal would be
whatever arrow is coming out of it towards the basically exterior. And the surfaces tend to only have
one normal for lighting calculations in 3D engines typically, but you can
also use it for various other things. For example in Super Mario Galaxy– let’s load that real quick. And I don’t know if this has been
officially confirmed by Nintendo, but the world was made up by circular,
or spherical, oblate spheroidal, masses to simulate planetary
interactions and just to make it feel more like
you’re in outer space. And so Mario could actually
walk around 3D spherical objects as if they were flat, right? And the way that it’s
thought that that worked was that you would just
calculate the surface normal off of any given part of the mesh and
orient Mario that way on the terrain so that his body was always kind of– basically he was the surface normal. His body was parallel with it. And that gave it the appearance
of him walking on the planet. And so you would do kind of
the same thing with this. You would figure out, what’s the surface
normal of the individual vectors making up the– or I guess they’d be rays. Would they be rays? No, I guess they would be– they’d be line segments but you
could think of them as vectors. You’d figure out the surface
normal of all of these and then you would just orient the
lander kind of in the same way, is my intuition. I’m sure there are many
different ways you could do it. Kavabongo and Ki11ercrow, thank
you very much for following. So anyway, back to what
we were about to do. Let’s take this new quad idea that we
have implemented and draw some aliens. Well, let’s actually,
let’s draw a ship first. We were going to decide what
the ship was going to be. So I’m going to, in my source folder– do I want to make subfolders, or do
I want to just make it all into one? We can probably just do
it all in one for today. We don’t have to go into
separate subfolders. I’m going to create a ship.lua class. And what this is going to do– Bavich_knight, normal is you could
draw a perpendicular line coming out of a plane surface, correct. [INAUDIBLE] said I’m
too lazy to go to bed. Can’t wait to start the
CS50 games course after I finish the web programming course. This is so fun, says Isotv. Awesome, thank you so much. I’m glad you’re enjoying it. Quickly, make a robot
that brings you water. Oh, wait. Hey, am I very late, says Oshkosh32. Relatively– we’ve been
up for about two hours. We haven’t done a ton of coding because
I’ve been taking it a little bit slow. I’ve been looking at
some conceptual stuff. Scrin26, thank you for following. We’re looking at some conceptual stuff. And I just realized the chat– I don’t think the chat’s been
up this whole time, which is horrible by the way. I apologize for that. That should now be–
it should now be up. Let me make sure. Yeah, the chat hasn’t
been up this whole time. That’s terrible. I apologize. I think I must have hit something in
the CS50, in the chat here or something, and then it got rid of it. But no, we haven’t been– you’re not terribly late. We basically just talked about how
to splice a texture into subsprites. And we set up our window. We looked at a sprite generator, got
a texture, decided on our resolution, did a whole bunch of stuff
like that, set up our window, used push, went through the process
of splitting up a texture into quads, which are sprites– essentially what are sprites,
effectively– drew it to the screen. And now we’re about to get into moving– well, getting one of those sprites
to be our player, moving that player, and then doing the
same thing with aliens. Jobcoachin says, I’m still
learning C. So wait, really? We are doing Space Invaders–
kind of appropriate, says Asley. Space for the lunar Lander game? Is that what you mean? There’s the chat again. Man, I hate the fact that
I didn’t have the chat up. Ugh, man, because I love
seeing it in the video. And now it’s not going to be in
the video for like two hours. Oh, well, you learn from your mistakes. What are those on your
fingers says, Callmegm? Just rings I got on Amazon– just a red, and a green, and a blue. Fun story, I had a finger on my other– sorry, my index finger ring,
I had it on this index finger. I took it off and I put
it on my other finger, on my left hand which you see
as my right hand in the stream. And my finger got– well, it was too small
for my other finger. So this finger got swollen. And because it got swollen I
was unable to take the ring off. I tried using soap and
Windex and the string technique or the floss technique. It wasn’t working. My finger got too swollen. My finger was about twice as
big as my finger normally is. So I had to go to the
emergency room and get the ring sawed off of my
finger, which I had never known was a thing that people do. So now I have two rings that
match, because I originally got three rings in a set, and then one
ring that’s sort of a UV light sensor ring that my best friend got
me as a replacement for that. And that was actually
last Thanksgiving, because very appropriate that we mention that. It’s a one year anniversary
of going to the emergency room to get a ring sawed off of my finger. So that’s a story. OK, what happened to the chat? Should have mentioned it earlier. Yeah. I have a keyboard shortcut on the
keyboard here and it’s C. If I hit C, the chat disappears from the video. And I must have hit it at
some point and it disappeared and I didn’t notice it because I
was so focused on what we’re doing. But yeah. Better the ring than
the finger, says Brenda. I agree. And yes, it was terrible. But it was a fun, humorous experience. I’m just glad that my
finger didn’t get amputated. I’m glad that it didn’t get so swollen
and so blood starved for so long that it had to get amputated. That would’ve been
like, the worst thing. At least it would’ve been
on my left hand, though. So hey, I still have my
fingers on my right hand. Anyways, we want a class for the player. So we want to have a ship that we
can move left to right, just to get started, demonstrating this
quad technique that we’ve looked at in comparison with
moving something around, moving an image around like
we’ve looked at before. Actually, have we moved
images around before? This would be the first time
we’ve actually moved something freely around because with tic-tac-toe
we moved a cursor, a virtual cursor, around. With Snake, our Snake was
constantly moving on its own and we just manipulated its movement. And with the memory card game, we just– was that mouse driven? Did we just clicked on the cards? Yes, I believe it was just mouse driven. So, this will be the
first time we actually move a sprite around with the keyboard. So I’m going to say, player– sorry, ship, this will be the player,
is equal to class with brackets. And what that’s going to do– and first of all, if you
don’t have the class library they’re unfortunately named. But if you go to the
H-U-M-P library, Love 2D, and it’s unfortunate
that they named it that. But it’s one of the
biggest libraries for Love. Help Utilities for Massive Productivity,
they have a class .lua within that library. Download that. That class library will allow us
to use object oriented programming in our game. And I already should have a copy
of it already on my hard drive. Actually it’s in the folder here. I’ll just copy it from there. I’m going to go into
Space Invaders, into lib. I’m going to copy it into my lib folder. And then I’m going to
go into dependencies. And then above push, I’m going to say
class is equal to require lib/class. And now what this has
allowed me to do is almost like using a new syntax in Lua. Class is an object that basically does
a lot of the object oriented stuff for you that you would
normally have to do with meta tables and other weird stuff in Lua. It’s a bit ugly. But thanks to the class libraries,
part of the H-U-M-P library, you can just use this. You can basically say, ship is going
to be an object of type class, which just means it’s going to be an object. And any ship object that we
instantiate from this definition will have the properties of a ship. Asley said, do not read that as H-U-M-P.
I know most people probably don’t. [INAUDIBLE],, are you
using the 12 inch MacBook? Is this a 12 inch MacBook? Good question. It is a 13 inch, from 2013. It’s a bit old school, relatively. So now I’ve included this class– class? This class library. I can say ship is equal to class. I’m going to create a new class. Jacobchaussen says, I’m
missing too much code. So I’m going to pass this time. Sorry, I’ll be faster next time. No, definitely check it out on YouTube. I’m trying to go kind of slow but
also kind of relatively quickly and not cover too much of
the syntax just because we’ve covered it in prior streams. And this stream will
be very long as it is. We’re already at two hours and we
barely have much going in the stream. But yeah, definitely tune in next time,
tune in when you can, Jacobchaussen. Good to have you with us. Apologies if I am going a little
bit too fast for some folks. If you have any questions, specific
questions about what we’re doing, as always toss them in the chat and
I’ll be happy to try and answer them as we go. And I apologize if I missed it, but
scrin26, thank you for following. Sorry, apologize if I already
said that thank you for that. But if not, thank you
very much for following. So ship is equal to class. Now what we can do is, I can
say a function ship init. This is what’s called a constructor. I think we’ve talked about
the basics of objects before, but a constructor basically let’s us say
something is a ship with parentheses. That’ll make a new ship in our code. Every ship that we want– and
there’s only going to be one– is going to update over time and
it’s going to draw over time. And typically the naming convention
is render even though Love uses draw. Most engines will have render as their– that I’ve seen, I’m sure it varies– but they’ll have render as the word. And the init function,
this is the constructor. This is where we’re
going to set up the ship to have the information it
needs to perform its work. And what the ship is going to want to do
is basically just exist at the bottom. And I can’t draw too much at the bottom. I’m going to reload actually, and
bye bye to that because I don’t know how to scroll the screen right now. But our ship is going to
be here at the bottom. It’s going to have a sprite. So I know that I’m going to
want to draw this sprite. So it’s going to at least need
to have a reference to what sprite we want to use. And I think Babic and Asley
suggested specific sprites that we can use for the ship in the chat. But it’s also going to, because
it’s going to move left to right it’s going to need to
have an x and it’s going to have a y, and obviously
of course a sprite. In this case, that’s
going to be a quad, right? And because our table that we created
earlier is numerically indexed, this sprite or quad can
really just be a number– one to however large the table
is, the table of sprites. And this information is what all of
the aliens as well are going to have, but they’re going to have
slightly different behavior. And if we wanted to be really super
good at engineering our application and proper, we would make a base
class probably called entity. And that entity class would
have an x and y and a sprite and maybe some other information. And we would then create a subclass. We would have something like
entity as the parent class, where every entity is
anything that we can see. Or rather, it’s a little
bit hard– you can’t see it super well because of the chat. But this entity class can
then split off and have children classes, child classes. In this case we would
have a ship and an alien. So notice that the ship comes
down from the entity and the alien comes down from the entity. These are children and
this is the parent. Now, I’m just saying well we could do. We could do this. It would be a bit too
much work, I think. But this is something
that we should think about going forward
because we will probably implement more complicated games. And for a lot of games this kind of
hierarchy, this object hierarchy, makes sense. And ship, you could then have multiple
ship types and multiple alien types and they would share the information
that their parents all have. Scroll is shift and three
fingers or five fingers. Let’s do it that way, entity as
base class and then subclasses. We’re going to avoid that just
because it’s a little bit too much, and we’re not getting a
whole lot from the entity. We will potentially tackle that
when it actually makes sense, I think, for a later– no, we will deal with entity, actually. We’ll deal with entity. That makes sense. So entity.lua, this will
allow us to demonstrate how to use inheritance with
this library which kind of makes sense to demonstrate. Entity based class, anything
that moves and has a sprite. So entity is equal to class. And then in the init function we’re
going to say, self.x is equal to x, and self.y is equal to y, and
self.sprite is equal to sprite. Where sprite is a number,
so one to whatever the– 256, because that’s how
many sprites are in the– is that the 12 by 12? Yeah, that’s how many are
in the 12 by 12 table. And an x and y to be its position. And that’s all we need for
the entity class for now. The ship is going to inherit from
entity by using this underscore underscore includes equals entity. And this is specific to the
class library that we’re using. And this is all you really have
to remember in order to make a class a subclass of something else. So in this case, this ship
class is saying that it is a child class of the entity class. It’s going to inherit
everything that entity has, all of its functions and all of
its data, while adding some of its own. And I have to remember
if we have to actually– do we actually have to call init? I think maybe we might have to. I’m not 100% sure. We’ll figure that out in just a second. Oh, actually no because what
we do is, we could just– now what we can do is, we can
just call init off of ship. And because entity, the entity class,
already specified an init function it will allow us to get
this behavior for free. We don’t have to actually
implement it in the ship class. Same thing for the
alien class, actually. So I’m going to create a
new file called alien.lua. And alien class inherits from entity,
moves toward ship, and can shoot. So, alien is equal to class. And just like we did
before with the ship, I’m going to say underscore underscore
includes equals entity function alien update function alien render. And now we have two classes,
two separate classes, that their behavior is going to branch. The ship is going to be
controlled by the player. And we’ll be able to check for
keyboard input and move it around. The alien is going to be autonomous
and it’s going to be AI controlled. But it’s going to be very simple. It’s going to move left to right and
then when it gets to a certain point it’s going to move down. Then when it gets to
a certain point it’s going to move left, and then down, and
then right, and then down, and then left, and then down, and then
right, in this sort of infinite loop until it gets to the
bottom of the screen. And then when it
collides with the player, we’re going to get a
game over function– we’re going to get a game over result,
the game over state in our game. And so that’s what we’re doing here. I’m going to get another sip. My mouth is a little dry. Asley says, is self similar
to this in JavaScript? Yes, it is. And self as well in Python. Truesound, hey from Australia! Thank you for joining us. Thanks for the awesome stream. Out of interest, where
in the series would you recommend someone new should begin? Thank you very much
for joining, Truesound. I would recommend looking
at the Snake and– actually, probably the
memory card and tic-tac-toe are a little bit easier than Snake. Check out Snake as well. Snake is a two part stream. But the tic-tac-toe and the memory
card game are very easy to get into. A lot of the other videos that
we do are not game related and are not as from
scratch implementational. So like, the stream that
David and I did on Python and then regular expressions
are a little bit more conceptual and do dive into
some programming stuff. But they are separate. So the dependencies between
those are not really there. So wherever you want, but game
specific stuff I would probably do tic-tac-toe or memory card. And Asley herself actually suggested
memory card, so that was awesome. And I’ll say it again. If you have any ideas
for games in the future, definitely toss them in the chat. All right, cool. So we have the alien class,
we have the ship class, and we have the entity base class. So the base class means
a class that other stuff can take the attributes of and then
become a more specialized version. So a Honda Accord is a
special version of a car. A car would be the base
class, it’s an abstract idea. An entity is an abstract idea. Automobile is an abstract idea
of which a car is a subclass and a Honda Accord is
a subclass of a car. And then a Honda Accord EX would
be a subclass of the Honda Accord. But the EX might be a property of that
Honda Accord rather than a subclass. But that’s kind of the idea. Asley said, I’m not the first
one to suggest it but I’d really love to see the typing test game. I’ll think about that one. That would be fun. I would actually like to do that. And that one wouldn’t
be too hard, either. But yeah, so we’ve looked at the idea
of object oriented hierarchy now. So again, just to recap and
make it a little bit more clear what we’re talking about,
we have the entity based class. And so this would be
base class, or parent. And then these would be
subclasses, or children. And I can’t write super well
on the edge here looks like– children. And this is like day one object
oriented programming stuff. But that’s essentially what we’re doing. And object oriented programming
is very prevalent in games so I would encourage you to try to
understand what this means and think about ways that you could create
your own object hierarchies, think about the real
world as object oriented to get your mind used to the idea. And then think about how you
can structure your own code to be object oriented because this way
you can save yourself a lot of work. We talked about it earlier,
how now the ship doesn’t need to have its own x, y
definition, the alien doesn’t need to have its own x, y definition. They both don’t need to have
their own sprite definition. It’s a simple example. I was kind of hesitant to use it just
because there’s not a lot of data that we’re trying to save here. But the idea is simple enough
to illustrate the concept. And the concept is
very handy, especially as you work on large code bases. So that is object oriented
programming, day one. And we might do a stream
on more complicated uses of object oriented programming. This concept of the child class
adopting what the parent class has is called inheritance. So, I’ll write it here. This is inheritance because these
are inheriting from the entity. They’re inheriting the attributes and
the functions of the entity class. And there’s other ideas, like
polymorphism and composition that we can take a look at in another
stream where they become pertinent. But that is the idea. I’m interested in more than
games but I do love games. Really appreciate the advice. Yeah, absolutely. Thank you, Truesound, for joining. Glad you’re enjoying it. If you’re starting from
the beginning of CS, CS50.edx.org if you aren’t
already taking that, says Brenda. Yes, shout outs to CS50. Can you come to the same game without
using object oriented programming, like only using functional
programming, says Un3okapi? Yes, you can. And if you mean functional programming
in the sense of like Haskell or F sharp or functional
JavaScript for example, yeah, absolutely you could do it with that. Or you could do it with
procedural programming, if you’re referring to procedural
programming or imperative programming, being like your data is encapsulated
in functions that you call and your logic goes top
down, which is what C is. And you can actually do it in that as
well, because most games actually were all implemented in C back in the day. It was C– assembly, and then C. There
were really no ubiquitous OOP languages in game development
prior to the late ’90s– I mean the mid ’90s, just because
C++ was relatively expensive for the console hardware at the
time, although it was used in the mid ’90s to late ’90s for DOS
programming and stuff like that. But if you mean– either way, functional
or imperative slash procedural, which the two names
kind of get mixed up with each other but they’re very different. You can make games in both of them. You can make games however you want. All programming kind of,
at the end of the day, is just a different way of thinking
about solving the same problem. So if you can get comfortable
in a particular environment you can do pretty much
anything in that environment. Studying a bachelor of computer science
at Deakin University in Australia, but I figured CS50 would be good
supplement material to that. Well, thank you for tuning in. I’m glad that you are
finding it to be so. Polymorphism is where
I am stuck in Java. Well, take some time to
get it, says Bavich_knight. Polymorphism is an interesting idea. It is essentially just being
able to use an interface to talk to objects as if they are
all sort of the same kind of object. This applies really
well in the context of– like, generic programming
is kind of using that idea where you can have
lists that use the different data types, that contain different data
types but they work the same way. You can have, for example,
a monster base class that your function does
things to, regardless of whether it’s a goblin monster or
a elf monster or a demon monster. Like, no matter what it is,
because it inherits from Monster, any function that
operates on monsters also operates on goblins, elves,
demons, et cetera, as long as it implements that parent class. Anything that operates
specifically on goblins won’t affect elves, demons, et
cetera, because polymorphism doesn’t apply to sibling classes. It only applies to the
classes that implement from a particular common parent. And that’s what polymorphism is, just
basically allowing different classes to sort of function, behave, differently
according to the same interface, or behave similarly but differently
using the same interface. It’s a bit of a weird thing. You kind of have to actually use
it to understand it completely. But it’s pretty simple once
you get the hang of it. And you’ll see it quite a lot. Staypeaceful, thank you
very much for joining. Started creating a Pong game in Python. Ooh, Pygame, yeah, that’s– well, Pygame might be what you’re using. You might be using something else. You might be using PyGL
or something like that. So, yeah Python would be great to
make some games in sometime as well. Un3okapi, got it mixed up, yeah. Functional programming
is very fun as well. So check that out. Functional programming is super cool. I want to get better at that. Functional programming is definitely
a different way of thinking. Hi, Colton, thank you very much for
the work you are doing, Unsigned. I started in Edx but I got
stuck in Pong because I couldn’t find the file font.ttf. So If you could please
guide me would be great. A big merci from Paris, says Unsigned. Font.ttf just means, I think you
just need to have any font.ttf file in your project, so font/font.ttf. Go to dafont.com if you don’t have
the specific font that we downloaded. So dafont.com, go to pixel
bitmap fonts, go to any font. I think we use Press Start to Play in
the course, which is on the first page actually if I can find it. Right– not this one, sorry. Which one did we use? We used– I forget offhand
which one exactly we used. But just name it font.ttf. Put it in a font/font.ttf folder or in
the base directory where your main .lua is if the string is just
font.ttf, and that will load it. OK, cool. So, let’s go ahead and do
some actual drawing of stuff. So, ship.lua, we’re going to– also, another cool thing. Because all of the ship and the player– sorry, the ship in the
alien class don’t really have different logic in terms of how
they render stuff we can just say, entity render, define an
entity render function, and just say love.graphics.draw
gtextures aliens and gframes aliens. And then remember, this
is where we can actually make it different for each individual
alien or each individual ship. We can just say, self.sprite. And then we want to
say self.x and self.y. So this function here will take whatever
this current entity that’s calling it and use its self.x, its self.y, and its
self.sprite, and draw it on the screen. So now what we can do is, first
we have to go into dependencies and we have to actually
include all these files. So in dependencies.lua
require a src/alien, require src/entity, and src/ship. And what I like to do is
alphabetize everything. So notice that we’re requiring
the library stuff first. So this is actually something– this
is not an alphabetical thing, but more of a semantic detail where I have
the libraries being loaded first so that they’re at the very top. And then all of my own
code is loaded after that. And everything here is
in the same directory, which is the source directory. But every module that
we’re importing follows– it’s in alphabetical order, so alien,
constants, entity, ship, util– just easier to scan through the list
and see whether we’re missing a module or not. Because if you have
things out of order it’s very hard to mentally sift
through all of your requires, especially if this were like
10 times longer than this. It can be a bit overwhelming. So I’m going to go into my main.lua
and I am going to create a ship. So, I’m just going to say
ship is equal to ship. And we’re going to put its x, y– we want to be at the bottom
of the screen approximately. So we can say virtual width
divided by two minus alien– do we have, is it alien size? What is the– alien size. Minus alien size divided by two. And then that’s going be
at virtual height minus 32. It’s an arbitrary amount. Could make it 24 as well. Let’s do 24. And then it also takes in a– because remember, we
inherited from entity. So notice that alien doesn’t
have an init function. Ship doesn’t have an init function. But entity has in an init function. And because any alien and
ship is also an entity, because we did that
includes equals entity, it’ll have access to the init function. The init function being
this ship constructor here. This ship with parentheses, this is
the same thing as the init function. This is just the way that
the class library works. So I can specify, then, as my third
parameter, if I’m not mistaken, the sprite. And we didn’t actually decide yet
what we wanted our sprite to be. So let’s go back into the sprite image. We had some suggestions in the chat. I think the last one I saw was
Bavich_knight say this one right here, the cyan one. I think Asley also
recommended another sprite. I’m not sure– I thought it was sort
of like a small yellow– oh this one, right here. So between the two. So let’s vote in the chat, between
the two, the contenders are this one, so we’ll call them red, so red
ship, this is Asley’s ship. And then we’ll get a little
bit of a competition here. And the blue slash teal pale ship,
the cyan one, between those two. That’ll be our player ship. Cast your votes. So JPguy saying red ship. Jacobsen, red ship. Oh, we got a blue. Unsigned saying blue. It’s two to one. Blue– oh, it’s even, 2-2! Uh-oh, blue came in the lead. Blue came in the lead! Oh, it’s 4-2. All the people who say
red, pizza’s on me. Oh, that’s compelling isn’t it? Red, so 3-4 it looks like. Sorry 3-5, 3-5. 3-6, 4-6. Tell you what. We’ll do it fun. First of all, let’s figure out what
index these sprites are located at. So, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16– because we iterated through our
entire sprite sheet, row by row, and we just table dot inserted and we
just went to the next line, da da da, went to the next line, da da da,
they’re ordered 1, 2, 3, 4, 5, 6, 7, 8, da da da up until 16. And then it goes to the next line
17, 18, 19, 20, 21, 22, 23, 24. So what we can do is, we can basically
figure out which row it’s on. So in this case, Asley’s is
on the fourth row, right? So, let’s say we wanted to use
Asley’s which I don’t think won. I think Asley’s was– it was 4-6, or 4-7. Unfair. Jacobchaussen says. People are now asking, what pizza? What pizza? What pizza is Asley going to get? We’re going to say, if we
want Asley’s ship index, ship index is going to be equal to. So hers is on the fourth row. So basically what we need to do
is, we need to multiply 16 by 1 and then add the x offset, right? So multiply 16 by the number of rows. I guess before the actual– before this one, the number of rows,
so in this case it would be three. So three rows plus 1,
2, 3, 4, 5, 6, right? So, 16 times 3 plus 6. Right? So, 16 times 3 plus 6– so 16 being the number of aliens per
row and three being the number of rows before our alien and six
being the x index of that row. And then I’m going to say,
this is ship index right here. So if I load this and I run this,
is it not visible at the bottom? It might not be. Oh, you know why? Because we’re not rendering the ship. So we actually have to call ship render. So is it up here, right? Yep, ship render. So now it’s still not rendering. So, let’s make sure that it is– let’s try and render it. Let’s set it up. The screen might be too
small to see it, actually. So let’s say 64. Let’s make sure that I am
seeing it appropriately. Oh, wait. No, I did that right. Yeah, I did that right. Right? No? Uh-oh, live coding time! What did we get wrong? So virtual width divided by 2
minus the alien size divided by 2. This is correct. So that’s the x position that
we’re going to draw the ship at. Entity draw self.x, self.y. Yep, that’s correct. Lua knows I didn’t win
and refuses to render. But we’re drawing your ship. This is your ship. OK, so let’s figure this out. So 16 times 3 plus 6,
that’s the ship index. Virtual height minus 64. So that should be in the
middle of the screen. Love.graphics.draw aliens. Ship– oh, this is why. So, if you define an empty
render function in the subclass it will overwrite the
entity render function. And that will make it draw
nothing, which is not productive. So now we have the ship. Now it’s there on the bottom except
it’s the wrong ship, unfortunately. So where did we go wrong? It looks like it’s– wait, is it this one? 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16. 1, 2, 3, 4 5, 6. Did I do the math on that wrong? I don’t think so. Let’s see, 1, 2, 1, 2, 3, 4, 5, 6,
1, 2, 3, 4, 5, 6, 7, 8 [INAUDIBLE].. So why is that not drawing the ship
index, the ship, the correct ship? So if I add– OK, so let’s add nine to that. See if it changes. Why is it– is my math wrong? That’s the right ship. Are there 17? Are there? 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16– no there are 16. I count 16. 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16. I count 16. No, the sprites are not padded. The sprites are not padded at all. Huh. What in the world? 16 times 3 plus 9. What? We didn’t screw that up, did we? Oh. So this is why I like to
start for loops in Lua by one, because the loops are inclusive. So we actually created quads that are
one tile past the edge for each row. It’s not that it was zero. It’s not that the
table was zero indexed. It’s that the quad
generation was zero indexed. So what we needed to do was,
we actually needed to say, until sprites told minus one,
because the loops are inclusive, for one until some range. And it includes that range. It’s not a less than or equal to– or, not a less than, it’s a
less than or equal to for loop. So that was the bug. So modify, if you’re following along,
your loop to be minus one there. And now if we go back to
main.lua and make that six, boom. It works. So that was fun. You’ll also notice that the
background color is black and the sprite background color
is a slight purplish look. The reason, Andre, is because
they one index everything so it has the same effect for
a lot of algorithms. The reason that it’s less than for most
algorithms in C and other languages is because it’s zero indexed. The bug, Asley, was the ba ba
ba ba ba– in our util.lua. Because we decided to zero index this
loop and I one index in the course. But we zero indexed it just to make
the math here for the calculating the quad a little bit easier. You don’t have to minus
one on the x and y anymore. But we do have to minus one from
the sprite’s tall and sprites wide to the end of the loop
because it’s inclusive. It’s not exclusive like it is in for
loops and like a less than loop in C. It’s like a less than or equal to loop. So you want to make it
minus one because we were going past the edge of the
texture and basically creating an invisible sprite every 16 sprites. So we were essentially
filling our sprite table with empty image data– not useful. But now we have a sprite. So let’s move it. Let’s move the– oh,
sorry, sorry, sorry. I wanted to humor both
both people that decided to contribute an idea for their– so, shout outs to Alsey and Babic. Their names are now in the source code. Ship index Babic will be– and am I spelling that right? I apologize, Babic, if I’m
spelling your name wrong. Nope, I’m spelling it right. Babic decided we wanted to use the
sprite down here, way at the bottom. Where is it though? Right here, this one. So it’s actually kind
of like the opposite. It’s the very bottom here. So, which row is that? That’s 1, 2, 3, 4, 5,
6, 7, 8, 9, 10, 11, 12. So it’s 12 and then 1,
2, 3, 4, 5, 6, 7, 8, 9– 12 and nine. So now if I wanted to use Babic’s
I would say, ship index Babic. And there’s Babic’s ship. So shout out to Babic. But we can do it even better. We can say, ship index equals
math.random 2 is equal to 1 and ship index Asley
or ship index Babic. This is a pattern for
the ternary operation that you would see in C or Java,
which is the question mark colon. So now we have a random chance
of getting either of these two. So math.random 2 will
give us either one or two. And if it’s one, then ship index
Asley, or ship index Babic. Easy. So, 50/50 chance, one or the other. And what we’re going to do is make
sure that we seed our random number generator. So math.randomseed os.time. And then if I run this,
this time is Babic. This time it was Babic. This time it Babic. This time it was Babic. Hopefully I didn’t get this wrong. Did I get this wrong? Maybe I did. No, the random is equal to in
ship index Asley or ship index– oh, sorry, because I didn’t
actually write ship index in here. That’d be my bad. There’s Asley’s, there’s Babic’s. So now we get both. Both of the ship
contenders are in the game. Yes, I apologize. I’m a little– the chat is now catching
up to let me know that I was wrong. I caught the bug quickly enough. But thank all of you
for letting me know. JPguy with the– what’s
the name of that emoji? Crap, I forgot. Pog Champ. Game knew which ship
was better, since Isotv. Ooh, burn on Asley. But yeah, so now we can humor both sides
using awesome random number generation and say a 1 in 2 chance
that it’s either or, right? So now we have Babic or Asley. We don’t have to hard
code one or the other. Now what I want to do is, I want
to test to see whether the user has pressed left or right on the keyboard
so we can move the ship left or right. And thank you Rangero
T-W-T, Range-o-tweet, if that’s how you pronounce
your name, for following. Thank you very much. Change that index there. Hides all the pizza
from Isotv, says Asley. OK, so I want to say if the
user’s pressed left or right, move the ship left or right. Now, what we’ve normally
been doing is in love.keypressed we’ve been doing that. Love.keypressed is a callback
function that executes only when the key has been
pressed one time and will not trigger when you hold it down. What we want to do is hold the
key down and move left or right. So, Love has a handy
feature, a handy function, called love.keyboard.isdown
which can take a string key. So you can say, if
love.keyboard.isdown left then– remember if statements need thens– ship.x is equal to ship.x minus
ship speed times delta time. And we haven’t defined ship speed. But remember, delta time is how we
scale any movement operations such that if one frame has elapsed,
we’ll move one frame’s worth, one sixtieth of a second’s worth, of that
whereas if two frames have passed, it’ll be twice as much, the
delta time will be twice as much, so it’ll move twice as much the amount. So it will effectively
scale to however much time has passed since the
last frame, which won’t be much of a problem in this example. But when you do have games that are
more complicated and a lot of time can potentially pass
between an individual frame and you want it to run smoothly and
consistently on different people’s computers, you want to
scale it by delta time. If you don’t, this will run as fast
as the CPU is capable of running it and that will not serve us any good. Now, this is a design decision. You can say, do I want to put
ship speed in the ship class? Or do I want to put it
in the constants.lua? And I don’t know if I have
strong feelings on it. But probably putting it in
constants.lua will be what we do. And let’s say I want to move– every
second I want to move 80 pixels. I’m not sure how good
that’s going to be. A second is a fair amount of time and
that’s about a third of the screen. That might be too slow. Let’s set it to 100. We’ll see how that feels. So remember, since this is
getting multiplied by delta time, this is effectively how much
time the ship move per second– 100 pixels per second. So now that works. If– and let’s say else if here– love.keyboard.isdown right, then. And I had a bug where I did– there’s a subtle bug where you can do
elseif and that creates a new block and triggers a syntax issue. So be careful about doing that. Elseif is different syntax in else if. Elseif as one word can trigger scoping
issues differently than else if. I don’t know if I said that right. The two are different. Ship.x is equal to ship.x plus
ship speed times delta time. So now if this works, which it doesn’t. The reason that it’s not working
is because I’m not actually calling the update function in main. And that’s important. We want to actually do that. I’m going to go to main. And I’m going to, in my
update function– notice that love.update takes in delta time. So you can pass that delta
time to anything you want. And any class or any object that
needs to do these overtime operations can scale that operation with that
same delta time value, that same float, right? So I can say, ship
colon update delta time. And now I can move my
ship left to right. Now unfortunately, there’s a bug where
it moves past the side of the screen. We don’t want that to happen. That fortunately is pretty easy to fix. I can just say math.– what is it? Math. It’s going to be the greater of these. So, math.max will always set the
value to the greater of two values. It will return whatever the
greater is of two values. And basically by saying the max of
zero or this subtraction on the ship.x, we’re basically saying if
it goes less than zero, if we set the x to negative
1, well math.x is going to say that 0 is greater than negative 1. So it’s always going to only
set it to zero if we try to move beyond that point to the left. So it’s effectively clamped our value
within the left border of the screen. And I do the same thing with math.min
to virtual width minus alien size– or alien size is fine because
the ship’s the same size. Do the same thing with
math.min because math.min will return the lesser of two values. So if I’m smaller, if I’m at an
x-coordinate that’s less than the virtual width minus alien size,
which will be taking into consideration the alien being 12 pixels and
reaching the right side of the border, we don’t want it to go farther
to the right than that– the value of that is going
to be less than the ship increasing its x by some value if
we reach the edge of the screen. And so it clamps it to the right side. And my hands are in the wrong
spot because I’m flipped– right, left. But that’s what math.max and math.min– those are hard to say, especially
when your mouth is dry. Those are hard to say but
those are the functions that allow you to restrict
a value from exceeding some value in the negative or positive
direction– math.min, math.max. And so now I should be able
just move left like that. Pressing left, can’t go
any farther than that. Pressing right can’t go
any farther than that. So we’ve effectively clamped our
value within the edge of the screen. So we’re getting and closer to the
Space Invaders actual implementation. After pizza, liquid
beverage [INAUDIBLE].. I would guess the ship
because the aliens have their own specific
vertical speed, right? I apologize I don’t
remember what I asked. Keep the information encapsulated. Hopefully we don’t run into another
wall passing entity like with Pong. That was unfortunate. 3D physics can be quite challenging. But Ereney did a great
job helping us fix that. That was awesome. I think I missed that stream,
but I had the same thing happen in the Pong version in Love
2D in the course, says Majordufai. Oh, yes, because in the course if you– we don’t implement interpolated
collision detection. So if– I appreciate Bavich_knight,
three sodas for Colton. If you don’t interpolate
your collision detection and you have something increasing in
speed, which is what we did in Pong. If you kept playing the
game long enough the ball would just keep going faster
and faster and faster. If it gets to a certain point
between one frame and another frame it’ll actually move beyond the paddle. And so you won’t be able to
do an A, A, B, b collision check between the two objects
because they don’t ever overlap. It moves so much in one
frame that they never touch. So you need interpolated collision
detection for a case like that. And interpolated collision detection
just means between frame A and frame B, if the distance between them is
larger than the size of the object then you need to basically
check for every object size, check the gap of every object size
between the object and the target– sorry, between the object and its
current position between the two frames and then check for A, A, B,
B on each of those points. And it’s a more sophisticated
collision system. And you’re thereby adding collision
checks, more collision checks than one every frame which can get expensive. But that’s how you do more
realistic collision detection and that’s how you would
want to ship ultimately something that can function
properly for an actual release, if you’re going to release your game. Otherwise you have a bug. But yes, good point Majordufat
for mentioning that. OK, cool. So we have ships. Sorry, we have one ship. And we have a ship that can
actually randomly change to accommodate both Asley and Babic’s
artistic decision, so two ships. Now what we need to do is decide
how to make aliens appear. We’re approaching the three hour mark. We’re probably going to
keep going for a little bit longer so we can kind of cement this,
because we’re at a point where– I don’t think we can comfortably
leave the stream with as much as we’ve implemented today. But we have the ship moving. The next big piece
would be having aliens appear, so having a bunch of aliens
in a grid at the top of the screen, like we do in Space Invaders. And then another important
piece of the puzzle is having the ship be
able to fire projectiles. And the projectiles are fairly easy. The aliens are fairly easy. We might be able to do
that within the stream, and then maybe finish the next stream
with actually making the aliens move down, have different levels, have a
score, and all that sort of thing– and be able to die and
lose lives, and have lives, and have a screen that tells
you how many lives you have. That could be a good
part two of the stream. But today we’ll try
and get all the aliens on the screen with the
laser shooting from the ship and call it a stream for today. So, alien is going to be the
class that we use for this. And what I think would
be the best way to do this is to simply have a table
of aliens that we can just iterate over and render, right? So I can say– actually, let’s do– let
me go up here and here? I think it’s aliens. So I’m making his global. And I’m actually not
defining them as galiens, just because in this particular
context it’s a little bit– doesn’t feel right. I guess technically you’d probably
want to do it, galiens, gship. But we’re not going to use
them throughout our project. We’re only going to
use them in main.lua. So it doesn’t really necessarily make
sense, but you could go either way. But I’m going to create a table. And basically all I want to do is,
I want to say for y is 1 until– how many aliens do we
want wide and tall? How many was it in the
actual Space Invaders game? Let’s go into this, Space Invaders. We have 1 2, 3, 4, 5, 6, 7, 8, 9,
10, 11 4, 5, 6, 7, 8, 9, [INAUDIBLE].. Looks like 11 between both
of those screen shots. So we’ll do 11, 11
ships wide by five tall. OK, so ships tall,
it’s going to be five. Do for x equals 1 to ships wide,
do– and ships tall, that’ll be five. Ships wide will be 11. So we can go into constants. We all need util any more. We can get rid of that. I don’t know if we’ll
need entity anymore. I’m going to just close that. Ship we’ll leave open for now. Alien we’ll leave open
because we will need that. And dependencies we will
need in a little bit. So constants, ships wide equals
11 and ships tall equals five. Remember, avoid magic numbers. So, generate rows and columns of aliens. So again like I said before, the 2D
loop, the iteration, this pattern, we’ve seen this many times. We saw it before when we did
Snake, when we had the grid. We saw this in the memory card
game where we had cards laid out. We saw this in the– oop, what did I have? Yes, not ships wide says
Brenda, aliens wide. Yep, you’re right. Thank you very much– aliens tall, aliens wide. Let’s fix that. Yes, ships, since it’s
not the ship, yes. Yes, correct. You get 256 sprites, well,
minus the two for the ships, from which you can choose, right? So if you convert a random int
in one 256 position of the grid it makes it more readable and
less of a headache to implement. Makes it more readable and less
of a headache to implement. [INAUDIBLE] JPguy, we are getting
to selecting the sprite but I’m not sure what you are referring
to because this particular part here is going to create the alien objects. Oh, well, that’s even easier. That’s even easier, yeah. No, yeah, to generate
a random alien yeah, we just need to pick a
number between one and 256. Absolutely. But what we’re going to do for now,
we’re just going to create a new ship. So table.insert aliens. We’re going to insert into the aliens. I got something in my eye. Ouch. That hurt a little bit. Into the aliens table we’re going to
insert a new alien object with the– and we’re calling the constructor,
the alien with parentheses. And I’m going to say we want
to generate them in a grid. So we’re not going to worry about the
perfection of the grid at this moment. We’re not going to make sure it’s
perfectly centered and aligned. We’re just going to say, x– [INAUDIBLE] off of x? Oh, you know what I should do also? Is get rid of this
arbitrary draw call here, love.graphics.draw, because it was just
drawing an alien in the top corner. Sirthranduil56, thank you
very much for following. We’ll start off at the top left. So we’ll say x times alien
size and y times alien size. And then this is what
JP was referring to. We’re going to say math.random 256. And what we really should
do is say, aliens– is that what we want to do? Do we have any constants in here? We have the width and height but
we haven’t made this constant. So we’ll just say 256. 256 for now is fine. And so what that’s going to do, that
will now give it a random sprite value. So we are creating a table of 55 aliens. We are giving them a random– or, not a random x. We’re giving them an x and y that’s
deterministic by this nested for loop we’ve created. So it’ll create a grid. They’ll be right on each other,
so they’re not spaced out. They’re not padded, which
we probably want to fix. We can do that. We can do that fairly easily. We’re going to not only generate them,
but we have to actually render them as well in our draw function. So not only we’re going
to render our ship, we’re going to also render in
a loop, draw all aliens, again following this 2D pattern that
we’ve seen time and time again. For y is equal to 1 aliens tall do– or actually, no. We don’t have to do that. Because each individual alien
is keeping track of its own x, y we can do something even simpler. We can use iteration. You can use Lua’s pairs enumeration
function, iteration function. So we can say for blank
alien in pairs aliens do. And if you’re unfamiliar
with what this is, this is how Lua does iteration
over a collection– iteration when there’s only one collection
type in Lua which is the table. And so it receives a key value pair
for every index in this function call or every result of this
function called pairs. This function called pairs is part of
Lua and it takes a table as an argument and it will give you every
key value pair in the table. And we don’t care about the key
because we only did table.insert here. Table.insert just inserts
things starting at one. So all the keys are going to be 1,
2, 3, 4, 5, 6, 7, blah, blah, blah, blah, until we’re at 55. We don’t care about the key. We care about the alien itself. The value is the object,
the actual alien object. So I can just say, alien
render at that point. Because remember, alien–
and we have to make sure not to overwrite the render function. Alien inherits from entity, and
entity has a render function that just draws itself, its x, y, and
the sprite that it has reference to. So super, super basic. It’s just going to maintain a reference
because we specified a random sprite index here as part of the
constructor for the alien object. You’ll have a reference to that. Each individual alien object has
a reference to that, self.sprite, and has its own self.x and self.y. So we can therefore draw it. So if I do this, I have a bug. Main 59 alien render– render. Did I not to– include equals entity, yep. Mm-hm. Entity does have a render function, yep. Something is wrong. What did I do? Table.insert into aliens
blank in pairs aliens do– uh-oh. Live coding, here we go again. Attempt to call method
render a nil value. Did I– I did include alien, right? Yep, I did. OK, it’s definitely
inheriting from entity. Alien is doing that,
includes equals entity. The init function– yeah, it is
inheriting from the init function. What’s going on? In pairs of aliens to alien render, yep. There’s a render function. This is very strange. We can do it, chat. We can figure it out. Let’s make sure– so it’s saying it’s
trying to call the method render which is a nil value, which
means that the alien object that it’s getting from pairs aliens
doesn’t have a render function. But that’s not– wait. Aliens is here. It’s global. We have access to it. This is where I want to have– Twohourstrike, should it be called
class with the curly brackets instead of the curly brackets? No, you do need the curly bracket. So in Lua, if a table or– what is it? How does the exact syntax go again? If you have a function that takes
a table as its only argument, you can call that function
using dictionary syntax. Sorry, I keep saying dictionary
interchangeably with table. You can use these curly
brackets as the function call. So for example, I have a function
called hello which takes in a table, in print tab.text. So let’s assume that I wanted to
call hello and pass it in a table then like that, which has a key called
text that has the value of the string, hello. So calling this function will basically
print whatever that table’s text field is, which is hello, right? So it’ll just print hello. However, part of Lua allows
you to actually do this. If your only argument to
a function is a table, you can just call hello
with the curly brackets. And it’s the exact same thing. And that is what the class, class, does
is, its only argument is just a table and so therefore you can call
class with just the curly brackets. Do we need the parentheses around
the alien in the for enum loop? Yes. Yes. The– oh, wait, sorry,
in the underscore alien? No. No, you do not need
parentheses around these two. These will work just fine. Why is alien not rendering? That is so– that bothers me. OK, we have a subtle bug here
that we need to figure out. Oh! Nope, I figured it out. It’s stupid. Well, it’s not stupid. It’s a good thing to
take into consideration. Because alien was
imported before entity, the alien constructor–
this still gets called. This gets called when we require it. When we call require,
this executes this line. And when you see this dash
dash includes equals entity, it’s going to look for
this thing called entity but because it actually
came before this, it’s not going to know what that is. And so it’s going to be nothing. It’s going to be nil. So this actually needs
to go up above this. Entity, when you load base classes
because the way the library works, you need to import that first. And then what do you know? It works. But yeah, that was the
bug that we ran into. Be careful when you’re doing that. Base classes do need
to be imported first. JPguy says, damn. All right, well again, that was cool. Now we have aliens! Now we have random aliens
rendering to the screen, right? Good thing you discovered that. I would never have found it. That is, yeah. It’s something that I struggled
with at one point, I think. It was a subtle issue. Yeah, it can be tough to reconcile
the alphabetical stuff with that. But it’s not too big of a deal
often, because it’s not usually huge dependency chains where
a bunch of stuff out of order relies on other stuff out of order. It’s kind of like, we can kind of do
that and kind of make them separate. And so now it’s alphabetical and
we’ve sort of separated the idea of what those are– these being dependent classes
and these being parent classes. But yeah. Quick call it entity AE. I don’t– oh, AE entity, yes. Yeah, yeah, that’s beautiful. Good thought, good thought. OK, so we’ve got our aliens
all running to the screen. And the other problem is, if you’re
running it, if you’re running the code, you can see that the
color is very different. You can especially see it now that
we have all of those ships rendering. It may or may not be
easy to see on stream. I can certainly see
it on my screen here. And you can probably see it if you’re
running it on your screen at home. So what you can do– on a Mac at least, and because
you’re on a Windows machine– if you’re going to Windows machine you
won’t be able to do this as easily. But you can’t require entity
in alien, says Math08. You can. You can certainly do that. Putting it all in one
place is better practice, but yes you can require it
in alien if you want to. And I don’t recall offhand whether
Lua re-requires it at a certain point and either overwrites
it or includes it twice. I think if it knows that
it’s already required it, it’ll be smart enough
to not do it twice. It’s been a while since
I’ve looked at it. But yeah, that’d be
another way to do it too. You can require entity
in alien so that you don’t have to worry about the
dependencies getting screwed up like that. But then you’re searching through
potentially dozens or hundreds of files looking for proper dependencies. So it can be kind of
a double edged sword, so I’d be careful about
doing something like that. Oh, Jacobchaussen says, why not change
the game background to match it. Well, good thing you brought that up. That’s actually exactly what
we’re going to do right now. So I’m going to render the game. I’m going to use an app
on my Mac called Colors. I’m going to click on this, click on
my little handy dandy color picker, click on that pixel. It’s going to tell me somewhere– well, it should have. It used to. Why– well, now I feel
like kind of an idiot. Normally, this application tells
you what the color is, spectrum. Thank you very much, Meeedo– what is that? I can’t read that. Meeedooe, thank you
very much for following. Crap, where’s the– normally there’s a– it gives you the hex code. Where did the hex code display go? Developer? Grayscale slider, RGB sliders– oh, there we go. 20, 10, and 30. So those are the alpha– sorry, the RGB components
of that background color. So twice as much red as green,
three times as much blue as green, and therefore a
little bit more blue than red. It adds up to be kind of this
off purplish color, which you can’t actually see individually
on the color picker here by itself because it’s not juxtaposed
against the pure black background. But you can certainly see it if
you’re looking at the black background with the sprites. So, what we’re going to
do, take that color picker. And then I’m going to– so, it’s 20, 10, and 30. So what we can do is, get rid of this. 20, 10, 30 RGB, 20, 10, and 30. I can quit Colors, or
at least get rid of it. Let’s quit it. Now, Love 2D changed the
way they did RGB with 11.1. It used to be that you could just
literally write in 20, 10, 30 in your Love.graphics.setcolor. Now we actually have to do
it a slightly different way. So here’s what we’re going to do. I’m going to say, Love.graphics.clear. Love.graphics.clear will
just clear the screen, will just wipe the screen
with a given color. So, 20, 10, 30 was how we
used to be able to do it. We can’t do that anymore. Now we have to basically
say, what is it? It’s over one, so it would be 20 divided
by 255 and then 10 divided by 255 and then 30 divided by 255. You don’t have to put the
parentheses there necessarily. But that is how you now
have to do it, because now the love.graphics.clear,
love.graphics.setcolor, all those functions, they take
in numbers from zero to one. So by dividing all of
those numbers that we just got by 255, which is the upper
bound for any of those numbers, we get a value from zero to one. So if it’s 255, it’ll just be one. If it’s 20 it’s going to be whatever
the fractional amount is over 255. So that will give us
the color that we want. If we render the background
now, it is indeed the same sort of purple black color
and everything looks homogeneous. Not homogeneous, consistent. So, yes. Lua requires once, says Twohourstrike. OK, good to know. How can we stop Lua from
rendering the same aliens twice? Well, a couple ways you can do that. You could have a table within which
every time you generate a new alien, you just insert that value and then
you check to see on every iteration whether that alien index
exists in the table. So just fill a table with
numbers and basically do a check to see if that
number is inside the table. Good question. And you could optimize
for speed by setting the actual index, the actual
key of the table to that number, rather than making them values. So that way you can do a simple
almost constant time check to say, if index table bracket five,
which will return a value. You can set those all
to true and then that will end up giving you the
correct Boolean value for that. But yes. I don’t think we’ll
implement that in this case. But you could certainly
add it fairly easily. I would encourage you to try and
implement it yourself actually and let me know if you can or if
you have any luck doing so. Nestleeric, or Nestleeric says,
finally caught a CS50 stream. Feels bad, man. Yeah, thank you very much for joining. Glad you came. It’s about to end fairly soon. We’re going to finish
a couple of things. We’re going to do the projectiles,
or shooting up towards the screen, and then maybe lay the aliens
out a little bit nicer. And then we’ll have the foundation
upon which we can actually do the game behavior for the next stream. And this stream was a
little slower and didn’t cover quite as much, we didn’t
get it quite as far, I should say, in the game implementation as
we have done for prior streams. But this stream is a
little more complicated. We’ve been covering new stuff, like the
texture splitting and stuff like that. So it’s therefore in classes I’ve
talked about object oriented programming and using that and getting more
modular with the design of our game. But I’ll post this on
GitHub and everybody can mess around with it a little bit. And then on the next stream,
which probably will be– it’s going to be tough this week
because we have the hackathon, so Nick and I are streaming tomorrow. And then Andy and I– Andy Chen, who is going to talk about
biostats in r, the programming language r if you’re familiar, he’s
going to come in on Wednesday. Jacobchaussen, sorry
host, what’s your name? My name is Colton Ogden, so thank
you for joining for today’s stream. You’ve been in here
for the whole stream. It’s been a pleasure having you. We’re not done just yet,
but just to give you a sense of what we’re
doing for the week. We have that CS50 hackathon
this week on Thursday, which is a very busy, very long event. We probably won’t stream on Thursday. And it’s an all nighter so probably
won’t stream on Friday as well. And then it’s the weekend. We don’t typically
stream on the weekends. The week after that I think we’ll
probably have time to finish it up. If not this week, definitely
next week we’ll finish it up. But we’ll at least get it off the
ground so that you can mess around with the code if you want
to before the next stream, and I encourage you actually to
tinker with it just to get a– try and see you would do it compared to
how I would do it for the next stream. OK, so we’ve done all of that. Aliens are now getting
drawn to the screen. We have the ship moving. We have the same color
background so everything looks good, looks consistent. So what we need to do
next is shoot stuff. We want our ship to be able
to move, and not only move but also shoot bullets, shoot
lasers, shoot projectiles. And I’m just going to
make a projectile class. These top level comments aren’t
super helpful in this instance, but generally you want
a top level comment detailing how your class operates. And the projectile itself you
could think of as an entity. It has an x and a y. However, it doesn’t have the
same size as everything else. And I’m not actually going
to draw it with a sprite. So, I think I’m going to make it its
own separate class without deriving from entity. We’re not going to derive from entity. We’re not going to worry about
inheritance in this case. Create an init function,
our constructor. We will need a update function. And we will need a render function. And we will also need to
make sure that we require it so that it can actually be used. And so now, what we want to do is
basically say, in our main.lua– and we could do this
differently elsewhere. We could do this in the player class. But the Player class will therefor, if
we want to modify the list of aliens, which actually we do anyway, so. Essentially what we’re going
to want, the projectiles are going to be their own objects. And the projectiles are
going to have a velocity. And it’s going to be negative
or positive on the y-axis. Shouldn’t projectile
be required after ship, assuming that the projectile
will fire at the ship’s position and that will need access
to that information? No, actually it will not. The only reason that we
need to require the– it’s good instinct, yes, and
as I said, it’s good thinking. It is good instinct. But technically we
don’t need to do that. The reason that we needed to,
for example, include the– I forget what it was, alien? We needed to include
entity before alien, is because this code, this line
right here, executes on require. So when require actually imports
this file this line gets executed. And that includes looking
for this thing called entity because we make a reference
to in this call right here, in this table definition. However, if we only make a reference
to a projectile in a function– so in this case, any of the ship’s
functions or the alien’s functions– that code does not get
executed on require. So the symbol, projectile or whatever,
if the projectile symbol itself gets called– which it will because we
need to instantiate a projectile in the update function– that doesn’t get called on require. So by the time that
actually gets executed, require has gone through every single
module and required it in advance. Does that make sense? It’s different when you’re calling
it from a function versus when you’re actually calling this
top level includes statement. It’s a little bit of
a different use case. But good intuition, good intuition. So, in the ship class,
basically in ship update– you could do this in a
couple of different ways. You could do this in main. I could do this in love.keypressed. If I do this in love.keypressed,
it’s a global operation. Pressing space is not something
that the ship really does. It’s more the global game object. So because projectile isn’t vital
to make ship compile or vise versa, the order doesn’t matter. Got it. Essentially, yes. There is no technically
compiling going on. It’s more, the time at which it
looks for the symbol projectile is different in the context of it
being called in a function versus it being at the top level of the module. When you require a module everything
gets interpreted top to bottom. But function bodies don’t get called. They only get called when the function
itself gets called with parentheses. The function bodies
are just, it basically just tells Lua that this
function exists in this place but it isn’t run through the code. It’s just saying, when you want
to run through the code, when you want to call this function,
it’s here, it’s in this location, if that makes sense. Hope that makes sense. So it’s kind of not ideal to look at
love.keypressed, the global callback function, as the source
of firing projectiles. For escape it kind of
makes sense because you’re looking at the whole game and trying to
escape the whole game, as not the ship but kind of the player of the game. It’s kind of a player action. The ship action, even though
you’re controlling the ship, it’s not as wide reaching. You’re only controlling
one ship and the ship should have control over
when it fires the projectile. And this kind of comes down to
how you sort of see the game. And there’s multiple different ways you
could see the game and program this. What I’m going to do is, I’m
going to do it in the ship class. I’m going to say, if
love.keyboard.waspressed– and this function doesn’t
exist, by the way. We’re going to make
this function ourselves. If love.keyboard.waspressed space then
table.insert projectiles projectile up. Now, this might look
a little bit strange– rather, not up. Not just up but also x, y up. And this x, y should actually
be self.x, self.y up. A couple of things here. So first of all, we don’t have
access to this projectiles table. And we could do this in multiple ways. We could have a global
projectiles table which is in our main.lua, which
is one way you could do it and it would be fine
for a game like this. You can also pass in projectiles
to the update function. And this is a bit more of a better
engineered approach to doing it. And this is probably how I
would encourage you to do it. I would say in main.lua,
therefor, we can say local projectiles
equals an empty table. And now this projectiles table is
in our main.lua but is not global. We can’t edit this
arbitrarily across modules. This is only visible within main.lua. So we’ve tightened the scope
on its accessibility, which is important for something
that is going to be accessed by multiple things
in different modules. We’re making it harder to
screw it up, making it harder just willy nilly add stuff to it. And ideally the ship
should be this as well, and the aliens should be this as well. So I can actually say, local
aliens is equal to that and then get rid of this,
and then local ship. And we’re not going to
instantiate the ship in this case. But we’ll instantiate it in the
load function, as we’ve done. And let’s go ahead and,
in our update function remember I specified
that the ship should also update with the projectiles
passed in as a parameter. So now we can do that. We can say projectiles. So now the ship, when it
updates, not only will it be able to get the DT
from the update function it will also get the
projectiles table and it’ll be able to make changes
to that projectiles table. Which means we can add projectiles
to the projectiles table. Now, when we add a projectile
to the projectile table what we want that to mean is that
each of these projectiles should update as well. And by update, this will typically
just mean moving up or down, depending on whether they’re
going up or going down. And as we saw in the
ship class we specified in the constructor for
the projectile object here that it gets the string
up, because if we’re a ship and we fire a projectile we
always want that projectile to go up towards the aliens. And we want it to take
an x and a y as well. So this is how we get access to
information that’s in our main.lua, but within our ship class. So we’re modularizing our game a little
bit more by doing this and passing a bit more information
across functions, but we’re tightening things up a little bit. Yeah, uptime– we should
get an uptime bot. It’s been up for three and
a half hours approximately. We’ll probably finish before the
four hour mark with projectiles. And then on the next stream
we’ll finish everything up with the gameplay,
the different screens. We can use a state machine, actually. It’ll be a great way to introduce
the idea of a state machine into our game engine– our game engine? Our game here. The state machine just
being a way to move between different states of our game,
whether we’re at the title screen, whether we’re at the
actual playing the game, whether at the, like,
lost of life, et cetera– game over. We’ll look at that, because
we’ll have time on the next scene to do all of those fancy things. But here we’re passing
in the projectiles table. We’re going to be able
to add to it here. So now I actually have to
define what a projectile is, how to render it, et cetera, right? So what I want to do is probably just
love.graphics.line because a projectile really, really needs to be a
line, just a vertical line. Whether it’s going up or going down
it’s going to look the same, right? So love.graphics.line. It’s going to take in an x
and a y, so self.x, self.y. And it’s going to have a– it takes in another two arguments as
well, the second x and the second y, meaning where the endpoint
of that projectile is. An Isotv, yes, good intuition. Can we use the projectile table
to have the enemies shoot at us? Absolutely, and we will. We will be doing that eventually. That is good, good intuition. So let’s first of all fill out
the constructor definitions. We have an x, a y, and a orientation. And we can say self.x
equals x, self.y equals y, self.orientation equals orientation. And the draw function should also, by
the way, set its color appropriately. And let’s, just for
the sake of ease, just say pure red– that’s it, just R001. So we’ll just say 1 0 0 1. That’s full red– zero green,
zero blue, full opacity. And then we want to
set it back to white. White is the default color for
drawing operations in Love. So, 1 1 1 1. And then once we’ve started
drawing the line at self.x, self.y, we’re going to say, self.x
plus projectile– oops, sorry. We’re going to say, just at self.x– this is going to be the same
x-coordinate, but self.y plus the projectile length. And projectile length is a
constant we haven’t defined yet. So we can therefore define it. Projectile length is going to be
equal to, let’s say five pixels. And what I want to do actually is,
when I press spacebar as the alien I don’t want to just instantiate
the projectile on the player. I won’t actually instantiate
it above the player. I want it to look like it’s
shooting out from the player because if I instantiate it at
just where the player’s x, y is, it’s going to spawn
on top of the player. It’s going to look like the player’s
shot like from the middle of itself. It’s going to look kind
of weird, and especially if we do flexible collision detection
where the projectile and the– where the projectile and the– ba ba ba ba– where any projectile can interact
with both the ship and any alien, we’re going to want to make sure we
don’t spawn the projectile on top of the player or we’ll kill ourselves,
which is not ideal behavior. And actually I just realized, because
we’re using A, A, B, B eventually to do the collision
detection for this, I’m going to make the
projectile a rectangle– love.graphics.rectangle fill. And now instead of saying an x and
a y and then a second x and a y, I’m setting an x and y and
then a width and a height. So in this case, the
width is going to be one and the height is going to be five. It’s going to start at
x, y, the player’s x, y. And it’s going to be one pixel
wide by five pixels tall. But I want to make sure
that I set that to minus– sorry, not on the x, on the
y– minus projectile size– is it projectile size? Projectile length. Projectile length– wait no,
this is the draw function. This is not where I want to do this. Sorry. Projectile length, yes. So that is good. So this is good. I apologise if the chat is making it
hard to see what’s going on there. I want to draw a rectangle
of type fill at self dot– and it’s going to be a red
rectangle because we’re setting the color to red right before
it at self.x, self.y, width of one, projectile length height–
so five pixels tall. And then in the ship
class, this is where we’re going to actually
subtract the projectile length from the y of the spawn position
of the projectile, right? And then in our main.lua now, just
like we drew all of the aliens– actually, I’m going to draw,
before I draw the aliens, I’m going to say for_projectile in
pairs projectiles do projectile render. And now every time I hit spacebar,
I should get a projectile that– sorry, one more
thing, one more thing. We have to actually move the projectile. So now if I hit spacebar, it will
spawn a projectile and it will draw it, but it won’t actually move
anywhere because it’s not getting an update operation applied to it. So that’s important. We have to do that. So I can say, if self.orientation
is equal to up, then– or I guess direction
would probably be better? Let’s change that to direction. Orientation kind of implies like
a rotation, so let’s direction– self.direction, the
direction it’s moving. So if the direction is equal to up,
so if we’re going in up direction, then I can say self.y is equal to
self.y minus projectile speed times delta time. Projectile speed is not a constant
we’ve defined so let’s do that. Projectile speed is
equal to, let’s say, 120. I don’t know if that’s good or not. I don’t know if it’s balanced or not. This is game balancing, this aspect
of choosing variables that you think will work, choosing values that you
think will work, and then sort of fine tuning them as you go to make sure
that they’re not too overpowered or too underpowered, too frustrating. So we’ve done that. And then else if– or I guess I should say
else, because there’s not going to be any situation in which
the direction of the projectile is going to be not up or down. So self.y is equal to self.y plus
projectile speed times delta time. And now if I run this,
hopefully it should work. Was not– oh, right, we didn’t do the
key press thing that I talked about. That’s an important piece of the puzzle. So Love 2D does not give you the
ability to do single key press checking outside of the main.lua function. In the main.lua function you can go
to your love.keypressed function here, this love.keypressed key,
and then check to see whether a key was pressed on the
current frame, or the last frame. And that’s what we’re doing with Escape. But it doesn’t work if you’re trying
to test for this, the single press behavior, inside of another module
because there’s no way to check for love.keypressed for that given key. You have to actually extend this
class, the love.keyboard namespace with your own functions or
figure out some way to do it. The way that I like to do it, and
I believe I saw this in a forum a long time ago and I
decided to adopt it, is you say,
love.keyboard.waspressed index key is equal to true in
that key press function, because remember this gets called in
main regardless every single frame. So I press spacebar,
this will fire in main. It just won’t do anything if I
haven’t specified any logic for key being equal to Space. We’ve only specified if the key
is equal to Escape we should quit. But this actually fires for every single
key press at all times for anything we do. It doesn’t have any logic, so it’s
just empty function calls essentially until we’ve defined some
of our own custom logic. So we can say, love.keyboard.waspressed
key is equal to true. And this is a table that we’re
creating called Was Pressed, part of the keyboard namespace. You can add your own stuff to any
namespace you want to just like that. It doesn’t exist right
at this moment in time, because we haven’t actually defined it. So what we want to do
is, in our love.load say, love.keyboard.waspressed
is equal to empty table. And this doesn’t exist
in Love by default. Love.keyboard exists and it has a lot
of its own stuff, but was pressed? Love.keyboard.iskeydown, for
example, is a function that exists. It’s part of Love. Was Pressed is nothing. It’s not a function or a table. It’s something that we’re
implementing right now ourselves. So I can say, love.keyboard.waspressed
is equal to an empty table. Then, in our love.keypressed callback,
whenever we press a key we can say, love.keyboard.waspressed
key is equal to true. However, as some folks
may be thinking, this could cause issues because as soon as
it happens once it’ll always be true. So if you want to check to see whether
it’s true at any time after that, it’s not really going to be meaningful. So what we need to do– I’m just making sure I didn’t
actually turn off my belt pack, which it doesn’t look like I did. What we need to do is, we need
to reset this every frame. So every frame I need to
say, love.keyboard.waspressed should be back to an empty table. And we can do that by saying,
love.keyboard.waspressed is equal to empty table. And now it’ll just get
reverted back to an empty table once we’ve applied all of our updates. And all of our updates should
be what has the checking to see whether there’s
anything in this table. So once you’ve done all that
stuff, it doesn’t matter. We can then just clear it. We don’t need that information anymore. It’s used, it’s done, it’s gone, right? I believe that is everything. Oh, nope, sorry! One last very important
thing that we need to do is, we need to actually define the
function, love.keyboard.waspressed. This function does not exist in Lua. So we define it ourselves. Could we also use false instead
of an empty table, says Asley? No, because we want to be able to check
to see whether multiple different keys have been pressed. You could have a frame
where any given key is set– whether space is set,
A is set, Enter is set. If we just set it to
true, any of those keys will set it to true,
and so any condition that checks for any keyboard input will
be true and that’s not what we want. We want specifically to check
to see whether Space is checked, or Escape is checked, or maybe
some other key, left or right, are checked, because those will
get fired when we press them. If we press left or right and if
we set the table equal to true, then if you press left
or right we’ll also shoot and we won’t move because left and
right will also be checked, right? Well, actually in that case
love.keyboard.isdown would fire, so it’d be a little bit different. But every time we pressed left or
right it would fire, it would be true. And we’re going to index into it that
table anyway so it wouldn’t work. We need it to be a table
that we can index into. So all I’m going to do here is say,
return love.keyboard.waspressed– oh sorry, keys pressed, key. And I apologize. This should be keys pressed,
and this should be keys pressed, and this should be keys pressed. I apologize if that’s confusing. Keys pressed is the table. I apologize. I mentally made an error here. Love.keyboard.keyspressed is the table. That’s the table of keys– sorry, that’s why I think
Asley said what she said about, was pressed being a Boolean. This should be called keys pressed. I made a mistake. Love.keyboard.keyspressed
is going to be a table. There’s going to be all of the keys
that were pressed on the last frame, because we’re going to, anytime
somebody presses a key, record it in that table with this line here–
love.keyboard.keyspressed at index key is equal to true. So if somebody presses Shift, then
love.keyboard.keyspressed shift is going to be true. If someone presses spacebar,
love.keyboard.keyspressed space is going to be set to true. So we can then say, if
love.keyboard.waspressed space– because what we’re going to do, this
function, love.keyboard.waspressed, this is the actual function that’s
going to return true or false. Love.keyboard.waspressed key
takes in a key parameter. And we can say return
the Boolean that’s at key indexed into that keys pressed table. So if someone says
love.keyboard.waspressed shift, it will return whatever
love.keyboard.keyspressed shift is. And if it’s nothing, if nobody’s
recorded shift in the table, it’s going to be equal to nil. And nil and false are interchangeable
for how we’re going to use it, for an if statement. So that is sort of the
dichotomy between those two, between the was pressed
table and the keys pressed– sorry, the was pressed function
and the keys pressed table. So let me know if you have any
issues with that, if I wasn’t clear. I did make the mistake
between the two but hopefully I was able to explain it clearly enough. This, therefore, allows us then
on line 14 in the ship class here to say, if love.keyboard.waspressed
space, because now whenever we press space in main.lua it
will record that in the table, table.insert into projectiles
a new projectile self.x, self.y, minus projectile length up. And then in main.lua what we need to
do also, one very important thing, is for_projectile in
projectiles pairs projectiles do projectile update delta time. And then, ba ba ba ba, make
sure that’s going well. We have them rendering,
we have them updating. Now if I run this, this should work. Whoops, global ship at line 11. Oh, sorry, I wrote ship.x. It should be self and I happened
to get lucky in that I named– see, this is why global
variables are kind of an issue. I named ship. We had previously ship as a global
variable in the main.lua module. Because of that, here where I wrote
ship.x and then it changed its x value, it was actually manipulating
that global ship value which it shouldn’t have been doing. It should have been
manipulating its own x value. So here changing it to self. But that wasn’t a terrible problem. But that’s an example of where you can
easily get global variables causing issues with each other. Now if I move left to
right and I hit spacebar, well, now I get projectiles
that go through the screen. The only problem is
that these projectiles will go on forever and ever and ever
and keep rendering and keep updating. So we could theoretically have
like, hundreds of projectiles– thousands, millions, I
mean infinite, however many until your computer exploded, right? Which would be a lot because these
aren’t taking up very much memory, all of these projectiles. But it is iteratively
updating and rendering all of them, every single frame. So you want to be careful
of doing stuff like that. What we’re going to actually do is
use what’s called an object pool. Actually, well, not
really an object pool. But we’re going to enforce the
lifetime of these projectiles such that when the projectile
goes beyond the edge of the screen after up or bottom, it will just delete
itself, remove itself from the table. Or, main will clear it
from the table, right? But yeah, I mean, that’s the basis
for getting the ship rendering and the projectiles rendering. But there is a much more
efficient way that we can do it involving lifetime management. Hopefully it won’t cause a stack
overflow, says Bavich_knight. Yeah, I don’t think in this case
it would cause a stack overflow. I think this would be a– this is heap memory, so I don’t
think it would get a stack overflow. I’m not sure exactly what issue you
would get after a certain point. But yeah, all of those
things are not good. Looks so cool, says Asley, yes. And then JPguy says, alrighty. Alrighty indeed. We’re at the 3:50 mark. I’m going to commit all
this code to GitHub. It’s been a long stream. We’ve been taking things kind of slow
and that’s part of the fun of it. And hopefully it’s
been fairly digestible. I can try to go a little
bit faster next time. But I think we covered
a fair amount of ground. We covered projectile– or not,
well, we did just cover projectiles. But we covered moving
stuff continuously, which we haven’t really done. I guess we did it in Pong for the Unity
session, which is little bit different. Same idea, but we haven’t actually
done anything like this in Love yet. So it’s actually been cool. It’s been very fun but my
brain doesn’t work anymore. Lua is a stack language. It’s a language that runs on top of
C, so yeah, by virtue of that it is. You can get stack
overflows with Lua because underneath the hood you’re
still running the same memory model for your application. Twohourstrike, you are overwriting
love.keyboard.waspressed table. Yes. Yep, overwriting it, setting
it back to an empty table. I like the interaction
but I can understand that you want to finish
the project during streams. Yeah, yeah. No, I do. I do like finishing the project. Some projects are just infeasible to
finish over the course of one stream, honestly, for four hours. Some of them, like if we were to
make a dungeon crawler, that’s like, that could take weeks
of continuous streaming. And even if we were to stream like
eight hours a day, some of those could take a long time. But by the way we are contemplating
doing like a eight hour super stream at some point,
probably in the spring, like a Python super stream
or maybe a C super stream. So if you’re interested in
that, definitely let me know. That would be covering all
of the basics of Python for someone who has zero
experience, or JavaScript for someone who has zero experience. Lua we’ve kind of touched
on it a couple times. A couple of the streams
that we’ve done have sort of built up the language and the syntax. I tried to go over the lot of that
for the Snake stream a while back. But yeah, it’s something
that we could definitely do. I think that’d be a lot of fun. A lot of people get really exhausted
doing streaming for that long. I don’t really get that
exhausted to be honest with you, if we can keep it casual. I would get exhausted sticking
to the script, I think. That’d be the worst. This is much better for me to
do long continuous streaming than it is to do a rigorous
outlined sort of thing. Having an objective and working
towards it, it’s also more fun. But that’s just me. Let me know what your thoughts are. It seems like everybody’s having
really positive things to say, though, which is super awesome. Thank you guys so much. The pace was really nice
for a newbie, says Unsigned. Good! I’m glad that it was– because
I felt like I was going too slow but I’m glad that you
felt the pace was good. Favorite stream so far, says Asley. Awesome, thank you so much. Onedayinmylife says, I would not mind
at all if you streamed for eight hours. Yeah, that would be a lot of fun. I think we’d have to do like a Python
super stream for that or something that a lot of people would like a lot. I don’t know. We’ll think about it. This was so enjoyable and educational
even though I have never heard of Love. The video was so cool. I’ll definitely watch
the second part of this. Awesome, yeah, thank you so much,
Jabcochasen, Jabe Co Chasen. However you pronounce
your, name definitely let me know so I can say it right. Jpguy, 24 hour coding stream, ugh. If I can call in some ringers
I think we could do that. If we like David code for a few
hours and I code for a few hours– that’s essentially what the hackathon
is though, coming up on Thursday. Kudos to Colton for doing
this long without a break. Yeah, thanks. I’m glad I didn’t drink a lot of fluid
in advance because this would be rough. Iso says, eight hours
streams would be so awesome but can’t even imagine
how taxing it might get. It really depends on what
you’re doing, because I would get super taxed if this were like a– if I had like a strict script to follow
and like, pages and pages of stuff to go through and there was no
conversation and no casual feel to the atmosphere, this would be– eight hours would be terrible. But if we’re just having fun
and having a conversation and making a game together and
working toward something loosely, but like on a path and having
goals but not worrying too much about whether we’re sticking strictly
to a timeframe, I could go forever. It’s not a big deal, right? I think explaining it is
what’s making it slow. John Blow, I watch his streams,
dude gets a lot done in two hours. Yeah, yeah, no, John
Blow is super talented. I’m waiting. I’m super eager to see his
programming language Jai, by the way. I’m very eager to see
that and try that out. Yeah, he’s very talented. I think if this was just me coding
and just saying, ah, blah blah blah, doing whatever, I probably wouldn’t
be making Space Invaders first of all. This is largely to be educational. But if it were just like
casual no explanation, I think I could get a lot done, too. But that’s not super useful
for a lot of people, I think. I think this is good to converse
and make stuff together. Super stream for JS would be good. We’ll be in force, says Bavich_knight. Awesome. Yeah, we’ll definitely consider doing– we’ll consider doing both of those. You say the last name right. Job Coachuson– Cochasin. J from Java. Jobcochason, you say
the last name right. Cochason or Cochuson? Andre, I can’t really
say fully about today. I was busy but I was here on and off. But the way you do
these streams is great. Awesome, thanks Andre. Glad you think so, appreciate it. Is a good stream. Do you plan on going over entity
component system in love 2D and Lua? Entity component system, maybe? It’s something that
we do a lot in Unity. I would be happy to touch
on it at some point maybe for a more complicated game. That’s really not something
that’s meant for a game like this. Like, a game like this does not
need an entity component system. It’s way overkill. But something like an RPG would
benefit hugely from an entity component system, and Unity games generally. And Unity makes it really easy to do it. So Unity is a great environment to
test that out and talk about it. We can talk about it more in
another Unity stream, perhaps. Brenda says, we should bring back the
Breakout in C, piece it as a stream. Yeah, that’d be addressing. Yeah, that’d be cool. We should take a look at it. I’m not a huge fan of the
Sanford Portable Library, though. It’s a little bit weird. I feel like it’s cumbersome. And it’s not super widely used. I’d probably prefer
doing Breakout in Love. But yeah, good, good, good point. Maybe just for history’s
sake we could do it. Another interesting concept of
a less interactive based stream, the development of a full
fledged game in real time where a whole team is just working
and communicating without– mouse is in the way– looking at the chat. Yeah, maybe. I feel like that’d be
boring for a lot of people. I feel like not a lot of
people would watch that. Only people that are super engaged,
I think, in the process of doing it would be interested. But I can’t imagine very many
people would want to see that. And also, how we would display like
having multiple people’s screens and being to see what people are doing? I feel like that’d be like
a camera in a room looking at a bunch of people on the computer
and just a bunch of conversation. I’m not sure. It’s a cool, interesting idea. I think it would maybe work if
you could see multiple people’s computers at the same time. Yeah, one day can’t wait to try out Jai. Yeah, that’d be awesome. The language looks cool. I’m excited to check it out. Is there any particular reason
why you choose Lua as a language, says Unsigned? Mostly because I really
like the Love framework. It makes it super easy to make games. And the language is pretty nice. It’s also very often used in the
game industry, so a lot of engines use it as their language,
their glue language. It’s all over the place. Isotv, are we having
another stream tomorrow? Yes. We are having a stream
with Nick Wong and he’s going to be talking about
setting up a web server with AWS. So if you want to create a web
application or a lot of different stuff in the cloud as opposed to your own
physical system, we’ll talk about AWS and using an Apache
server, using Ubuntu Linux. And we’ll talk about a
bunch of other stuff. And knowing me and Nick
and how we do our streams, it’ll probably go off on a
lot of interesting tangents and explore a lot of cool ground. So tune in for that one. Let us know what you
want us to talk about. Love a Python super stream, says Otter. Yeah, me too. I think that’d be cool. I think coding videos
without comments are boring. Cannot watch them, much prefer these. Yeah, me too Asley, I agree. I think it’s much more interactive. I don’t think a lot of
people want to watch me sit and just code and kind of mutter
to myself for eight hours. I think this is a lot more entertaining. And then JPguy agrees. Makes it easier to
understand if you can ask. Yep, exactly. And it’s good feedback
for me to know what I should talk about more, as opposed
to just kind of gloss over, you know? Andydicomona says some
Unity would be brilliant. Yeah, we’ll talk about it another time. Jabcochasin, good to have you. Thanks for tuning in. It’s 2:00 AM, wow. So yeah, thank you for joining us. We’ll catch you on the next stream. Mocroonderjebed, I’m not sure if
I’m pronouncing that right at all. Probably not, but thank you
very much for following. Yeah, not the most interesting
content to livestream. If I was going to
livestream idle stuff, I’d livestream gaming because
I like gaming a lot more. I think that’s more entertaining. Not on CS50’s dime, but probably
on something that I would– maybe for a private stream or something. Although we do have
the Super Mario stream that we did with David
because that felt appropriate. So check that one out. We did that last week. That was super fun. We beat all of Super Mario
Brothers One on stream. And David did most of the game playing. And Kareem also did an excellent
job being his sidekick for that. 10:00 AM for Brenda, about 3:00 for
Babic Wow, the world is a crazy place. What time will the stream begin
tomorrow, says Beerman5000. The stream tomorrow will be at
3:30 PM Eastern Standard Time. So a little bit later
than today’s stream. It’ll go for about two hours. I’ll stick around for a
couple more questions. We are just hitting
the four hour mark now. But if you have any other
questions, definitely let me know. And we’ll call it a day. Oh, I was going to commit
everything to GitHub. Shame on me. Let me make sure I’m in the right spot. I’m not. Let’s go into Space Invaders,
get init, make a new repository, do the horrible act of Git add dot. Git commit initial commit, which is– actually we’ll do ships and
aliens rendering with projectiles. And then Git remote at origin. I got to actually create the
repository so I’m going to go to GitHub and create that. Do I have a rubber duck? Ooh, not in here, which
is kind of terrible. Do I have a rubber duck in here? This is like the one room that CS50 has
that does not have a rubber duck, which is kind of embarrassing. The best we have is the CS50 Muppet. will he stay up? He will. I should have had this on the
stream with me the whole time. Aw, man, I regret that. This is the best I have. It’ll function as a rubber
duck if you need it to. OK, let’s create a new repository if we
have nothing on there that’s private. I don’t think so. Space Invaders invaders stream,
live coded implementation of– Jellybelly1991, thank you for following. Live coded implementation
of Space Invaders on Twitch. Ba ba ba ba ba ba ba, public. It’s going to be public so all of
you can clone it, mess with it. Get the Git URL here. Git remote at origin– I spelled origin wrong, which
is not what you want to do. Git remote at origin, blah, blah, blah. Get push upstream origin master. So now all of the files that we
just looked at and created today are on GitHub. So I’m going to toss this in the chat. Testing, testing, testing. Testing, testing, testing. All right, that was very strange. So the reason that it crashed
is that Facebook events– we crossed a stream to Facebook. And because we crossed
stream to Facebook, the event was a specific length of time. And the event closed at 5:00 on the dot. So what we need to start
doing is, make the events longer than broadcasting amount of time. Well, I guess maybe after an hour
beyond the broadcast amount of time it’ll terminate. So, apologies for that. We also have bad gateway
stuff in the stream there. So let’s just go ahead and
get rid of that and that. As beautiful as that looks– it doesn’t look beautiful. I’ll finish saying all
the stuff in the chat. I apologize about that. That was not something that I
anticipated happening, but it’s OK. We’re going to end on a good note. We’re not going to let the
stream die just like that, right? I did not spill the drink. The stream Facebook basically said,
nuh-uh and terminated our streaming. And the script that we use for
that broke and therefore stopped cross streaming to
Twitch and to Facebook. So, yeah. That was that. And yeah, I wasn’t
answering the chat because I was trying frantically to figure out
how to get it back up and running. But we’re good. We made it. No PC crash, everything is great. I apologize if it’s echoing. I’m not sure why it’s echoing. But, yes, just so that we have
this at the end of the video and it doesn’t end in a very awkward
way we’ll take this as our farewell. And I’ll say, thank all of you for
joining us for this long stream. This was CS50 on Twitch. This was Space Invaders part one,
so part two on the next stream. Again, we’ll be making
the aliens centered, making them move left to right and
down, making them shoot autonomously– but only the bottom row, because if
the top rows shoot projectiles down they’ll shoot the aliens that are
right below them and kill them and that’s not good. So only the bottom row can shoot. We’ll figure out how to
do that algorithmically. We’ll figure out how
to get lives and score, and whatever other– oh,
yeah, the state machine stuff, that should take about
three or four hours, right? So this little mini stream is
only about a few minutes long. But yeah, this was CS50
Twitch, Space Invaders. Thanks to all of you for
coming to join us today. This was a lot of fun. I’m looking forward to the next one. Join us tomorrow for the
Nick Wong stream on AWS. And then join us on Wednesday for
some r and some biostatistics. It’s going to be a lot of fun. I know nothing about r, so
that’s going to be great. It’s going to be very
educational for me as well. Oh, and what’s his name, the muppet? CS50 Muppet I think
is his official name. I’m not 100% sure. But yes, thank all of you. Have a wonderful rest of your day. And I will see you on the next stream. Good bye.

4 Comments

  1. Naveen Singh November 27, 2018 at 10:02 pm

    Hello

  2. Hawk Force December 30, 2018 at 11:59 pm

    What in the world was this stream

  3. Dan & JJ April 7, 2019 at 3:18 am

    Wait… are u named Colton Noggin? That can't be your name…

  4. Dan & JJ April 7, 2019 at 3:22 am

    are u gonna make a pacman one? or roblox?

Leave a Comment

Your email address will not be published. Required fields are marked *