Mouse Click Signal?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By ThreeSpark

I am trying to get Godot to recognize when I click on an enemy. How should I go about doing this?

:bust_in_silhouette: Reply From: 2D

I will assume that this is a 2D game and your enemy is a type of Physicsbody2D (rigid or kinetic). If not, I will follow up with another solution.

Physicsbody2D inherits from CollisionObject2D, which has some nifty signals. The one you want for this case is the signal (input_event). You can’t connect this directly to your main or other node because it doesn’t pass the physicsbody (enemy) itself so you won’t be able to determine what was clicked. Instead, connect the signal to a function in the enemy class itself. Go ahead and connect this signal in the editor in your enemy scene. Also, it will throw the signal even if the mouse enters the enemy so you have to check for clicks. Once that is all true, it can call a user defined signal, which calls a function in your main node or some other node where your logic is. Don’t forget to set “pickable” to “on” in the editor for the enemy body.

Inside of your script in your enemy scene:

extends KinematicBody2D

const BUTTONTYPE = "InputEventMouseButton"
const ENEMY_GROUP = "Enemy"

signal ENEMY_CLICKED

func _ready():
	add_to_group(ENEMY_GROUP)

func _on_KinematicBody2D_input_event(viewport, event, shape_idx):
	if event.get_class() == BUTTONTYPE and event.pressed == true:
		#Button index 1 = left, right = 2
		#Click = true button down, false button up
		#print("Mouse Click Down", event.pressed, ", ", event.button_index)
		emit_signal("ENEMY_CLICKED", self, event.button_index)

And inside of whatever node you want to get notification that the enemy was clicked:

extends Node2D

const ENEMY_GROUP = "Enemy"
#Path to enemy scene
const enemy_path = preload("res://enemy.tscn")

func _ready():
	#Make sure this node is above all of the enemies in the scene tree
	#This is for connecting the enemies that are present in the scene at the start of the game
	get_tree().call_group(ENEMY_GROUP, "connect", "ENEMY_CLICKED", self, "enemy_clicked")

func enemy_clicked(enemy, button):
	#Do something with this information
	print("Button ", button, " pressed in ", enemy)

func spawn_enemy(location):
	#This is for enemies that are instanced AFTER the game is started
	var enemy = enemy_path.instance()
	add_child(enemy)
	enemy.connect("ENEMY_CLICKED", self, "enemy_clicked")
	enemy.position = location

In the above code, I am adding the enemy to a group called Enemy. I have this as a constant, which you may want to put in another file that has the constants and stuff for your game. I also have a user defined signal in the enemy class called ENEMY_CLICKED. This signal is connected in the ready function of the node you want to be notified in using the call_group function of the scene tree. This connects the enemies that are in the scene at the start of the game. For enemies that are created after the game starts, you have to connect them in whatever function you use to spawn your enemies.