10.creating-the-pickup

Creating the ice pickup

The player needs a way to use your newly created ice spell and all the ones you will make afterward.

In this guide, you will use the provided pickup classes to create a pickup for your spell.

The principle of this pickup is the same as the pickups you created in the obstacle course series. The code and scene structure is similar, with the pickup being an Area2D node.

But this game has different requirements, so the code isn’t exactly the same.

There are two kinds of pickups in this project demo:

We want the pickups themselves to apply their effect to whatever collects them as we did in the obstacle course series.

In this lesson, we will create one pickup together. We’ll go quickly through the code we’re already familiar with.

Overview of the pickup scene and scripts

Open the Pickup.tscn scene in the pickups/ directory.

The Pickup node is an Area2D with two child sprites and a particle node for the visuals.

There’s also an AudioStreamPlayer2D to play a sound when the player collects the pickup.

Finally, like in the obstacle course, we have an idle animation and an animation that shows the pickup disappearing.

Notice how the animation has a function call track that calls queue_free() on the pickup at the end.

Code-wise, the key difference compared to the obstacle course’s pickup is that we designed the robot so that the Robot node can collect regular pickups and the SpellHolder node can collect spells directly.

Here’s a capture of the Robot scene where you can see both nodes.

The SpellHolder is an Area2D so that we can differentiate when it’s the Robot node that touches a pickup or the SpellHolder.

We distinguish which node interacts with the pickup in the Pickup script using the body_entered and area_entered.

func _ready() -> void:
    connect("body_entered", self, "_on_robot_pickup")
    connect("area_entered", self, "_on_spell_holder_pickup")

Note that we set our Pickup node to have no collision layer and to mask the robot’s layer: layer number 1.

Our two signals are connected to virtual functions. This means that the functions do nothing and that you have to override them in each pickup you’ll design.

Also, we have two functions, one for the Robot, and one for the SpellHolder.

# Virtual function (scripts that extend this class should override this
# function). Called when the Robot touches the pickup.
func _on_robot_pickup(robot: Robot) -> void:
    pass


# Virtual function. Called when the Robot's SpellHolder touches the pickup.
func _on_spell_holder_pickup(holder: SpellHolder) -> void:
    pass

There’s one last important function: the _disable() function.

We use it to turn off physics on the pickup and avoid cases where it could be picked twice while its “destroy” animation plays.

# Call this when someone loots the pickup to prevent it from getting looted
# twice. This is important if you want to play an animation before freeing the
# pickup.
func _disable() -> void:
    # The set_deferred() function waits for the end of the current frame to
    # change the property in quotes to the value passed as the second argument.
    #
    # You need that for some physics properties or Godot will give you an error.
    # Turning off monitoring and monitorable will prevent the area from
    # detecting anything else.
    set_deferred("monitoring", false)
    set_deferred("monitorable", false)
    disconnect("body_entered", self, "_on_robot_pickup")
    disconnect("area_entered", self, "_on_spell_holder_pickup")

That’s the most important part of the Pickup base script.

Next is the SpellPickup script, which is dedicated to pickups that equip spells.

The code is short so here it is in full.

# Gives the player a new spell.
extends Pickup

# This is the spell that will be set on the player's SpellHolder
export var spell_scene: PackedScene


func _on_spell_holder_pickup(holder: SpellHolder) -> void:
    # We use the "set_spell_scene" method to pass our spell_scene to the
    # player's spell holder.
    holder.set_spell_scene(spell_scene)
    _disable()
    _animation_player.play("destroy")

The main feature of this script is that it exports a spell scene. That way, we can assign a different spell to each pickup that we create in the Inspector.

This will be the spell the player gets upon touching the pickup.

We also override the _on_spell_holder_pickup() function to call the SpellHolder.set_spell_scene() function that equips the spell on the player. You can see how this function works by opening the SpellHolder.gd script.

Creating the ice spell pickup

To create a new pickup, all you have to do is create a new inherited scene from Pickup.tscn.

Create an inherited scene, rename the root node to PickupIce, and save the new scene in the pickups/ice_spells/ directory.

Use the images in the directory to change the look of the pickup, of the particles, and the sound it plays.

To change the particles, you have to select the ParticlesSparkle node and change its Textures -> Texture property.

Finally, you want to assign the PickupSpell.gd script to the PickupIce node because, by default, it will inherit Pickup.gd instead.

Then, drag-and-drop the SpellIcePunch.tscn scene you created in the previous part onto the Spell Scene property in the Inspector.

And voila, you have a pickup!

Instantiate it in the test room scene, run it with F6, and walk over the pickup with your character to equip the ice spell.

You can now work on other pickups for each of the spells you created as part of the previous part’s challenges.

In the next lesson, you’ll get to work on mobs.