Tower Defense Tutorial

Creating a Project

Import Asset

Creating a New Level

Animation Player Object

Wave Spawners

Enemies

Ship Enemy

Level 3

Tutorial: Creating Levels and New Enemies

This tutorial will cover the procedures to add a new level to the Tower Defense template. In addition, this tutorial will cover the process of adding a new type of enemy to increase the challenge.

Creating a Project

  1. In the Jump homepage, select the Tower Defense template and fill in the following:

    • Project Name

    • Game Description

    For this tutorial,

    • Set the Project Name as “space harvest adventure”

    • Set the Game Description as "fly through space, collect resources, and beware the space pirates”

  2. Select Open Game Engine. The game engine opens.

Import Asset
  1. In the Project Details Page, import a new asset for the new enemy. You can create your own asset if you wish.

  2. Open the character to check out how to use it.

  3. Check the animations, the character ratio, and overall project. Once you are acquainted with the project, export it to be used in the game, even if the character does not match the theme context.

  4. Once exported, close the Asset Editor and open the game engine in the Jump screen.

  5. The game engine will begin importing the exported asset into the game engine project. Once it is finished you can check its result and start configuring it.

  6. In the Toon Boom Project Panel, double-click on the imported asset to check its result and configure it.

  7. Here is where you can configure the main asset to be used in the game. The main configuration you need is to map the animations to the custom Toon Boom preset animations.

    The main animation you need is the walk animation. Configure it and set it for the left, right, up, and down.

Creating a New Level

The template already has a standard level mechanism.

To create a new level in the FileSystem:

  1. Right click on the level in the File System and select the “new inherited scene” option or press CTRL+D to duplicate it and set a name.

  2. NOTE An inherited scene does not allow you to change the elements of the base scene, while a duplicated scene does. This tutorial will cover work with the duplicated scene.

  3. Name it level3.tscn and place it on the levels folder, the same folder as the other scenes.

NOTE The path is editable as a TileMap. It is the scene node named TileMap you need to edit to change the path.

The scene has two other TileMaps:

  • AStarGrid, used to compute the path the enemies will follow

  • TowerPlacer, stores the information about the towers the user places in the game.

The path configuration and the terrain settings, where the player can and cannot place towers, is configured in the TileMap. The AStarGrid and the TowerPlacer are built automatically from the TileMap.

The level settings in the Tower Defense template are adjusted in level.tscn.

The current level defines if there is a next level.

To set the level we created as a level of the game:

  1. Open level2 and select the root node on the scene tree.

  2. In the Inspector you see the property “Next Level Path”. This is where you must set the level you just created.

    There are two ways to set the next level:

  • Open the Open a File dialog box by double clicking the folder next to Next Level Path in the Inspector

  • Drag the level3.tscn data in the FileSystem tree to the Next Level Path field in the Inspector

Once you have done this, you inform level 2 that it has a next level. The game logic will take care of it.

Animation Player Object

The Tower Defense project takes advantage of Godot’s AnimationPlayer object. The animation mechanism in Godot is very versatile and allows the timed manipulation of every property exposed by Godot API or configured by the developer in a node script. It also allows the timed and synchronized calls of script functions. You can take advantage of this to implement your level.

Select the animation player node labelled EventsPlayer on the scene tree to check the animations configuration.

If the animations are empty, it is because you are still configuring your level. You can check how it was implemented on level 2. Open level 2 and check the animations of that level’s Events Player. To do so, select EventsPlayer in the Scene tab and open the drop down as seen in the image below.

Here there are 12 animations configured and named 01.”event name”.

This animation sets the dialogue panel visible, the text label that will be displayed. It also configures the animation of the displayed text using the label’s visible_ratio property.

The button “got it!” on the dialogue panel is responsible to advance the animation.

NOTE Be aware that the EventsPlayer animation node has its own script to control which animation to play.

The button calls a method of that script. You can check the button signals to understand how it works

Back to the EventsPlayer animations configurations you can see that animations 02 and 03 configurations are very similar to animation 01.

Animation 04 is the one that differs. It calls the function “start round” on the level script.

