SPEAKER: In Mario 3, we took a look at procedure generation.
So it's an area of game programming that I particularly am very interested in.
It allows programmers to really take advantage of the CPU's resources
and take away from design time in order to--
if your algorithm is good--
construct a large amount of sort of content assets
that you can use to also regenerate every time you run the game,
and make it a different experience every time.
So games like Minecraft in particular capitalize on this tremendously.
But they have slightly more sophisticated generation algorithms
than we've used.
In this update, we're just going to add an avatar to the screen.
So we're going to add the little a in alien, so a sort of faux Mario
to the scene.
It's not going to be able to move in this update just yet
or really do much of anything.
It's there more for illustration just to mock up
sort of what we have going forward.
But it is a step towards realizing the full sort of vision of the Super Mario
Brothers mockup.
So let's transition over to the code here.
We're going to really store the player inside of the map.
And also, one thing to note too.
In the Graphics folder, I've gone ahead and added the blue_alien.png,
which you'll see in the distro.
We have the spritesheet from before, which is just blocks.
But we have the actual blue_alien.png which has all of its frame data.
So this first frame here is a standing frame.
But then we have things like walking and ducking and climbing a ladder,
jumping, so on and so forth.
So it has quite a few different frames for different use cases,
depending on if you want to go out and explore
some other things with the distro.
But we're just going to use a few of these throughout the track.
So let's go back to Map.
And what I want to do is create a player object.
And when we were doing this before, we created the Player class.
What I'm going to do is I'm going to say self.player is equal to player.
And I'm actually going to pass in self.
I'm going to pass in the map object to the player
so the player has a reference to the map data when we're constructing it.
So this is important.
We're passing in a reference to self, which is
the map itself, going into the player.
So very useful.
Now what we're going to do is, I'm going to go down to the update function.
Now, we're not doing anything with the player
in terms of updating it this iteration.
But we're going to add it just for going forward,
just sort of to proactively anticipate that we're going to need to do so.
We will, in this iteration, need self.player render here
in the Map render function.
Now what I'm going to do is I'm going to create a new file, the player.lua.
And actually, before I finish with that, with Map, I'm going to go up here.
And underneath Util, I'm going to require player just proactively.
Going back to Player.lua, I'm going to say player is equal to class.
I'm going to create a few functions.
So player init, of course, is necessary.
We will eventually need an update function,
though we won't use it in this version of the track.
And then render we will need as well.
So we're going to need a few variables.
So for example, we will need a width and a height.
So I do know that the width is 16 pixels.
The height is 20 pixels, actually so that the character is actually slightly
taller than the tile size of our map.
We're going to initialize it with an x and a y value.
So the x value is just going to be a certain amount of tiles.
So we're going to use tile width in this case.
And we're going to multiply this by 10.
So about 10 tiles to the right is where we're going to place our character.
Because we're multiplying by tile width.
So that's 160 is really what that adds up to.
So 160 pixels to the right.
And in this case, we're going to do map.tileHeight.
And we want the avatar to be just above the halfway point of the map.
So we're going to say tile height times map.mapHeight divided by 2.
So it's halfway down the map.
Minus 1 because it's 0 indexed pixel-wise.
So we're going to have minus 1.
And then further, I need to actually-- because everything, remember, is
relative to its top left corner, I need to subtract self.height
as well so that we're not drawing right where the halfway point starts.
We're drawing 20 pixels above that.
So the avatar can be standing on top of the ground as opposed
to have its head right where the ground is, which looks obviously a little bit
unnatural.
Another thing that we're going to need to do
is define the texture data and the frame data for our Mario avatar.
So I can say self.texture equals love.graphics.newImage where we take
in graphics/blue_alien.png.
And then we can say self.frames is equal to generatequads,
which is the function that we wrote before to splice up our frame
information for the tile sheet.
And I can say self.texture.
And 16 pixels by 20 pixels are the dimensions
for each of the quads in the aliens spreadsheet.
So then I can say in render I want to love.graphics.draw our texture.
I want to draw frames 1-- so that's the very first frame that we split up.
And that's just a standing frame.
And then I want to do self.x and self.y, just like so.
Now, if I run this, it looks like map is a null value for player.
So I'm going to go back over here.
And I forgot to pass that map as an argument
to player init, which is very important.
Don't forget to do that.
Remember, that's the self that we're passing in from the map
when we actually instantiate the player in the maps constructor.
I'm going to go ahead and run this again.
And we do indeed see we have our alien drawn there with a bush beside him.
We've got a couple of gaps there to show our sort of random generation in a way
that we didn't get to see in the last iteration.
So that's it for drawing Mario.
So pretty straightforward.
In Mario 5, we're going to take the next step.
We're going to add the ability to move Mario left or right.
Even though we're not going to have any animation just yet,
we're not going to have collision, we're going to get to all that very soon.
But for now, join me in Mario 5 as we add keyboard input to move Mario.
See you then.