0 votes

I have a cannon (KinematicBody2D) with an Area2D. If the Enemy (also a KinematicBody2D) enters the Area2D or if the Enemy is already in the Area2D, the cannon should rotate in the direction of the enemy.

How can I do that?

Thanks for answers!

in Engine by (330 points)

1 Answer

0 votes
Best answer

Everything I wrote in this answer to another question of you applies here as well. But instead of calling move_and_collide you would now set the rotation like this:

rotation = velocity.angle()

That's assuming your cannon's sprite (or whatever you use to indicate the direction) is facing right by default. Otherwise you'd need to add an offset. Furthermore this will rotate the cannon immediately, which might or might not be what you want.

If you want it to turn around slowly, try this instead:

var difference = abs(rotation - velocity.angle())
if velocity.angle() > rotation:
    rotation += min(difference, 0.01)
else:
    rotation -= min(difference, 0.01)

Here 0.01 is the maximum value (in radians) your cannon will rotate in one frame.

by (10,281 points)
selected by

The problem is, sometimes a Enemy goes into the Area2D and while the canone kills the enemy, the next enemy goes in the area2D. And when the first Enemy dies, the canon doesnt shoot at the secound Enemy.

EDIT: If there are much Enemys the cannon sometimes doesnt rotate at all

I already pointed out to you that there would be issues:

Note that this script has a few issues when there are multiple player characters: The enemy won't follow the character closest to it, but instead the character that entered it's area last. And will stop once a character leaves the area regardless of whether there still are other players in the area.

Instead of keeping track of just one enemy, you could maintain a list:

extends KinematicBody2D

var targets_in_reach = []

func _physics_process(delta):
    if not targets_in_reach.empty():
        var target = targets_in_reach.front()
        # ...

func _on_Area2D_body_entered(body):
    targets_in_reach.append(body)

func _on_Area2D_body_exited(body):
    targets_in_reach.erase(body)

This will always follow the enemy that is inside the area for the longest time. This might or might not what you want, but I hope you get the idea.

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.