How to check if a KinematicBody2D entered the correct Area2D within Node2D

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

Hi guys, basically i have these scene:

  1. Cat | KinematicBody2D
  2. Train Cart | Note2D that contains 3 sprite representing 3 cart with each cart call Cart Area2D scene below
  3. Cart Area2D | Area2D with CollisionShape2D, basically representing the collision area of each cart
  4. Main | 3 Cat, 1 Train Cart

The game goal is to put each Cat to the correct Train Cart based on color with touch screen control. My problem now is that i want to move the Train Cart when each cart already contains the correct Cat. But i can’t seem to found how the Train Cart can detect if each Cart Area2D already contain the correct cart.


My empty code is like this

func _on_Area2D_body_entered(body):
	#if correct cat entered +1
	pass


func _on_Area2D_body_exited(body):
	#if correct cat exited -1
	pass
		
func _process(delta):
	#if all cart contains correct cat, move cart
	pass

I’ve set up color variable in my Cat and i know that i can get the cat color by doing body.color, but how to get the Cart Area2D color that triggers the signal?. Or there’s better way to do this?

Thanks!

:bust_in_silhouette: Reply From: timothybrentwood

I would make your problem a little easier by changing your Train Cart node into a Train node that has 3 Train Cart nodes as children of it. Then in your Train Cart nodes do something like this:

 # Train_Cart.gd
extends Area2D

signal cart_changed

var correct_color = 'blue' # or however you're keeping track of the colors
var has_correct_cat = false

func _ready():
    self.connect("body_entered", self, "_on_Area2D_body_entered")
    self.connect("body_exited", self, "_on_Area2D_body_exited")

func _on_Area2D_body_entered(body):
    if body.color == correct_color:
        has_correct_cat = true
   emit_signal("cart_changed")

func _on_Area2D_body_exited(body):
   has_correct_cat = false
   emit_signal("cart_changed")

Then the rest of the logic is handled in your singular parent Train node:

 # train.gd
extends Node2D # or whatever you think it should be

func _ready():
    for train_cart in get_children():
        train_cart.connect("cart_changed", self, "_on_cart_changed")

func _on_cart_changed():
    for train_cart in get_children():
        if not train_cart.has_correct_cat:
            return # if one cart doesn't have the correct cat just drop out of the function
    # if we got here, all carts have the correct cat
    # so place the logic to move your train here

That clears things up. I somehow doesn’t even have any script on the Train Cart node, so signaling from the Cart nodes to the Train nodes really solve my problem. I made this game for my daughter, me and her both thank you!

edit: after trying this and played around with it turns out this doesn’t work as i intended and produce a funny bug where the train moves without the cat.

gibihakkasy | 2021-08-14 16:23

:bust_in_silhouette: Reply From: Cogan

A simpler way to do it would be to put the cats in a group and get their color, which should probably be a string. then you could do this:

func _on_Area2D_body_entered(body):
    if(_body.is_in_group("cats"):
        if(body.color == correct_color):
            correct_cat = true;

func _on_Area2D_body_exited(body):
    if(_body.is_in_group("cats"):
        if(body.color == correct_color):
            correct_cat = false;
:bust_in_silhouette: Reply From: gibihakkasy

I use the others suggested method with _on_Area2D_body_entered and _on_Area2D_body_exited connection but that result in the train immediately move without waiting the cat to snap to the cart position. Since the signal emitted once the Cat touched the Area2D

After some trial and error i found the best way to do this the way i intended. I create a function in my Cart that can be called by the Cat

extends Area2D

var color = "Pink"
var hasCorrectCat = false
signal cart_changed

func correct_cat_in_cart():
	#when called mark that correct cat in cart
	hasCorrectCat = true
	emit_signal("cart_changed")

In my code i have the cat quickly snap to cart position when the user release their touch control. So i call correct_cat_in_cart()when the user release their touch and this ensure the cat to snap to the cart first before the train moves.