Table of Contents
Introduction
In this post we'll be covering how Godot uses it's core concept of Scene
composition using Nodes
in the SceneTree
for both large and small scenes. With scenes at the core of Godot, you can break your game into smaller reusable components.
These components then become the building blocks for your game. This is at the heart of Object Oriented Programming and once you have your mind wrapped around how it works, the sky is the limit.
Video
You can watch the video covering this topic, or go at your own pace following this post.
Tank Scene
We'll be composing a Tank Scene in this example. Let's first start by creating a new Scene by clicking the new tab icon on the 2D Main Screen or right click in our FileSystem dock under the res://
folder and selecting New > Scene...
Next let's create a Root Node by selecting the + icon in our Scene Dock. We will search and select CharacterBody2D
. This node is a type of Node2D
that inherits from PhysicsBody2D
and also includes behaviour for handling movement and collisions with other objects.
Let's rename our CharacterBody2D
to Tank
as it better describes the scene we are building.
When using any extension of the CollisionObject2D
node, it will warn you if you don't include a Collision Shape (CollisionShape2D
or CollisionPolygon2D
). We can go ahead and add a CollisionShape2D
child node to our Tank, we'll define it's shape
property as a RectangleShape2D
for now and once we've imported and set our sprite texture we can adjust it's shape to better match our needs.
Asset Resources and Organization
Let's take a moment to organize our project a bit further and save our current Tank scene. This will help us stay organized and is a good practice to do early on in a project.
At the root of our project res://
lets create a folder called assets
and another called scenes
. We'll create a subfolder in assets called sprites
and this is where we will store our sprite assets.
Our scenes
folder is where we will save our Scene .tscn
resources and their corresponding .gd
script resources. Now save our current Tank scene into the scenes
folder as tank.tscn
.
We may later decide to create further layers of organization in our folder structure to better represent our project as it grows.
Tank Sprites
Next we will either download the assets from our project's Github repo or create your own tank_body.png
and tank_weapon.png
. These images will imported as Texture
resources to be used as our tanks main body sprite as well as the weapon which we may want to control separately in the future.
Select our root node on our Tank scene and create a new Sprite2D
child node and name it BodySprite
. We'll also create our weapon by first adding Node2D
as a child of our Tank name it Weapon
and then add a child Sprite2D
named WeaponSprite
to our Weapon.
With our BodySprite
node selected we should see in the Inspector Dock the texture property. Let's set this texture to our tank's body sprite we've imported into the assets/sprites folder. You can do this by selecting the dropdown and loading, or drag and drop from our FileSystem dock into the sprites texture field in the Inspector. Repeat this process for the WeaponSprite
.
You'll likely need to move your WeaponSprite
to be aligned with the BodySprite
. For our example we'll also set the pivot point to middle of our weapons attachment area. Select the pivot icon on the 2D Screen's toolbar and click the location on the image that your weapon would rotate around.
AnimationPlayer
Note that if you're using the provided project's tank body sprite, it is a texture atlas and requires that on your Sprite2D
node you also define the Animation's hframe property to 2
to match the number of animation frames we have in our sprite sheet.
With this we can also add an AnimationPlayer
to our Tank root node. With this AnimationPlayer
selected, you can select on the Bottom dock's Animation
tab and we'll create 2 Animations: idle
and move
. To create a new Animation select the Animation
button and select New
and name it idle
.
Select our BodySprite
node and on the Inspector you'll notice a key icon on our properties. This allows us to add a keyframe to our Animation Track. Let's add a keyframe for the Sprite's current frame property. Ensure the beginning of the track is selected and then press the key icon for the frame property. Confirm that we want to create a track for the frame property and leave the RESET track option selected. This tells our Animation player what to do with the frame property when the animation resets.
We should now see the BodySprite
's frame property being tracked on the timeline track for our animation. We'll repeat this process by creating a new animation called move
and adding a keyframe for the frame property again, but this time we will click the key icon a second time and Godot will automatically increment the frame value and insert another keyframe on our timeline in the next step.
The step is defined next to the Animation
button and is defaulted to .1
. We can adjust the the length of our animation by modifying the value next to the stopwatch icon on the right side, this is defaulted to 1
. Next to that is our looping option, where looping is off by default. If we click the loop icon once it'll enable looping, a 2nd click will enable ping ponging, and a 3rd time cycles back to off. For our move
animation we'd like it to be looping, with a duration of .2
and the default step size of .1
.
Branch as Scene
Next we'll cover extracting a branch of our scene and moving it into it's own scene. Our Weapon
node is a great candidate for this, as we may have different behavior and children such as our WeaponSprite
.
Select our Weapon
node and right click and select Save Branch as Scene
and name it weapon.tscn
. This will pull our nodes into their own scene, which you'll note the Scene icon on our Weapon
node. Click the Scene icon to open our new Scene tab and our SceneTree
will only contain the root Weapon
node as well as the WeaponSprite
node child.
We'll do more with our Weapon later on, but for now understand that the process of extracting nodes into their own scene is great for decoupling features when it makes sense and prevents a scene from becoming too large in scope.
Collision Shape
Now that we've got our Tank sprites visible in our editor, we can modify the CollisionShape2D
's sizing to better fit our tank. Select the CollisionShape2D and drag the scale handles to adjust the size to our liking.
We will handle collision logic later on, but for now we will just setup the sizing and ensure it matches our sprite's artwork.
Recap
This is a good start to learning the basics of creating and managing a Nodes in Scene for an object in our game and how those Nodes compose into the SceneTree. We've also learned setting properties in the Inspector and how we can keyframe those properties within an Animation.
Join us next as we add some life into our tank by introducing GDScript
and write some initial code to move our tank around in our world.
Happy Coding.