SPEAKER: In Mario 1, we looked at how to implement scrolling to our app.
So one of the key features of a side scrolling platforming game
is the ability to scroll our map.
In this example, we're going to take a look at controlling the scrolling.
So previously, it was autoscrolling.
And there are platforming games that are considered autoscrollers,
where you don't actually get to manipulate the camera based
on your movement.
In our game, as we get towards the end, it
is going to be a normal scroller in that it follows an avatar.
But for right now, we're going experiment
with just moving the camera ourselves with the keyboard controls.
And that's really the only explanation I think I'll give for this.
I'm going to go over to my main.lua.
And actually, really, we're not doing anything with main.lua at all.
So I'm just going to run this so we can see what we have.
So currently, it scrolls automatically.
We don't want that behavior.
What I want to do is have this be manual.
So what I'm going to do, I want to clamp the movement
to the width of the map in pixels.
And to do this, I'm going to sort of cache some values
for the size of the map in pixels.
So I'm going to say mapWidthPixels.
And I'm going to set that equal to self.mapWidth times self.tileWidth.
Same thing here.
mapHeightPixels is going to be equal to self.mapHeight times self.tileHeight.
And so this will keep track of the overall pixel size
such that when we're moving our camera, when we're actually moving our camX
and camY here, we can clamp that to be no less than 0, no greater
than the sort of upper bound of those values.
So I'm going to go down to update.
And this is where I want to have this actually happen.
Now, remember we have the love.keyboard.isDown function
to make this possible.
So I'm going to say, if love.keyboard.isDown--
and we'll just use wasd for this.
So w, and then we'll say, elseif love.keyboard.isDown s,
elseif love.keyboard.isDown--
actually, w, we'll do a, s.
And elseif love.keyboard.isDown, d.
Cool.
So here we are basically checking up, left, down, and right for the movement.
So we'll just say up movement, just to keep myself organized here.
Left movement, and this is down movement, and right movement.
What we want to do now is basically do what we're doing down here.
I'm going to copy that.
Moving the camX or camY accordingly.
I'm just going to copy this in each of these,
even though this is currently just moving the camera to the right
by setting the camX going forward, I'm going
to go ahead and set-- so this is up.
So this needs to be camY.
Down needs to be camY well.
So if it is the case that we are pressing up, w, then what I want to do
is say that this should be to negative SCROLL_SPEED if we're going up.
And then if we're going left, then this should be negative SCROLL_SPEED on x.
And then this can be positive scroll speed on y going down
and x going to the right.
Let's go ahead and save this and just test this out.
So if I move to the right, if I'm pressing d, we do indeed move right.
If I press s, we go down.
And it looks like we have a little bit of a bug here.
So let's go ahead and check this out.
I think it's because we are currently not actually setting
the translate to the camY.
Oh, we are setting it to camY, OK.
So we're going to say love to translate math.floor negative camX plus 0.5,
which we are doing floor on.
Let's go over to Map.
And let me just make sure that I'm doing this appropriately.
So self.camY plus dt.
Oh, you know what?
Because I have a bug here.
I forgot to set this to y.
Let's go ahead and make sure both of those are camY.
So let me rerun that, try it again.
I'm moving down, moving up, moving left, moving right.
And everything does seem to be smoother.
OK, perfect.
Now, we haven't taken care of the aspect of actually smoothing out
the movement--
or clamping the movement, I should say--
such that it doesn't go beyond the map edges.
So observe one more time.
If I run this and I move the map, we do have it sort
of allowing us to move left and right.
So we're not going to do that, be on the map edges.
I want it to clamp.
I want it to only show the left edge but not the sort of cut-off point.
And the right edge are flipped.
So what I can do is, remember, we have the math.min
and math.max functions, which will allow us to say, return the greater or lesser
of two numbers accordingly.
So in the example of moving up, we essentially
want to return the greater of 0 and this value, y
being added to negative SCROLL_SPEED, or dt times negative SCROLL_SPEED.
So if we return the greater of 0 and that amount,
it will never get any less than 0.
So we can say math.max of 0 and this number.
I can do the same thing for moving left, actually.
So I can say, math.max of 0 and this.
And this will prevent both on the y and the x going below 0.
And for y, we can return the math.min of the map height of pixels,
so self.mapHeightPixels of that.
And we'll do this for math.min of self.mapWidthPixels.
And actually, what we need to do as well is subtract virtual height.
Because remember, it's relative the top left corner.
So if our camera is [INAUDIBLE] the top left corner
but we allow ourselves to go all the way to the end of the map height
and width in pixels, then we'll end up actually
going all the way past the screen, a whole screen size past the border.
So we want to subtract virtual height and virtual width from that
to account for these screens offset.
So we'll say VIRTUAL_WIDTH in this case.
Run that.
Now if I move the camera, I can't actually move left here.
It's preventing me, which is perfect.
That's the exact behavior I want.
And if I try to move right, this is as far as it will let me go right.
And if I move down, eventually I'm going to hit the bottom of all the brick
walls, which will be more or less the screenshot that we
saw in the prior example.
And if I move up as well, eventually I won't be able to move anymore.
So that's it in terms of getting the ability
to control the movement of the screen.
In the next update, we're going to look at something I think
a little more visually interesting.
We're going to get into procedural generation
with the procgen update, where we actually see how to create something
beyond just a flat sort of grid of bricks,
and start adding columns and spaces and bushes and blocks and clouds
and so on and so forth.
So we'll see you then in Mario 3.