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.
