In this lesson, we’ll extend the Pickup scene to create and test our ghost pickup.
Like before, we will use inheritance and have all pickups extend a base scene and script.
Unlike the turret, this script will be tiny. It will only do one thing: when it detects the player, it will remove itself, and apply its effect to the player.
This script will guarantee that all pickups work the same code-wise.
Reopen the Pickup scene and attach a new script named
Pickup.gd
to it.
We know every pickup type will have an effect, but we don’t know all
the effects we’ll need yet. We define a function named
apply_effect()
with an empty body. We’ll override it in
each pickup to apply the pickup’s effect to the character.
# Virtual function. Applies this pickup's effect on the body node.
func apply_effect(body: Node) -> void:
pass
This is something we call a virtual function. It’s a function that does nothing until you override it. That’s why we call it “virtual.”
It ensures that the apply_effect()
function exists in
all pickups and prevents errors.
You have already used some virtual functions from Godot, such as
_ready()
and _process()
. Until you override
them in your scripts, these functions exist in the engine but do
nothing.
All pickups share a common functionality: when the player touches it, we should destroy the pickup and apply its effect on the player.
onready var animation_player := $AnimationPlayer
func _ready() -> void:
connect("body_entered", self, "_on_body_entered")
func _on_body_entered(body: Node) -> void:
play("destroy")
animation_player.apply_effect(body)
The destroy animation calls the queue_free()
function at
the end, so playing it will remove the pickup from the level.
At this stage, we already have a working pickup. If we place it in a
level and the player touches it, the pickup will get destroyed and call
its apply_effect()
function.
But since we added the ghost code to the Godot script, we might as well create the ghost pickup before testing.
To create our ghost pickup, we start by creating an inherited scene.
In the FileSystem dock, right-click on the
ObstacleCourse_Part2/pickup/Pickup.tscn
file and select
New Inherited Scene.
Rename the scene’s root node to PickupGhost and save it in
the pickups/
folder.
Then, right-click on the PickupGhost node and click Attach Script to attach a new script to it.
First, we need to extend the Pickup.gd
script we just
coded.
extends "Pickup.gd"
Next, we override the apply_effect()
function from the
Pickup base script by declaring a function with the same name
and parameters.
This function override takes priority over the virtual function in
Pickup.gd
.
func apply_effect(body: Node) -> void:
# We turn on the ghost effect on the character when it touches the pickup.
toggle_ghost_effect(true) body.
That’s it! All we need to do is call
body.toggle_ghost_effect()
on the player.
We can make a temporary 2D scene with a ObstacleCourse2/
directory to test that the ghost effect gets applied to the player.
Create a new 2D scene. In the FileSystem dock, select the rocks, the Godot character, and the PickupGhost scene files.
You can find the rocks in the obstacles/rocks/
sub-directory.
Drag and drop them into the viewport to instantiate them. Then, spread them around to test the ghost effect.
Play the scene and try to run into the rocks. They should block the character.
Then, walk over the pickup and then over the rocks. The characters should now walk through them.
In the next lesson, we’ll create our second pickup type, the speed boost pickup.
Open the practice Increasing the gem counter.
This practice will bring you back to detecting collisions and interactions with the
node.Here’s the complete code for the files we coded in this lesson.
Pickup.gd
extends Area2D
onready var animation_player := $AnimationPlayer
func _ready() -> void:
connect("body_entered", self, "_on_body_entered")
func _on_body_entered(body: Node) -> void:
play("destroy")
animation_player.apply_effect(body)
# Virtual function. Applies this pickup's effect on the body node.
func apply_effect(body: Node) -> void:
pass
PickupGhost.gd
extends "Pickup.gd"
func apply_effect(body: Node) -> void:
# We turn on the ghost effect on the character when it touches the pickup.
toggle_ghost_effect(true) body.