0 votes

I was wondering a way to make a enemy that "ambushes" the player. Is not a real ambush that make a lot of decisions based on player behavior to proper tricks him, just a AI that follows the player by the back besides the front or global position.

I already have a default enemy that follows player with this basic AI:

extends KinematicBody2D

var ENEMY_1_LIFE = 100
var RAND_SPEED = 0

onready var player = get_parent().get_node("player")
onready var enemy_1_FOV = false

func _ready():
    get_node("fov_enemy_1").add_to_group("fov_enemies")
    get_node("enemy_1_hit").add_to_group("enemy_1_hit")
    RAND_SPEED = randi()%320+100

func _on_fov_enemy_1_body_entered(body):
    if body == player:
        enemy_1_FOV = true
    else:
        null

func _physics_process(delta):
    if enemy_1_FOV == true:
        var vec_to_player = player.global_position - global_position
        vec_to_player = vec_to_player.normalized()
        move_and_collide(vec_to_player * RAND_SPEED * delta)
    else:
        null

func _on_enemy_1_hit_area_entered(area):
    if area.is_in_group("bullet_1_hit_group"):
        ENEMY_1_LIFE -= 50
    else:
        null
    if ENEMY_1_LIFE == 0:
        destroy_enemy_1()

func destroy_enemy_1():
    queue_free()

You can see that enemy follows player with a global position in relation with player. I was wondering if it's possible to adapt this to make enemy following the player by the back when it approachs by certain distance.
I make some sketch to exemplify:

example

thanks guys

in Engine by (170 points)

I make some tests, it's a bit amateur but it works.

I will put here to share, so anybody can test or refine.

1) I put two areas attached to player on a triangular angle:

player area

2) then i re-write the code with two behaviors: first step, when player go to enemy FOV, enemy walks with one of this areas (randi); second when enemy colides with this areas, then the movement changes and he start to follow player by global position; code:

    extends KinematicBody2D

onready var player = get_parent().get_node("player")
onready var player_ambush_1 = get_parent().get_node("player/player_catch1")
onready var player_ambush_2 = get_parent().get_node("player/player_catch2")
var ENEMY_4_LIFE = 150
var RAND_SPEED = 0
var vec_to_player_ambush_1
var vec_to_player_ambush_2
var randi_ambush = 0
var enemy_4_FOV = false
var enemy_4_get_position = false

func _ready():
    global.enemy_4 = self
    get_node("enemy_4_fov").add_to_group("fov_enemies")
    get_node("enemy_4_hit").add_to_group("enemy_4_hit")
    RAND_SPEED = randi()%280+200

func _on_enemy_4_fov_body_entered(body):
    if body == player:
        enemy_4_get_position = true
        randi_ambush = randi()%2+1
    else:
        null

func _physics_process(delta):
    if randi_ambush == 1 and enemy_4_get_position == true:
        vec_to_player_ambush_1 = player_ambush_1.global_position - global_position
        vec_to_player_ambush_1 = vec_to_player_ambush_1.normalized()
        move_and_collide(vec_to_player_ambush_1 * RAND_SPEED * delta)
    if randi_ambush == 2 and enemy_4_get_position == true:
        vec_to_player_ambush_2 = player_ambush_2.global_position - global_position
        vec_to_player_ambush_2 = vec_to_player_ambush_2.normalized()
        move_and_collide(vec_to_player_ambush_2 * RAND_SPEED * delta)
    else:
        null
    if randi_ambush == 1 and enemy_4_get_position == false:
        var vec_to_player = player.global_position - global_position
        vec_to_player = vec_to_player.normalized()
        move_and_collide(vec_to_player * RAND_SPEED * delta)
    if randi_ambush == 2 and enemy_4_get_position == false:
        var vec_to_player = player.global_position - global_position
        vec_to_player = vec_to_player.normalized()
        move_and_collide(vec_to_player * RAND_SPEED * delta)

func _on_enemy_4_area_entered_player_position_area_entered(area):
    if area.is_in_group("player_catches"):
        enemy_4_get_position = false
    else:
        null

func _on_enemy_4_fov_body_exited(body):
    if body == player:
        enemy_4_get_position = true
        randi_ambush = randi()%2+1

    else:
        null

func _on_enemy_4_hit_area_entered(area):
    if area.is_in_group("bullet_1_hit_group"):
        ENEMY_4_LIFE -= 50
        check_enemy_4_life()

    if area.is_in_group("player_hit"):
        enemy_4_get_position = true
        randi_ambush = randi()%2+1
    else:
        null

func check_enemy_4_life():
    if ENEMY_4_LIFE == 0:
        destroy_enemy_4()
    else:
        null

func destroy_enemy_4():
    queue_free()

With this way, the enemy can make something like this:

https://youtu.be/Bgk3GP0Ue_M

I'm still have problems when enemy hit player by the front and get stuck, but is a huge progress.

Please log in or register to answer this question.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.