Binbows
Binbows

Reputation: 45

How can I make an enemy ram through the player in Godot?

I'd like to make an enemy alternate between charging at the player and shooting at the player.

I can do this by using the move_toward() method and having the enemy stop at the player's position (for a given point in time). However, I think it would be better if the enemy charged past the player's position.

enter image description here

This is the code I've tried for it:

func _physics_process(delta):
    
    if shoot_on==false:
    

        position = position.move_toward(target, delta * speed)
    
    if position==target:
        shoot_on=true
        target = Vector2.ZERO
        $Timer.start()
        launch_proximity()


     func _on_Timer_timeout():
        movement_vector=(Global.player_pos-position).normalized()
    target=1.4*position.distance_to(Global.player_pos)*movement_vector
    shoot_on=false

I've omitted the launch_proximity() function. It just fires a laser at the player.

This code makes the enemy alternate between its starting point and a point between the enemy and the player.

enter image description here

I can't figure out why. Its motion is similar to what it did when I made the target

Global.player_pos-position.

I realised that this describes a point between the enemy and the player. I thought I could fix it with

target=1.4*position.distance_to(Global.player_pos)*movement_vector

but the result is pretty much the same.

I've also tried

target=20*position.distance_to(Global.player_pos)*movement_vector

This will make the enemy charge past the player, but only a short distance. Oddly enough, I get what looks like the same result when I use

target=2000*position.distance_to(Global.player_pos)*movement_vector

Does anyone know what I'm doing wrong? I'd like the enemy to charge further past the player, but altering the coefficient of the target doesn't seem to have an effect.

Upvotes: 1

Views: 340

Answers (1)

Theraot
Theraot

Reputation: 40295

This will be your mantra: REMEMBER THE DIRECTION, FORGET THE TARGET.

This seems to be your direction:

movement_vector=(Global.player_pos-position).normalized()

The line is equivalent to this:

movement_vector = position.direction_to(Global.player_pos)

Note that here position is in local coordinates (coordinates relative to the parent node). I would suggest to work with global coordinates (global_position), and that would be extended to what you set to Global.player_pos wherever you set it. Anyway...

Remember the direction. Make it a script level property. And you do not need to check Global.player_pos again. Forget about the target.

You will move with that direction:

position += movement_vector * speed * delta

Or, again, work with global_position instead of position.

See also How to overshoot with direction_to.


For anybody doing this with a character body:

velocity = movement_vector * speed
move_and_slide()

You would have to work with global coordinates, because move_and_slide works with global coordinates.

People using character body might also be interested in: How to move_and_slide to a target location and stop (which is the opposite problem than this).

Upvotes: 4

Related Questions