This function checks if there are still events on the level. If there are, it finishes the round to set up for the next wave. The signal is configured on the game.gd script.

Back on the animations of level 2’s event player, we check the next animation, 05, which configures the first wave.

Wave Spawner

The waves are configured in a separate scene mechanic, configured in the WaveSpawner2D node, defined in the objects folder of the project file system.

The Wave Spawner declares a spawn scene as a property and that is the property we need to set in the animation. But to set it, we need to create it.

The waves are configured in a different scene, with a predefined script. They are in the Waves folder, inside the Levels folder.

Configuring a Wave to Set to the New Level:

You may configure a wave to set to the new level later. First, open level 3.

The Wave node is a clean Path2D node which will be configured in the level script from the AStar paths. The AStar is configured in the _setup function, relating the TileMap and the AStarGrid.

The Path2D property in the Inspector sets the interval between the enemies. The Path2D wave script has its own script to control how and when the enemies in the wave will be spawned.

Enemies

Each enemy is a scene itself. The enemies are declared in the Actors folder of the project structure. Let's open the simple enemy to check it out.

The Enemy object root is a node of type PathFollow2D. This differs from the base .tbg asset node, which is derived from CharacterBody2D.

This means that this kind of node has a different behaviour from the .tbg imported asset, but this is not a problem. The .tbg asset can be used as a child of this node and configure the behaviour in the script, which is what happens with Perry Poireau in this case.

On the Inspector, there are properties for the enemy. If you open the tough enemy, you will see that it shares everything the enemy has, but has different values in the properties.

Ship Enemy

Create a new scene in the Enemies folder and name it ShipEnemy.

You can do this by creating a new node, copying and setting the data from the base enemy, or by duplicating the base enemy scene and working from that copy.

You can duplicate the scene by selecting it on the engine FileSystem panel and hitting Ctrl + D. Now you can name it ShipEnemy and all the base configuration is set, including the scene behaviour script.

NOTE There are several other scenes as children nodes of the enemy. They are not covered in this tutorial.

Now, add our asset to the scene and adjust its size.

Finally you need to set the script to the scene. You can create a new script derived from the enemy.gd or you an use the same script.

You can use the same and adjust some information. To do this:

  1. Select the root node and go to the Script property on the Inspector panel.

  2. Then, drag and drop the script on the Property.

  3. Go back to the top properties in the Inspector panel and check the properties set.

NOTE If you use the ShipEnemy in a wave you will get an error.
NOTE Checking the script we can see that on line 18 it looks for a property named PerryPoireau, but no such property is present in our scene. That was the tbg property for the enemy scene. An easy fix is just to rename the tbg asset we added to the scene as PerryPoireau. Let's do this.

You can set up the enemy properties as you wish. The asset animations for Walk/Up, Walk_Down, Walk_Left, and Walk_Right are already configured, so we can go back to create a new wave.

Level 3

Back on the levels\waves folder, create the waves for the level 3.

Creating a wave is a simple process of creating a scene with a Path2D as the root node, assigning the wave script to it, and add the enemies.

Add a simple enemy, two tough enemies and a ship enemy, and you can be done.

Now you can set up the level. Add a simple text as configured in the first animation of level 2.

After the texts you will need to call the routine to start the round so that the player can set up the towers. This is configured in an animation as well.

Now the wave configuration in another animation. Let’s configure just one animation. If in doubt, check how it is done on level 2, but we need to set up which wave will be configured on the Wave Spawner and call the routine to spawn the wave.

Add an ending text to finish this level and then the ending event calling the finish routine.

Now it is time to run the game and check if the level is working.

Note that there may be something off with the last enemy. You will need to check it out on the wave and on the enemy scene.

On the wave you may see that the properties Rotates and Loop are set to On in PathFollow2D. They are not set on the other enemies.

Setting it on the enemy scene will update it for each and every wave this enemy is being used. If set on the wave it will change only on that wave.

Also, the enemy is not receiving hits. Do the same process and check the other enemy configurations.

As expected, the area responsible to process the hits are not connected to the code that applies it. To solve this, connect the node’s signal to the code that deals with it.

Run it again and check it out.

You should have a new enemy and level created.