Welcome To Godot! Let's Make A Platformer!

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
Welcome! Ladies, gents, and everything in-between! You can call me Ken, and THIS is a game-development tutorial! Now this isn't something that I usually do mostly due to the fact that I've never made a tutorial before. (^~^'') But also because it's been quite some time since last I've done anything seriously related to game-development. :'C You see, it was around fifth grade when I realized I wanted to be a game-developer. Seventh grade is when I actually started making that dream into a possibility. I worked on a bunch of small projects and various game engines From Multi Media Fusion and RPG Maker to Game Maker Studio and even a text-based adventure project IN PYTHON. D: Out of the various engines I've used, Game Maker Studio is my FAVOURITE. :D But recently I discovered this gem: The Godot Engine. In this tutorial we will be working with Godot to make a prototype demo of a platformer Platformers are games with a focus on navigating levels made of varying biomes and platforms. Games in this genre include Mario, Sonic The Hedgehog, Tomb Raider, Jak and Daxter, Mega Man, and Castlevania to name a few. Here in the Godot Engine, in the top right we have our nodes. The skeleton of Godot. In the bottom right, we have the inspector which is used for editing nodes. To the bottom left we have our resources, which will contain all our... RESOURCES that we're gonna use in the game such as sprites and scripts and whatnot. Now in the top left we have the file explorer and our paths here in the file system. In the middle here we have the environment. Right here we're working in 2D. but there's also 3D and scripting as well. We're gonna be working with 2D. which basically here, is going to be a highly versatile room-editor. But it also has functionality for other things such as making tilesets, which I won't cover in this tutorial, but I'm gonna work on more tutorials in the future because... I want to get back into this and this is a good excuse. Plus it's material for YouTube content guys (and girls). Hehe >3O Now enough talking about Godot and let's start actually using it. To begin with, we have to have our character. but luckily for you guys, I took some time to cut up some sprites that we can use. These along with the Godot engine can be found in the link below. To import our sprites into Godot, we're going to take it into the Godot project folder. Now let's begin by creating one of those "Nodes" I was talking about earlier. You could click this little plus sign or you could be fast and efficient and push "ctrl + A" (command + a on Mac). Now we're gonna type in "Node". That's not a node (well technically it's Node2D, but that's not the node we are looking for) hehe. There we go, afterwards we're going to push "ctrl + A" again. And search for KinematicBody2D. Make sure you select this one. Cos if you click on that one Then you'll get the 3D one which will obviously only work in 3D. We're going to push (ctrl + A) one more time and type in "AnimatedSprite". Alright, so if you have done it correctly you should see arrows creating a tree-like pattern, like a file tree. which say "Node --> KinematicBody2D --> AnimatedSprite" Now a kinematic body is an object of the game universe that can interact with other objects without necessarily using physics. ... From there... (whoosh). From there we are going to go to the inspector. After clicking on AnimatedSprite, we're gonna go click on sprite frames. We're gonna click New Sprite Frames. So we're gonna rename this default one to "Idle"... With a "D". That simply means that you're not pushing anything, he's just kind of standing there doing his thing. We have this little guy and different animations and we're just gonna drag him over. So despite clicking on AnimatedSprite. We have a static sprite for our first image. Now for me, the sprite looks really crisp, but for others it might not. So what we're gonna do just in case, to be safe. We're gonna hold down "shift" and select and select the first sprite and the last sprite, we're gonna go to Import -> Preset -> 2D Pixel and reimport. This is something that's safe to do in practice before you actually start developing because it makes sure that your pixel art images are nice and crisp. If you're not really working with pixel art and you're doing something that's more render (I might have meant to say "raster") based. It could be beneficial not to do 2D Pixel? but I've always done it because it makes the images look sharper. Now let's create an new animation and call this one "Rise". This will be for when you jump up so you're RISEing. Another one called fall for when you're falling (for me). hehe We'll put that there, and finally th last one will be "Run". "Run" not "Sun". Now you CAN just click and drag one by one very slowly. But if you have animation with lots of frames that's not going to be good for you. So you could click on "run00", hold down shift. And then click on "run07" and drag it all in. The reason why it's called "run07" despite having 6 frames of animation is because computers start by counting with 0 *counts to seven* but that would mean there's EIGHT frames. Well there were two other frames that just didn't look right in the animation so I cut them out. Which is why they're misnumbered. Alright, to preview our animation, what we can do... We can click on this arrow and change the animation to "run". Now... it's just static. BUT if we click "playing"... we can see the animation actually play. Now that looks all nice and dandy but it's REALLY SLOW. So, we're going to speed (fps) and I like to put it at ten. There we go that looks noice. Now let's change it back to idle cos that's just the default pose. *very fake sigh* that was quite a bit of stuff that we went over. But now, that means we can actually start DOING THINGS. Because if you look at this right now... We could drag this over here... and we can hit "F5" to test our game. And we're gonna name this Node "world". And you'll see he stands here but nothing happens. Because we didn't put any programming or code into it. "ctrl+Z" is to undo that action. And now we're gonna make it to he can actually do things. The first step to actually doing things is to create a collision shape. So we're So we're gonna CLICK (I edited it out but I said "kick"). on KinematicBody2D and we're gonna rename it to "Player". Just because we can have other kinematic bodies that aren't related to player control at all and this would make it easier to Identify. and the AnimatedSprite is just gonna be "Sprite" because that makes life much, much easier. However when you are working with multiple sprites for enemies and monsters, it would be smarter to just put "spr_Player" or or "PlayerSprite", but we're just gonna call it "Sprite" for now. now we're gonna click on the player like I said earlier and push "ctrl + A". From there, we're gonna type in "Collision". But we're gonna spell it properly (heh heh). And you're gonna find CollisionShape2D. Remember *2D* not *3D*. And from there we have this little box. What we're gonna do is go to the shape and select "New Rectangle Shape". Now you may or may not have "Snap" turned on. I turned on snap earlier cos I was messing around and it's really good after you have your masks set up. But if you don't have it set up yet then it'd be safe just to turn it it off for a second and adjust the mask before hand. So we're gonna click out and click on the blue. Now we can drag these little dots here and move them up to better suit our character. So we're gonna have it like this and... *jump cut* Alright, now if you don't want to struggle like I did you can just copy whatever the proper coordinates are here. So the position is ".0996773" for "X" and "Y" is "3.132704". and then the rectangle itself has "11.084545" (for "X"). and the "Y" is "28.893131". So you can just type that in instead of having to deal with my struggle. Now we can click on our parent node and we can click here. That way when we move it around we move it around as a unit. Put that back where it belongs. Now let's actually make him do things. This is gonna be done by PROGRAMMING. *GASP* yes, I know it's a very scary word because when you think of "programmer" you think of "master hacker" (or pocket protector nerd). Well programming is actually not as hard as many people make it out to be. Cos we're going to be using GDScript. We're gonna click on the little scroll. And the language here where it says VisualScript, we're gonna turn that off and we're actually gonna turn on GDscript. So GDScript is based off Python with some terminology and inspiration takien from RUST and LUA. The Godot Engine is recently now compatible with C# ant VisualScript is another way to visualize code for those won't be programming at all, like designers. Although the majority of us will be doing design work, coding is a valuable skill that will make you more likely to be hired in anything involving game development. So, logically it's essential for properly understanding what the real CodeMonkeys do so that you can fmphatize with them so as not to burn out your lead programmer and FINALLY, if taught properly and thoroughly coding is actually easy very easy to learn. So this inherits the KinematicBody2D, that just means the type of object not the name we have relating to it. And the path is going to go to "Player.gd" because it's the player node that we are editing. Alriiiight, hehe, so... we are here in the script environment Here it is very similar to other coding IDEs like Notepad++ and Geany. One great feature that's shared with Game Maker Studio and other game development engines is the ability to auto-complete, which is done by selecting the completion with the arrow keys and pushing tab to select it.. Now let's begin with making constants. I'm just going to casually erase all of this because they're comments which are ignored by the computer and are meant for human eyes. Now constants are super useful, unchanging values. that make repeat variables easy to deal with. So you if you have lots of things affected by a variable like Gravity, but you plan on changing the strength of gravity, you can simply edit the constant without having to "ctrl + F" and search all your way through each individual instance of Gravity to change. The first constant will be written as "GRAVITY". So we're gonna type "const" and then we're gonna type "GRAVITY" in all caps. And that is gonna equal 20, because I feel that is a nice, good weight to just get things a nice taste of how they're gonna be. Next constant we're gonna create (not "Coinstant" I'm not from New Jersey). is gonna be "SPEED", this is gonna be the speed of the player character And let's start with 300 just so it's a little slow, but it's gonna show an example as to what's happening. And I'll explain what these mean in a minute. The next constant after that is going to be "JUMP", which is going to be the height of the jump and we're gonna make that 500. The game we're making right now has a very floaty character (think Luigi from Mario). We'll change the gravity back to ten to emphasize just how floaty we're gonna be. It's gonna be kinda silly. (^//~//^) And the last constant we're gonna have is gonna be called "RESISTANCE". That's how you spell "resistance". Are you ready? "Vector2(0, -1)" Okay, now we just made our constant and you're probably thinking, "What the FLUFF is this?" Well, Vector2 is a vector in a 2-dimensional space. It has an "X", which is here by "0" and a "Y" and which is here by "-1". Vector2 is gonna control all movement in the 2D space. "GRAVITY" is gonna be the strength of our gravity vector which is gonna be "10". The constant "SPEED" is the strength of our speed vector which will be "300" and "JUMP" will be "500". Now the reason these numbers are so big is because the gravity is gonna have acceleration, much like gravity in the real world. Whereas in the real world we have 9.8m/s^2, we're gonna have "10". like "+10 per frame". So the first frame will be "10", the next one will be "20", after that will be "30" so on and so forth. Now we're gonna create our first variable which is done by typing in "var". and [var motion = Vector2()]. Now what this code does is it simply means instead of having to create separate variables Say like "var hsp" and "var vsp" for vertical and horizontal speed, we can have both of those in one in one variable which'll make life easier to say the least. Now let's create our first function, so we're going to type in "func" (with a "C" not a "K"). And we're gonna call this "[_physics_process(delta):] That was an example of the auto-complete that I mentioned earlier. I just pushed tab the minute I saw what I wanted. I'm gonna push "enter" and you're gonna see that there's a little arrow with a line, and an arrow up here. As it goes down with an (invisible) right angle, it points you to where you're going. Everytime you hit "tab" an arrow is added. That's because Python and GDScript are based on tabs. Which are special (white) spaces (I believe it's five A tab's it's own block of white space and this is how the code handles everything. In other languages like GML and C++ or C#, you use these braces, so it's possible to write the same function that you have here in multiple lines in just one line, but I prefer this because it makes everything easy to see and easy to understand. And the arrows help keep track of which tab you're on. Alright, the first thing we're gonna do with this [_physics_process(delta):] It simply means that "while the object is existing/while it's still alive." We're gonna go [motion.y += gravity] And this means, "for every step or every frame the object is alive, add ten to the gravity." Or "add '10' to the 'motion.y'". And that gravity is "10" which we could change to "20". And you don't have to change this code again to "20" as well, (cos) it'll just be the same, cos it's a constant. Alright, so that's our first real thing (function, don't know why I said ,"Thing".) o(^~^'o) So if we go and push "f5" which is to test our game Or first let's select "world.tscn" as our starting node. (>~<) You'll see it doesn't do anything! D:< Well, that's because we didn't type in this important phrase... Which is... [_move_and_slide(Vector2,motion)] Alright, let's push "f5". I reversed it (or did I? heh heh heh) (don't listen to anything he says for a few seconds, he's a bad actor). Let's see what our error says. "Error paring expression, misplaced built-in type." So it's not going to be "Vector2" so what's it going to be? Well we have motion... So therefore... I believe it's actually "RESISTANCE" because resistance is the "up". There we go, and our guy fell down! O: You see, I purposefully messed those up So that we can have a debugging experience. See, the reason the "Vector2" wouldn't work is because Vector2 itself is also a function that we're calling. So that has it's own parameters that we have to meet, but we didn't put any. Plus "Vector2" isn't the correct term. The reason why I said "RESISTANCE" is our "up" is because on a game development-graph or (in a) game-development engine our graph here is different from what you have seen in math class. The "X" is still positive to the right, and negative left, but the "Y" is actually flipped so that positive is down and negative is up. The reason why is because gravity in the real world. is the strongest force that we have on Earth. It pushes us down and keeps us on the ground. Whenever we jump we're simply negating the gravity being applied to us but then it always comes back because it overpowers. That's at least MY explanation, although I'm not quite sure if that's the real explanation, but I believe that's why it's so. (^w^ ') We're gonna go back to our [motion.y += GRAVITY] and we're gonna have our first check. Now if you have an *Xbox 360*, or an *Xbox One* controller (this actually might be compatible with some other controllers as well like a *Dual Shock* (Playstation) if you have the proper drivers.) You can actually plug your controller in right now. So, I'm gonna plug my *Xbox One* controller in it's just some generic third party controller I grabbed, nothing special. Let's plug that in. Now we can create our first line of code that will work for keyboard AND gamepad. So we're gonna type an "if statement". Now an "if statement" simply asks the question "if...." And then the return will always be a "Boolean" of some sort, which means "True" or "False". With Boolean logic you could create anything. Because if something isn't or is not something, then it has to be something else. So [if Input.is_action_pressed("ui_right"):] Now "is_action_pressed()" checks "is the action being pressed" (as it says). And "ui_right" is a special, universal/global varable for programming/for player input from the "Input" class. I believe you can actually change this yourself so the values will be different. By default this is the right arrow key, or right on the d-pad. You can change this however using a special key-code for each individual key that Godot will recognize. But right now we're gonna stick with "ui_right" because people know the arrow keys. So we're going to hit "enter" and the first thing we're gonna type is [motion.x = SPEED]. That's simple enough and then we're gonna go [$Sprite.play("Run")] Make sure you get the capitalization correct. If you didn't capitalize it, you made your life easier. But we added some complication because we capitalized it. Now we're just checking to see if that's correct. Let's go back to the script environment. And then here, we're gonna type in right above it because I did it backwards my bad. (u//_//u |||) Bus we're gonna type in [$Sprite.flip_h = false] Now I'm pretty sure that code explains itself, but just in case. This code right here calls upon the "Sprite" node, which is what the "$" means, it means "call this node". So we have this node "Sprite". The "flip_h" flips the sprite image on the horizontal axis. And "play()" just means "play this animation." If we get rid of this gravity script really quick. Uhm... I believe with "#". That will comment it out so the computer won't doesn't read it and we could test just the input without falling down. So the right arrow key mover our guy but... I let go and he kept moving! (=3=)" Now let's finish the rest of that code so it doesn't seem so buggy. We're gonna keep that commented for now because we don't have a block to run on for gravity. We're gonna push enter, then push "shift + tab" to go backwards on the next line. So "tab" goes forward and "shift tab" goes backwards. We're gonna type in [elif Input.is_action_pressed("ui_left")]. And we're just gonna (input) the opposite (values). [motion.x = -SPEED]/[$Sprite.flip_h = True] and finally "$Sprite.play()" is actually gonna be exactly the same. [motion.x = -SPEED] [$Sprite.flip_h = true] [$Sprite.play("Run")] And finally "else". "If this is being pushed, if that's not being pushed but THIS is being pushed, but if NEITHER of them are happening" (which is the else) we're gonna go [motion.x = 0] [$Sprite.play("Idle")]. So let's test that really quick. Moving right... Moving left. On an *Xbox* controller, moving right... moving left... So you're already miles ahead of your colleagues... hehe Unless your colleagues are also watching this video, then you're all on the same pagce. Now what we're gonna do is we're gonna create a block object. Go back to 2D and push "ctrl + A". We're gonna call this one with "Static" to look for "StaticBody2D" And from there we're gonna go "Sprite" just, a regular one. And we're gonna go back to "StaticBody2D" and we're gonna type "CollisionShape2D". Now from there, we're gonna go to We're gonna go to that shape, we're gonna give the sprite of icon.png Which everyone should have by default as part of the regular Godot setup. We'll put that in the texture tab here. Then we're gonna go to "Visibility" and make that all black. Now we have a block! <(^O^)> For the collision shape we're gonna go "New Rectangle". And this one for sure I know is 32x32. And we're gonna lock that parent node. Cool. B) So now we can place that block underneath our character. Let's go back to our script And turn this back on. Let's see what happens. He lands on it. We go left, we go righ- AND HE JUST FALLS LIKE CRAZY WHHAT WAS THAT!? Well that was a bug. And we can fix that very soon by completing the code. Cos this is not all that there is to the code. From there we're gonna have jumping. Which is also PRETTY IMPORTANT if I do say so myself in a platformer. So [if Input.is_action_just_pressed("ui_accept"):] Which will be the spacebar on a keyboard or the "A" button on an *Xbox* controller. From there, we're gonna go [if is_on_floor(): Which asks, "Well, are ya on the floor?" It's gonna say [motion.y = JUMP] [else: if motion.y < 0:] So if you're going upward as I said earlier: gravity is pushing down on us and up is negative. [$Sprite.play("Rise")] That means we're rising. And finally [else: $Sprite.play("Fall")] To explain once more for proper understading, this code means if the button is just pressed, check if you're 'n the floor and play the animation. Whoops, my apologies everyone, this will bring up another bug. Cos if we go here to test it. The animation won't happen if you fall off. You saw we just had the generic running animation. But if we push jump... Nothing happens! There are some reasons why and I'm glad that I caught them. One reason is that THIS is backwards. All of THIS should come first, so we're gonna select it all. And push "ctrl + x" which means "cut". On a Mac, you're gonna push "command + x", because Godot Engine is supportive of Macs. We're gonna "ctrl + V" which is paste. And then we're gonna delete some of this extra stuff. We're gonna "ctrl + X" here. Let's get rid of some unnecessary tabs. That should make a lot more sense now. So the code reads [if is_on_floor(): if Input.is_action_just_pressed("ui_accept"): motion.y = JUMP] [else:] (if you're in the air) [if motion.y < 0:] (so you're rising). [$Sprite.play("Rise")] [else: $Sprite.play("Fall")] So let's test that. And if we fall... WHAT!? We have no animation!? "Well what happened THIS time?" You might ask. Well let's see, so let's make sure our animation names are proper. So we're gonna close that. We're gonna click on our AnimatedSprite. And let's see the names of our animations. Ahhh... It's "Fall-ING" that we have. Now let's just make our lives easier and just call it "Fall" by itself. That way we don't have to change all that code. Now let's see what happens. There we go, we've got a falling animation! Let's see what happens when we jump. Oh no, we can't jump! Well this one was actually on purpose. The last one with the falling was an accident. We couldn't jump because JUMP was positive when it should have been negative. So now that it's negative, it will play the proper jumping animation and it will jump properly because we are not adding to the force that's being pushed down upon us, but we are negating the force. So let's try that again... Look at that! We have a super high jump and we can move left and right (we're a lot like Luigi actually) because we go up... And we go WAY down. You just sink again, why does he keep sinking? That's because we never put a limit on our gravity. So we could go to here with "move_and_slide" and simply change it to [motion = move_and_slide(motion, RESISTANCE")] This means that it won't go any farther that what our motion is equal to. Left, right, jump and down And walking off... We have the same speed now! And actually, you're done! That's it, we just created a platformer. So, I'm gonna stretch this out so we have more to move around with. But, if we watch... We could run around fine and we could jump! Now that is a HUGE jump arc, so it's pretty floaty. Now how would we change that? Like I said earlier in the beginning (practicing Chekov's Gun) We could change the constant "GRAVITY" to equal "30". And SPEED to equal 400. Now watch hat happens. We go a lot faster and have a much shorter jump. And just like that, we made a working platformer in about 30 minutes. Back in the day that wasn't really possible, but here we are today, here we are now. We just did something amazing. I hope my explanation was simple enough to follow easily and that you will be inspired to be more creative and to go down the game-development rabbit hole. As I can promise you this: game-development is both fun and rewarding. Especially when you get into more complicated programs that test your ability. If you liked this video, feel free to drop a like, and if it's not too much of an inconvenience tell me in the comments below what you liked or didn't, and how I can improve. I'll be always reading. Until next time, I'll catch you guys on the flip side. Buh-boiee~ (0ワ0)/)
Info
Channel: Kenneth Stewart
Views: 39,757
Rating: undefined out of 5
Keywords: Game Development, Godot Engine, Tutorial, How To, Platformer, How To Make Games, Make Games
Id: FGF1WMWqq0c
Channel Id: undefined
Length: 30min 26sec (1826 seconds)
Published: Thu Apr 05 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.