SPEAKER: All right, so in pong0, we took a look
at getting a window up on the screen.
We used a 16 by 9 aspect ratio--
1,280 by 720-- instead of the square aspect ratio
just so that we have something looks a little bit more
like what you would see on a modern screen.
And we also took a look at drawing something
in the center of the screen with printf.
So a very simple start with Hello, Pong.
Now we're going to approach a problem that we realized we had
towards the end of the last section.
And that's the fact that the text was just a little bit too small.
So with this update, we're going to increase the size of the text.
But what we're really going to be doing is emulating a virtual screen size
that's much smaller, much more like as if we were coding for, let's say,
the NES or the Super Nintendo.
We're not actually increasing the font size, but we are zooming in.
We're drawing to a virtual raster.
And ordinarily, that would be a little bit tricky.
But fortunately, we have something called the push library.
Now this is on GitHub.
This is Ulydev/push.
It's just a very simple library that essentially
has a virtual raster that you can draw to that gets stretched to fill whatever
window size that you want.
It's a simple download here from GitHub.
If you click this green button here, it'll be included with the distro code.
I've gone ahead and downloaded it in advance.
And it looks something like this.
This push.lua file is going to be what you actually get out of that zip file.
So just make sure you include it here with your main.lua
file in the same directory.
And I've gone ahead, and I've also, in advance,
created this pong1 folder here with the source code from the last example.
Now I'm going to open it up just in advance in VS code here.
So let's do that.
And I'm going to magnify that.
And as you can see, we have main.lua, and then we
have push.lua, which is going to be a little bit
intimidating to read through.
It's a little bit lower level.
And then in this case, I'm using the distro code for pong 0,
not the code that we used in the last section.
Just so we have everything consistent with what
we're giving out in the distro.
And also, you can see here there are a lot of comments
to highlight as you're reading through it-- maybe a little bit more iteration
upon which I've described already in lecture.
Now before we get to actually coding some improvements to this
and using push, I want to explain a few functions
we're going to be talking about.
So the first one is love.graphics.setDefaultFilter.
It takes in a min and a mag.
And this essentially lets us scale and de-scale scale images
without applying, in our particular use case, any blurring to those images.
Now normally, when you increase a image size, when you zoom in,
there's some blur.
There's some interpolation, specifically bilinear filtering.
It looks essentially at a pixel, samples the pixels around it,
and sort of calculates what that should look
like when it's zoomed in or zoomed out.
We just want nearest neighbor filtering.
We just want it to essentially take the flat pixel value when it's calculated,
when it scaled or minified so that it retains sort of a m retro look.
We don't want any of that blurried look because when we zoom in,
we start using fonts and images and the like.
Especially when we get to Mario, it just does not look very good at all
on a sort of simulated resolution.
Another thing we're going to take a look at,
which we didn't talk about last time even though we looked at game loops,
is love.keypressed, which takes in a key as an argument.
And this essentially lets us specify the behavior for whenever
a user presses a key at the keyboard.
If we decide we want to have escape mean something, in our case,
we're going to make escape quit the application,
and to do that, we're going to use this love.event.quit function, which
literally just quits the current love window.
And lastly, just a slide to illustrate texture filtering.
On the right side, you see what is normally
the default in love, which is when you scale up an image.
It gets filtered.
It gets blurred a little bit.
We want point filtering or nearest neighbor filtering.
And nearest is going to be specifically the argument we provide
to love.graphics.setDefaultFilter.
So I'm going to go back into my code here.
And the first thing I'm going to take care of
is just getting rid of that keypressed.
So I'm going to say function love.keypressed, takes a key.
And I'm going to do--
a key is just going to be given to us as a string.
So what I'm going to do is I'm going to say if key is equal to escape, then--
and then is important because then is sort of like the open curly brace in C.
It just means this is the beginning of my if statement of what
happens within the if statement.
So if it's the case that key is equal to escape, I want to just love.event.quit.
So I'm going to save it.
I'm going to rerun that.
It's got the same look as the last time with Hello, Pong.
But now if I hit Escape, it does indeed quit.
So I don't have to hit the red X. I don't have to do
Command-Q. It's very straightforward.
A lot easier if I'm just using the keyboard.
I don't want to mess with the mouse or any keyboard shortcuts.
Now the next part is going to be a little bit more work.
We want to essentially use the push library to simulate
as if we were coding on a smaller raster size
if we were coding, for example, the NES at 240p roughly,
which is as big as the screen sizes were back in the day.
To do this, the first step I'm going to do is specify a virtual width of 432
and a virtual height of 243.
And this is just a resolution I pick that's about 16 by 9
but very similar to what you'd see for the NES or something.
So it's still modern in appearance, but it has that old retro look to it.
Now the next thing I need to do is actually import the push library.
So push is something somebody else wrote,
but I need to get that functionality into my main.lua.
In order to do this, it's very simple.
You just do push equals require push--
just like that.
And it's going to automatically know that what you're looking for
is something.lua.
That's just the default here.
So push equals require push.
It's essentially looking for this push.lua file by default.
So now the next thing we need to do is push
operates with the window in a different way than the default
love.window.setMode.
Instead, we're going to do push:setupScreen.
This colon is very important, and we'll get to that a little bit later.
But essentially, push is an object calling a method inside of itself.
It's sort of like a function contained inside
of an object that has data specific to that
object as opposed to just a global object that belongs to a table
somewhere.
So this colon is important, and we'll get to that a little bit later.
push: SetupScreen is very similar to love.window.setMode,
but it takes in four arguments at the beginning instead of two--
VIRTUAL_WIDTH and VIRTUAL_HEIGHT for what we want our virtual raster to be
and then WINDOW_WIDTH and WINDOW_HEIGHT for what
we want to actually have our physical window be in terms of its dimensions.
Then we're going to pass in a table just like we did with love.window.setMode,
fullscreen's false, vsync is equal to true, and resizable is equal to false.
Now the last sort of bit here in order to get
push to actually work-- now we set it up,
but it's not actually going to be doing anything at all.
What we need to do is call something called push:apply--
again, a method on push with the colon there.
The colon is very important-- push:apply start and push:apply end.
And just for a little bit of space, I'm going to do that.
So this is a sort of a state machine way of thinking.
And you might not have learned about this.
But things like OpenGL, which you may have heard of.
Essentially, that's, in graphics programming,
you set a state, sort of a flag, or a switch somewhere
that says things are going to be done a certain way.
And when we say push:apply start, we're essentially saying,
we're going to be drawing things the push way.
Anything that happens after that is going
to be done with our virtual resolution.
And once we hit push:apply end, it's like flicking off the switch.
And now things are going to be drawn the normal way.
And you'll notice that everything, all of our draw calls in this case,
the only draw call, printf, is contained within sort of that nestling there
of push:apply start and push:apply end.
Now an important thing to be aware of is we have currently
WINDOW_HEIGHT and WINDOW_WIDTH, but our window
is actually not that size anymore.
Our window is going to be drawn--
it's going to be drawn at 1,280 by 720, but it's
going to be a raster of 432 by 243.
So what we want to do is change this from WINDOW_HEIGHT and WINDOW_WIDTH
to VIRTUAL_HEIGHT and VIRTUAL_WIDTH.
And to do that, I'm going to save it.
I'm going to run the program.
And we do, indeed, see Hello Pong there in the middle of the screen.
Now it looks a little weird.
It looks a little bit blurry because, just as we talked about before,
love is applying filtering to the font.
Now to fix that, we looked at a function that of love.graphics.setDefaultFilter.
So all we need to do to fix this is go up
here and do love.graphics.setDefaultFilter
of nearest and nearest.
I'm going to rerun it.
And we there do see now, hopefully you can see on your screen,
Hello Pong much more crisp.
And now we're running not at 1,280 by 720 in terms of our raster
but 432 by 243, though we do get to use a 1,280 by 720p window.
So that was a low res update that was using push.
And let's go back to our slide deck here.
For pong2 being the next update, we're going
to take a look at actually drawing paddles
on the screen, rectangles on the screen, which will get things looking
a little more visual interesting.
So see you soon for pong2.