Can I Remake Super Mario World in Godot? (Part 1)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
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.
Info
Channel: wye
Views: 288,621
Rating: undefined out of 5
Keywords: gamedev, indie, devlog, smw, godot, godot engine, unity, super mario world, smw mario, explained, game physics
Id: u2fwxuHZXIA
Channel Id: undefined
Length: 18min 43sec (1123 seconds)
Published: Sun Feb 25 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.