Let’s recreate Super Mario World, from
scratch, in the Godot game engine! I’m going to reverse-engineer the original
game, and go into ridiculous detail about it, and then, well, forwards-engineer it in Godot! Hi there! I’m wye, and I want to make games! And for my first warmup project, just
to gain some experience with the engine, I’ve decided to recreate the
SNES classic Super Mario World. But why that one, of all games? Why not
start off with a simple game like Pong, or Snake, or a Flappy Bird clone? For one thing, I’m very
familiar with Super Mario World, and I’m more invested in it than in Flappy Bird. And for another thing, I think I
can handle a more complex project, because I do have some grasp
on making playable things! My background is in something called “ROM hacks”. Basically, there are tools
out there that let you edit games and build on top of them to make your own! You can build levels, put in new assets - and, if
you know how to program, do pretty much anything! I’ve spent years making
Super Mario World ROM hacks, and I’ve become very familiar with
the inner workings of the game. It’ll be forever ingrained into my memory what
the tile number of these concrete blocks is, or where the game stores Mario’s powerup state. I know, it’s very impressive, please
try to contain your amazement. But now it’s time to leave behind
my old retro game dev ways, and see if I can do the same in Godot! I won’t be getting all that far in this video,
which is just part one of however many - but I do plan to finish
this project somewhat soon, and have learned a thing or two along the way. So here we go! After creating the project folder,
Godot greets me with an empty screen. This is the scratch from which
Super Mario World will be made! I could start by making the title screen, or the file select, but I kinda want to
build a level! That sounds the most fun. I’m told everything in Godot is a
node, so this level is just a 2D node. And because it’s made out of tiles,
I’m attaching a TileMap node to it. So now it’s time to make some tiles! There are Super Mario World tilesets online
- or I can just make one myself. This is where my Mario hacking
experience comes in really handy. I’m just going to open the level editor, build a
kind of dummy level with all the objects in it, and then screenshot that to get a tileset! There’s already a lot more freedom
here compared to making SNES games. I could use any number of tiles
and as many colors as I like! But of course I’ll be sticking
to the Mario World tileset. The tedious part is defining the collision
for each tile. I’m sure there’s a way to edit multiple tiles at once, and I’ll
be very happy when I figure it out. But now, with all the tiles in place,
and a solid blue color for a background, let’s get to building the level! Again, it’s handy to have the actual Super
Mario World level open for reference. I’m just going to add a camera node and write a quick and dirty script so
I can have a look around. …and also do some fun things that would be really
hard to pull off on the SNES, but easy in Godot. But this world wouldn’t be
very super without Mario in it. So let’s add a player character! I’m going to add a CharacterBody2D node - and save it as
its own scene, because that seems useful. Mario’s collision shape is just a
16x16 box for now. It’s actually more complicated in the original
game, but I’ll come back to it. For Mario’s graphics, I’ve prepared this sprite
sheet here that has the basic frames I need. To make these into animations, I guess
I could use an AnimationPlayer node, but for this very simple case, I think
an AnimatedSprite2D is gonna be fine. After a slightly cumbersome process (because
Godot keeps forgetting the sprite sheet layout), I ended up with these animations: idle, walk, run, jump, fall, fly, duck, look
up, slide, spin, and turn. There are more animations in the original game, and more powerups too, and I’ll
be adding them in the future. But for now, I just want to get a basic
player character up and running - literally. Because now, it’s time for: player physics. I’m not trying to recreate the Mario
World physics down to the pixel, but I do want it to feel like the original game. The CharacterBody comes with
a template script that gives you basic movement - walking around and jumping. But… yeah, this is not gonna cut it. The Mario World physics are really intricate.
There are documents out there listing most of the physics values, and very patient people
have explained the finer points to me, but to really understand the logic,
a lot of times I just had to dive deep into the game’s code and take
cryptic-looking notes along the way. And the adventures from those deep dives I will
now recount to you! First, a lesson on speed. How speed works in SNES
games like Super Mario World To make something move, you change its
position by some amount of pixels each frame. So, the basic unit of speed
is pixels per frame, right? Well, kind of. The SNES doesn't
have any numbers with a “decimal point” - only whole numbers. And
that would be really restrictive for speeds - what if you wanted to
move Mario at 2.25 pixels per frame? What SNES games do is imagine a unit
smaller than a pixel: a subpixel. In Super Mario World, one pixel is 16
subpixels, the SNES’s favorite number. That way, 2.25 pixels becomes a
whole number - 36 subpixels, or $24. This means Mario moves 2 full pixels each frame, and the remaining 4 subpixels
get added to a running total. When that total reaches a full pixel, Mario moves
by an extra pixel. That way, it averages to 2.25! It’s like how leap years work: a
year is about 365 and a quarter days, but we can’t have a quarter of a day,
so we add a full day every four years. Here’s the code from the original
game that does this calculation. So that’s how speed is measured in
Super Mario World - subpixels per frame. You can also think of it as pixels per frame, but with an imaginary decimal
point between the digits. This is known as a fixed-point number. How speed works in modern engines like Godot In Godot, speed is measured in pixels per second. Modern hardware and software lets you work
directly with fractional pixel values - so you can change Mario’s position by
2.718 pixels, and Godot just handles it. But now it’s the time dimension
that’s harder to deal with. On the SNES, one frame is
just about 1/60 of a second. But in Godot, a frame can take more or less
time, depending on how long it takes to process. You don’t know how many frames there are in a second anymore - but you still
apply the speed one time each frame! How can you keep the speed consistent if
you don’t know how often it’s applied? That’s where delta time comes in. Godot gives you a variable, usually called delta, that tells you how long the
last frame took to process. And every time you apply speed,
you multiply it by delta. That way, if frames take longer,
the speed gets applied less often - but it’s a higher speed, because you multiply
it by a larger number! So it evens out! If you want to hear more of the
surprisingly intricate details, Jonas has an excellent video
on delta time and its pitfalls. But right now it’s time to climb out of that
pit, and put all this knowledge to good use! In Super Mario World, Mario’s maximum
walking speed is $14, or 20. That’s 20 subpixels per frame, or 1.25 pixels per
frame, or (at 60 FPS) 75 pixels per second. There we go! …but I still have a long way to go before
this feels anything like the original game. Firstly, Mario actually has
three separate maximum speeds: one for walking, another one for
running (when you hold the run button), and a third one for running
when the P meter is full. The P meter is a kind of gauge that fills up
when Mario is running and depletes when he’s not. When it’s full, Mario’s maximum speed is higher, and he can run even faster -
that’s also known as P speed. (The P meter was actually displayed
on screen in Super Mario Bros. 3, but here, it’s only used behind the scenes.) And secondly, Mario doesn’t
instantly reach his maximum speed when you press a direction on the D pad - and he doesn’t instantly stop when you let go. That’s because the game has acceleration. Just like speed changes position over
time, acceleration changes speed over time - so it takes a short while to build
up speed, and to slow back down again. And when you apply acceleration in Godot,
you have to multiply by delta again! I guess that makes sense, for calculus reasons, and also because you don’t want the
acceleration to depend on the frame rate. Delta is a pretty small number,
and factoring it in twice means the acceleration values end up being
pretty large and not easy to interpret. But that’s no big deal - I just need to
make sure I’m doing the conversion right. So, with all the speeds
and accelerations in place, the results are finally… still not right.
It’s still a bit off from the original. Like I said, Mario’s physics are really intricate. It took me ages to figure out the
logic of when the game does what. With a lot of help from Thomas, probably the world’s leading expert
on Super Mario World physics, I eventually landed on this code. It doesn’t
seem like much, but I’ve agonized over this. Here are just a few fun facts about it: #1: acceleration and deceleration is
different depending on the situation. If you’re holding a direction on the D
pad, Mario slows down quicker than usual, but if Mario is ducking, he takes longer to
slow down, even if you’re holding a direction. #2: if Mario is in the air and
you’re not holding a direction, he doesn’t speed up or slow down at all. That’s why when he shoots out from a pipe, he actually moves faster if
you don’t hold a direction! #3: the game never really caps Mario’s speed at the maximum - it just makes
him slow down if he’s too fast. When Mario is running, his
speed is constantly fluctuating! He briefly goes above the maximum speed, so he slows down, and then he speeds
back up and goes above the maximum again. And on average, that comes out
to exactly the maximum speed. So after implementing all of this in
Godot... yeah! That feels pretty good. Mario’s position is still a few pixels
off in the long run - literally. Either way, I’ll say this is good enough. It
definitely feels like Super Mario World now. I’ll just add some dust clouds when
Mario turns around. That’s an easy thing for a change - I just need to make
it a scene, give it an animated sprite, and add code in the player script to spawn it. And now, we can move on to moving up. Mario’s jump is surprisingly easy to
make! There’s not that much logic to it. When you press the jump button, Mario
moves up. And every frame there’s gravity, which changes his speed over
time, like downwards acceleration. So after jumping, Mario slows down
and then starts falling down again. I remember reading somewhere that
Super Mario World doesn’t actually apply gravity while Mario is jumping up, so
his upwards speed would actually be constant. But as far as I can tell, that’s just not the
case. Maybe I’m misremembering the rumors. But Mario’s gravity can change! While you hold
the jump button, it’s only half as strong. So when you hold the button the whole time, Mario jumps higher and doesn’t
speed up as much when falling. That’s also what lets you run
across these one-tile gaps. And of course, Super Mario World also
has the spin jump, which has pretty much the same logic as the normal one,
except Mario jumps a little less high. When I coded the jump, I noticed
Mario was jumping a little higher in my Godot version than he does in
Super Mario World for some reason. That “some reason” turned out to be: I forgot to
apply gravity to Mario when he’s on the ground. That extra frame of not having gravity
pull on him can make a difference. Mario’s upward speed, and thus his jump height,
actually depends on how fast he’s running. So the faster he runs, the higher he jumps. And technically, there’s not even
a limit to this jump height! It’s only limited by how fast he can
run, and that does have a limit. But if I were to remove that, just
for the heck of it, then… yahoo! Now that we have walking physics and jumping
physics, let’s get to… walking physics. Because you know what I forgot? Slopes. Slopes might be the most annoying
part of platformer physics. They’re not that much of a pain in Godot, because the physics engine
handles collisions well enough - but recreating the exact slope physics of
Super Mario World is a different story. There are four types of slope in the original
game: gradual, normal, steep, and very steep. First of all, how do I even detect when Mario
is on a slope, and what kind of slope it is? After some trial and error I found
the get_floor_normal function, which gives you a vector
pointing away from the surface. If it points straight up, then Mario is
on flat ground - and if it’s at an angle, I can find out what type of slope he’s
on by how much it’s leaning to the side. Trigonometry! Godot actually makes things slow
down when they move uphill - a nice gesture, but I want to have finer control
over the physics here, so I’ll disable that. I’ll also need to set the floor_snap_length, so Mario sticks to the ground a little and
doesn’t overshoot when he walks uphill. Now Mario is walking across the whole terrain at
the same speed, which is a good starting point. Now, what do slopes do to
that speed? A bunch of things: #1: they change Mario’s maximum speed, so
he’s slower uphill and faster downhill. #2: they change Mario’s
acceleration and deceleration, so he speeds up quicker
downhill and slower uphill. #3: Mario can slide on slopes when you press DOWN,
and there’s a separate speed just for sliding. #4: on steep and very steep slopes,
when you let go of the D pad, Mario starts walking down the slope on his own. That auto-walk has its own,
separate, acceleration values. And of course, all these things are
different depending on the type of slope, and also on whether Mario is
walking uphill or downhill, and also whether you’re
holding the run button or not - so I need to check for all those cases. Eventually I gave up giving these numbers
meaningful names, and just hardcoded them all in. I was really struggling with
these very steep slopes, because they’re a special case in many ways. They’re so steep that Mario can’t walk
uphill even if you hold the run button, and they make Mario slide automatically, without you pressing DOWN, and
without showing the sliding animation! That was pretty fun to find out. I’ve had my fair share of
slip-ups - but eventually, I got slopes under more or less control. This is all still far from perfect,
but perfect isn’t my goal here! I want to learn how to use Godot,
and I’ve already learned plenty. And the movement really feels like Super Mario
World now! This seems good enough to move on with. There are so many details I
couldn’t cover in this video. And there’s still so much left to do
here even just for player movement: water physics, climbing, flying, springboards, conveyor belts, more springboards,
Yoshi - not to mention powerups. But I’ll leave that for another time. For now, I’m gonna add some polish to
the level and give it a background. I’ll make a “Background” scene, add a colored
rectangle node for the backdrop color, and also a parallax layer node, because that seems like the easiest way to
make it scroll slower than the foreground. In modern games you would probably
just use an image for the background, but in Super Mario World, the
backgrounds are also made of tiles, so I’m adding a TileMap node and putting
the background together from a tileset. And to round off the jump mechanic, I’ll give Mario an “audio stream player”
node and make it play a jump sound. At this point, I think I’d be
remiss not to mess around a bit. Here’s where engines like Godot really shine: once you have something coded up, you
can just copy it, and now you have two! …or three, or four, or five! But yeah, there we have it! An okay Mario in an okay level - the start of my adventures in recreating
Super Mario World in Godot. In the next video, I’m probably gonna
take a break from Mario physics, and flesh out the world a bit by making
coins, powerups, blocks, and enemies. …or maybe I’ll just add some more Marios. Either way, thank you so much for watching! If you enjoyed this video… you’re a frickin’ nerd.