How to chase a player in Godot

When I was working on my first game project, I decided to introduce different types of enemies. For example, simple guardians will patrol their area and can attack the player only when he is near. More complex samurais will not only see the player, but also can chase him. This is a common task in game development. In this short case study I want to demonstrate you how I created such character in Godot.

Create an enemy object

The samurai inherits the KinematicBody2D class, which means, that it is not controlled by engine’s physics, but is controlled by the developer (in our case by code). When the samurai detects the player nearby, it will move into its direction. There are two important things I want to mention here:

  1. What does that mean “near”? How the samurai can “see” the player?
  2. The “Masks of Edo” is a platformer game, so we need to move the samurai only in a single direction by X-axis

Let start with the structure of the entity. Take a look on the screenshot below:

Here I have an Area2D object that plays a role of the detection box. Once the player enters this zone, the samurai will start to chase him. I also have an another zone to attack the player, but we will not cover it in this post. The principle is however the same. Let start with the first point – how the samurai will detect the ninja.

Make an enemy see the player

The most common pattern that I found is to create a detection box, and once the player enters it, the enemy will follow the player. There is some specific stuff for “Masks of Edo”. First, there is an invisible mode, so once the ninja is invisible, the samurai will not follow him, even the ninja overlaps the detection area. Second, I want to know where does the player stand relating to the samurai – on the left or on the right, so I could to flip the sprite accordingly.

Let start by registering two signal listeners for the DetectionBox entity:

  • body_entered() is fired once the body will enter the area. Don’t forget to configure collision layers, so only the player entity would call this method
  • body_exited() indictes that the player left the area, so the samurai stops to chase him

The next step is to implement these methods. Please note, that I use GDScript here. I also defined a class variable player which indicates the player instance:

var player = null

func _on_DetectionBox_body_entered(body):
    if body.has_method('get_invisible'):
        is_player_invisible = body.get_invisible()
        if not is_player_invisible:
            player = body


func _on_DetectionBox_body_exited(body):
    player = null

The code snippet is self-explanatory. Once the body enters the detection area, we call its get_invisible() method in order to verify that the player is not in invisible mode (I use the precaution has_method maybe due to my past in strong typed languages, yet it is not necessary). Once the ninja leaves the detection box area, we set the player value to null.

The next question I want to tackle is how to rotate the samurai based on the player’s position. Because, the ninja also extends the KinematicBody2D class, we can obtain its position by calling the respected property. I wrote a simple method to do so:

var is_left_oriented = false

func check_if_player_is_on_the_left():
    if player:
        var player_position = player.position
        is_left_oriented = player_position.x < position.x
    else:
        is_left_oriented = false

Follow your nose!

Now, the samurai will see the player but he also need to move towards the ninja. This logic lives inside the _physics_process loop. Basically, we go here through following steps:

  1. Check if player is detected (e.g. not null)
  2. Check that player is visible
  3. Verify the position of the player
  4. If the player is on the left – we move into negative direction
  5. If the player is on the right – we move into positive direction

This is how it can be defined. But, what do these directions mean? Let me explain. From the technical point of view, positions in Godot are vectors (e.g. 2D pairs). The motion direction of the player can be described as the difference with the player multiplied by the speed. Godot has a helper method direction_to which simplifies our life a lot. All what we need to do is:

var direction = motion.direction_to(player.position) * SPEED

But be careful! This value is the vector, but we need to move the enemy only by single axis. That means, that we write only motion.x value, but the motion.y is 0.

The complete implementation is below:

func _physics_process(delta):
    var motion = Vector2.ZERO
    if player:
        is_player_invisible = player.get_invisible()
        if not is_player_invisible:
            check_if_player_is_on_the_left()
            if not is_left_oriented:
                var direction = motion.direction_to(player.position) * SPEED
                motion.x = direction.x
                motion.y = 0
                AnimationSprite.flip_h = false
                AnimationSprite.animation = "walk"
            else:
                var direction = motion.direction_to(player.position) * SPEED
                motion.x = -(direction.x)
                motion.y = 0
                AnimationSprite.flip_h = true
                AnimationSprite.animation = "walk"
        else:
            motion = Vector2.ZERO
            AnimationSprite.animation = "idle"
    else:
        motion = Vector2.ZERO
        AnimationSprite.animation = "idle"
    move_and_slide(motion)

This code makes the samurai to chase the ninja. The result looks like this:

I hope that this post helped you at least a bit! If you’re interested in more content about Godot and game programming, don’t hesitate to follow me in social networks.

admin Written by: